No.007 - 08 拡大縮小コピー |
拡大縮小コピーです。 直線描画のとき同様 bresenham(ブレゼンハム)の 方法を使って処理を行います |
・拡大縮小ルーチンの基本 |
|||||||||||||||||||||||||||
拡大縮小コピーの基本となるルーチンはこちらです。遅いですよ。
コピー先とコピー元のサイズが違っても要は、コピー先の範囲が全部埋まりゃあいいので、 コピー先のサイズを基軸にループを作ります。 ix_start は ”X座標側のループは、ix_start 進んだ状態でスタ−トしますよ”という意味 です。 描画範囲が画像の外まで広がってる時の補正用です。(初期XY座標自体を補正してしまうと、倍率が変化してしまうので) iy_start も同様です。 |
|||||||||||||||||||||||||||
・Bresenham で拡大縮小ルーチン(メインループ部分) |
|||||||||||||||||||||||||||
これをY座標側にも適用したのがこちらのコードです。 "X座標の e" → e_x 、"Y座標の e" → e_y に名前を分けました
以上でメインルーチン部分は完成です。 |
|||||||||||||||||||||||||||
・範囲補正を行う前に |
|||||||||||||||||||||||||||
引数の保持についてです。 指定されたコピーサイズは保持しておかなければなりません。 範囲補正を行うとき、拡大・縮小の倍率を変えてしまわないようにです。 倍率を小数値で保持すれば当然誤差がでるので、しかたなく分母と分子を保持する意味で元の引数のサイズを使います。 画像よりハミでた部分は映らない分でも縦横が歪んだらやだなぁと思うので。 |
|||||||||||||||||||||||||||
・拡大縮小での範囲補正1 (コピー先の範囲をチェック) |
|||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||
・拡大縮小での範囲補正2 (初期値がコピー元の範囲内にあるかをチェック) |
|||||||||||||||||||||||||||
次にコピー元側の座標が画像の外にハミでていないかチェックします。 コピー元のX座標の初期値は nx = src_x+ix_start*src_cx/abs_dst_cx; です。 これは普通の数学でやってもこの式がでますが、いまひとつ直感的でないので いっちょ試しに 上記Bresenhamを使ったメインループのルーチ ンから考えて見ます。
|
|||||||||||||||||||||||||||
さて nx = src_x+ix_start*src_cx/abs(dst_cx); という初期値がコピー元の画像の外にハミでているかどうかで、 ハミでているときどう処理するかが問題でした。 src_cxがマイナス値のとき鏡面コピーになります。 if (nx<0 || nx>=p_src_img->m_width){ if (src_cx>0){ if (nx<0) src_start = -src_x; if (nx>=p_src_img->m_width) return -1; } else{ if (nx<0) return -1; if (nx>=p_src_img->m_width) src_start = src_x - p_src_img->m_width; } ix_start = src_start*abs(dst_cx)/src_cx; if (src_start*abs(dst_cx)%src_cx) ix_start++; } とまあ数学的にはこんな感じですが、またいまひとつ直感的でないので。 もういっちょ試しに上記Bresenhamを使ったメインループの ルーチンから考えて見ます。
これをY座標側にも適用すれば初期値OKです。 |
|||||||||||||||||||||||||||
・拡大縮小での範囲補正3 (終了値がコピー元の範囲内にあるかをチェック) |
|||||||||||||||||||||||||||
さて今度は終了値です。 tx = src_x+(ix_end-1)*src_cx/abs(dst_cx); という値がコピー元の画像の外にハミでているかどうかです。
上述の初期値の補正と式そっくりですが、敢えて一つにしたりしません。 分けてあるほうが、分かりやすく演算も速いからです。 |
|||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||
下記サンプルソースは6つのファイルから成っています ピクセル反復子や、パレット(色テーブル)クラスを定義するヘッダの gt_img_parts.h と、 定数を定義している resource_08.h 、 画像クラスを定義している gt_img_08.h、 リソーススクリプトの gt_img_08.rc、 BMPファイルを読み書きするgt_img_bmp_io.cpp 、 メインファイルの gt_img_08.cpp です。
|
|||||||||||||||||||||||||||
・選択範囲を表示するのにPatBltとリージョンで矩形枠描画しています ・今回クリップボードには転送していないので他のアプリケーションに貼り付けできません。 |
|||||||||||||||||||||||||||
画像1と画像2にファイルを読み込んで下さい。 その後マウスでドラッグして 選択範囲を決めて、 右クリックメニューからコピーします そして今度は描画する範囲を決めて 貼り付けたいところに、右クリックメニューから貼り付けします |
1. 最初の画面です。 |
|
2. 画像1と画像2にファイルを読み込んで下さい。 |
|
3. コピー範囲を指定してから、 右クリックでコピーしてください (クリップボードにはコピーしていないので 他のアプリケーションに貼り付けはできません) |
|
4. 貼り付け範囲を指定してから、 右クリックで貼り付けしてください |
|
5. できました。 以上の順序を間違えるとコピーできません。 |
|
参考: メニューから拡大縮小コピーの 透明度も指定できます。 拡大縮小・半透明コピーも可能です。 |
resource_08.h |
// 拡大縮小コピー #define IDM_MAKE_DIB_0 1000 #define IDM_MAKE_DIB_1 1001 #define IDM_MAKE_DIB_4 1004 #define IDM_MAKE_DIB_8 1008 #define IDM_MAKE_DIB_16 1016 #define IDM_MAKE_DIB_24 1024 #define IDM_MAKE_DIB_32 1032 #define IDM_LOAD_DIB 2001 #define IDM_SAVE_DIB 2002 #define IDM_OPEN 2003 #define IDM_OPEN2 2004 #define IDM_COL 3000 #define IDM_COPY 3001 #define IDM_PASTE 3002 #define IDM_FILL 3003 #define IDM_ALPHA_100 4100 #define IDM_ALPHA_90 4090 #define IDM_ALPHA_80 4080 #define IDM_ALPHA_70 4070 #define IDM_ALPHA_60 4060 #define IDM_ALPHA_50 4050 #define IDM_ALPHA_40 4040 #define IDM_ALPHA_30 4030 #define IDM_ALPHA_20 4020 #define IDM_ALPHA_10 4010 #define IDM_ALPHA_0 4000 |
gt_img_08.rc |
// 拡大縮小コピー #include "resource_08.h" //リソーススクリプト GT_DIB_MENU MENU { POPUP "ファイル" { POPUP "作成" { MENUITEM "1 bit" , IDM_MAKE_DIB_1 MENUITEM "4 bit" , IDM_MAKE_DIB_4 MENUITEM "8 bit" , IDM_MAKE_DIB_8 MENUITEM "16 bit", IDM_MAKE_DIB_16 MENUITEM "24 bit", IDM_MAKE_DIB_24 MENUITEM "32 bit", IDM_MAKE_DIB_32 } MENUITEM "画像1にひらく", IDM_OPEN MENUITEM "画像2にひらく", IDM_OPEN2 MENUITEM "保存", IDM_SAVE_DIB } POPUP "透明度" { MENUITEM "不透明", IDM_ALPHA_100 MENUITEM "90%", IDM_ALPHA_90 MENUITEM "80%", IDM_ALPHA_80 MENUITEM "70%", IDM_ALPHA_70 MENUITEM "60%", IDM_ALPHA_60 MENUITEM "50%", IDM_ALPHA_50 MENUITEM "40%", IDM_ALPHA_40 MENUITEM "30%", IDM_ALPHA_30 MENUITEM "20%", IDM_ALPHA_20 MENUITEM "10%", IDM_ALPHA_10 MENUITEM "0%", IDM_ALPHA_0 } } //リソーススクリプト GT_DIB_MENU_R MENU { POPUP "右クリックメニュー" { MENUITEM "コピー", IDM_COPY MENUITEM SEPARATOR MENUITEM "貼り付け", IDM_PASTE } } |
gt_img_08.h |
// 拡大縮小コピー #include <stdio.h> #include <windows.h> #include "resource_08.h" #include "gt_img_parts.h" // ======== GT_IMG ================================== class GT_IMG { public : GT_COL_TABLE m_col_table; unsigned long *m_col_mask; char *m_alpha; int m_width, m_height, m_byte_width, m_bit_count; BYTE *m_pbits; GT_IMG(); virtual ~GT_IMG(); // 作成と破棄 virtual destroy(); virtual create(int cx, int cy, int a_bit_count, int a_color_size=0); // ピクセル描画 set_pixel(int x, int y, DWORD col); DWORD get_pixel(int x, int y); // アルファ値 is_alpha(){ return (m_alpha!=NULL); } // 半透明用フラグ定数 enum { ID_BLEND=0, ID_NOBLEND=1 }; // 矩形塗りつぶし fill(int x, int y, int cx, int cy, BYTE r, BYTE g, BYTE b, int rate=255, int flag=ID_BLEND); template <int d_bit> void fill_pixput(int x, int y, int cx, int cy, BYTE r, BYTE g, BYTE b, int rate, int flag); // 矩形コピー from_draw(int x, int y, int cx, int cy, GT_IMG *p_img, int src_x, int src_y, int rate=255, int flag=ID_BLEND); template <int dst_bit, int src_bit> from_draw_set_alpha(int dst_x, int dst_y, int cx, int cy, GT_IMG *p_img, int src_x, int src_y, int rate, int flag); template <int dst_bit, int dst_alpha, int src_bit, int src_alpha> from_draw_pixput(int dst_x, int dst_y, int cx, int cy, GT_IMG *p_img, int src_x, int src_y, int rate, int flag); to_draw(int x, int y, int cx, int cy, GT_IMG *p_img, int src_x, int src_y, int rate=255, int flag=ID_BLEND); // 拡大縮小コピー from_elastic_draw(int d_x, int d_y, int d_cx, int d_cy, GT_IMG *p_img, int s_x, int s_y, int s_cx, int s_cy, int rate=255, int flag=ID_BLEND); template <int dst_bit, int src_bit> from_elastic_draw_set_alpha(int d_x, int d_y, int d_cx, int d_cy, GT_IMG *p_img, int s_x, int s_y, int s_cx, int s_cy, int rate, int flag); template <int dst_bit, int dst_alpha, int src_bit, int src_alpha> from_elastic_draw_pixput(int d_x, int d_y, int d_cx, int d_cy, GT_IMG *p_img, int s_x, int s_y, int s_cx, int s_cy, int rate, int flag); adjust_elastic_draw(int &ix_start, int &iy_start, int &ix_end, int &iy_end, int dst_x, int dst_y, int dst_cx, int dst_cy, GT_IMG *p_img, int src_x, int src_y, int src_cx, int src_cy); // カラー set_col_mask(UINT r, UINT g, UINT b); set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b); // 読込 load_dib(char *filename); load_dib_rle4(HANDLE hfile); // 4bit ランレングス圧縮 load_dib_rle8(HANDLE hfile); // 8bit ランレングス圧縮 // 書込み save_dib(char *filename, int rle_compress_flag=0); save_dib_rle4(HANDLE hfile); // 4bit ランレングス圧縮 save_dib_rle8(HANDLE hfile); // 8bit ランレングス圧縮 }; //========================================== // 拡大縮小コピー //========================================== // 拡大縮小コピー GT_IMG::from_elastic_draw(int d_x, int d_y, int d_cx, int d_cy, GT_IMG *p_img, int s_x, int s_y, int s_cx, int s_cy, int rate, int flag){ if (!p_img) return -1; if (!p_img->m_pbits || !m_pbits) return -1; if (rate<0) rate=0; if (rate>=255) rate=255; switch(m_bit_count){ case 1: switch(p_img->m_bit_count){ case 1: from_elastic_draw_set_alpha<1 , 1 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 4: from_elastic_draw_set_alpha<1 , 4 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 8: from_elastic_draw_set_alpha<1 , 8 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 16: from_elastic_draw_set_alpha<1 , 16>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 24: from_elastic_draw_set_alpha<1 , 24>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 32: from_elastic_draw_set_alpha<1 , 32>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; } break; case 4: switch(p_img->m_bit_count){ case 1: from_elastic_draw_set_alpha<4 , 1 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 4: from_elastic_draw_set_alpha<4 , 4 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 8: from_elastic_draw_set_alpha<4 , 8 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 16: from_elastic_draw_set_alpha<4 , 16>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 24: from_elastic_draw_set_alpha<4 , 24>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 32: from_elastic_draw_set_alpha<4 , 32>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; } break; case 8: switch(p_img->m_bit_count){ case 1: from_elastic_draw_set_alpha<8 , 1 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 4: from_elastic_draw_set_alpha<8 , 4 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 8: from_elastic_draw_set_alpha<8 , 8 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 16: from_elastic_draw_set_alpha<8 , 16>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 24: from_elastic_draw_set_alpha<8 , 24>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 32: from_elastic_draw_set_alpha<8 , 32>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; } break; case 16: switch(p_img->m_bit_count){ case 1: from_elastic_draw_set_alpha<16, 1 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 4: from_elastic_draw_set_alpha<16, 4 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 8: from_elastic_draw_set_alpha<16, 8 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 16: from_elastic_draw_set_alpha<16, 16>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 24: from_elastic_draw_set_alpha<16, 24>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 32: from_elastic_draw_set_alpha<16, 32>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; } break; case 24: switch(p_img->m_bit_count){ case 1: from_elastic_draw_set_alpha<24, 1 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 4: from_elastic_draw_set_alpha<24, 4 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 8: from_elastic_draw_set_alpha<24, 8 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 16: from_elastic_draw_set_alpha<24, 16>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 24: from_elastic_draw_set_alpha<24, 24>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 32: from_elastic_draw_set_alpha<24, 32>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; } break; case 32: switch(p_img->m_bit_count){ case 1: from_elastic_draw_set_alpha<32, 1 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 4: from_elastic_draw_set_alpha<32, 4 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 8: from_elastic_draw_set_alpha<32, 8 >(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 16: from_elastic_draw_set_alpha<32, 16>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 24: from_elastic_draw_set_alpha<32, 24>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; case 32: from_elastic_draw_set_alpha<32, 32>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); break; } break; } return 0; } // 拡大縮小コピー(アルファ値設定) template <int dst_bit, int src_bit> GT_IMG::from_elastic_draw_set_alpha(int d_x, int d_y, int d_cx, int d_cy, GT_IMG *p_img, int s_x, int s_y, int s_cx, int s_cy, int rate, int flag){ if (is_alpha()){ if (p_img->is_alpha()) from_elastic_draw_pixput<dst_bit, 1, src_bit, 1>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); else from_elastic_draw_pixput<dst_bit, 1, src_bit, 0>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); } else { if (p_img->is_alpha()) from_elastic_draw_pixput<dst_bit, 0, src_bit, 1>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); else from_elastic_draw_pixput<dst_bit, 0, src_bit, 0>(d_x, d_y, d_cx, d_cy, p_img, s_x, s_y, s_cx, s_cy, rate, flag); } } // 拡大縮小コピー位置補正 GT_IMG::adjust_elastic_draw(int &ix_start, int &iy_start, int &ix_end, int &iy_end, int dst_x, int dst_y, int dst_cx, int dst_cy, GT_IMG *p_img, int src_x, int src_y, int src_cx, int src_cy){ int co, tmp; //コピー先補正 if (dst_x<0) ix_start=-dst_x; else if (dst_x>m_width) ix_start=dst_x-(m_width-1); if (dst_y<0) iy_start=-dst_y; else if (dst_y>m_height) iy_start=dst_y-(m_height-1); if ((dst_x+dst_cx)<0) ix_end=dst_x+1; else if ((dst_x+dst_cx)>m_width) ix_end=m_width-dst_x; if ((dst_y+dst_cy)<0) iy_end=dst_y+1; else if ((dst_y+dst_cy)>m_height) iy_end=m_height-dst_y; //コピー元補正 int abs_dst_cx = abs(dst_cx); int abs_dst_cy = abs(dst_cy); // ix_start 補正 co=src_x+ix_start*src_cx/abs_dst_cx; if (co<0 || co>=p_img->m_width){ if (src_cx>0){ if (co<0) tmp =-src_x; if (co>=p_img->m_width) return -1; } else { if (co<0) return -1; if (co>=p_img->m_width) tmp=p_img->m_width-1-src_x; } ix_start=tmp*abs_dst_cx/src_cx; if ((tmp*abs_dst_cx)%src_cx) ix_start++; } // ix_end 補正 co=src_x+(ix_end-1)*src_cx/abs_dst_cx; if (co<0 || co>=p_img->m_width){ if (src_cx>0){ if (co<0) return -1; if (co>=p_img->m_width) tmp=p_img->m_width-src_x; } else { if (co<0) tmp=-src_x-1; if (co>=p_img->m_width) return -1; } tmp = tmp * abs_dst_cx; ix_end=abs(tmp/abs(src_cx)); if (tmp%abs(src_cx)) ix_end++; } // iy_start 補正 co=src_y+iy_start*src_cy/abs_dst_cy; if (co<0 || co>=p_img->m_height){ if (src_cy>0){ if (co<0) tmp =-src_y; if (co>=p_img->m_height) return -1; } else { if (co<0) return -1; if (co>=p_img->m_height) tmp=p_img->m_height-1-src_y; } iy_start=tmp*abs_dst_cy/src_cy; if ((tmp*abs_dst_cy)%src_cy) iy_start++; } // iy_end 補正 co=src_y+(iy_end-1)*src_cy/abs_dst_cy; if (co<0 || co>=p_img->m_height){ if (src_cy>0){ if (co<0) return -1; if (co>=p_img->m_height) tmp=p_img->m_height-src_y; } else { if (co<0) tmp=-src_y-1; if (co>=p_img->m_height) return -1; } tmp = tmp * abs_dst_cy; iy_end=abs(tmp/abs(src_cy)); if (tmp%abs(src_cy)) iy_end++; } return 0; }; // 拡大縮小コピーのインライン・テンプレート template <int dst_bit, int dst_alpha, int src_bit, int src_alpha> GT_IMG::from_elastic_draw_pixput(int dst_x, int dst_y, int dst_cx, int dst_cy, GT_IMG *p_img, int src_x, int src_y, int src_cx, int src_cy, int rate, int flag){ PIXEL_ITR<dst_bit, dst_alpha> d_pix; PIXEL_ITR<src_bit, src_alpha> s_pix; if (rate<0) return -1; else if (rate>=255) rate=255; d_pix.init(m_pbits, m_alpha, m_byte_width, m_width, m_height, &m_col_table); s_pix.init(p_img->m_pbits, p_img->m_alpha, p_img->m_byte_width, p_img->m_width, p_img->m_height, &p_img->m_col_table); int ix, iy, mx, my, nx, ny, abs_dst_cx, abs_dst_cy, abs_src_cx, abs_src_cy; int ix_start, ix_end, iy_start, iy_end, dst_add_x, dst_add_y, src_add_x, src_add_y; double e_x=0, e_y=0; if (!dst_cx || !dst_cy || !src_cx || !src_cy) return -1; abs_dst_cx=abs(dst_cx); abs_dst_cy=abs(dst_cy); abs_src_cx=abs(src_cx); abs_src_cy=abs(src_cy); ix_start=0; ix_end=abs_dst_cx; iy_start=0; iy_end=abs_dst_cy; src_add_x = (src_cx>=0)? 1: -1; src_add_y = (src_cy>=0)? 1: -1; dst_add_x = (dst_cx>=0)? 1: -1; dst_add_y = (dst_cy>=0)? 1: -1; if (adjust_elastic_draw(ix_start, iy_start, ix_end, iy_end, dst_x, dst_y, dst_cx, dst_cy, p_img, src_x, src_y, src_cx, src_cy)<0) return -1; // 初期値 my = dst_y+iy_start*dst_add_y; ny = src_y+iy_start*src_cy/abs_dst_cy; e_y= (iy_start*abs_src_cy)%abs_dst_cy; int mx_start = dst_x+ix_start*dst_add_x; int nx_start = src_x+ix_start*src_cx/abs_dst_cx; int e_x_start = (ix_start*abs_src_cx)%abs_dst_cx; // メインループ if (rate>=255){ // 不透明コピー for(iy=iy_start;iy<iy_end;iy++){ mx = mx_start; nx = nx_start; e_x= e_x_start; d_pix.set_pos(mx, my); for(ix=ix_start;ix<ix_end;ix++){ s_pix.set_pos(nx, ny); s_pix.to_draw(d_pix); // 描画 d_pix+=dst_add_x; // インクリメント e_x += abs_src_cx; while(e_x>=abs_dst_cx) { nx+=src_add_x; e_x-=abs_dst_cx; } mx += dst_add_x; } e_y += abs_src_cy; while(e_y>abs_dst_cy) { ny+=src_add_y; e_y-=abs_dst_cy; } my+=dst_add_y; } } // 半透明コピー else if (flag & ID_NOBLEND) { // 半透明コピー(ブレンド無し) for(iy=iy_start;iy<iy_end;iy++){ mx = mx_start; nx = nx_start; e_x= e_x_start; d_pix.set_pos(mx, my); for(ix=ix_start;ix<ix_end;ix++){ s_pix.set_pos(nx, ny); s_pix.to_no_blend_draw(d_pix, rate); // 描画 d_pix+=dst_add_x; // インクリメント e_x += abs_src_cx; while(e_x>=abs_dst_cx) { nx+=src_add_x; e_x-=abs_dst_cx; } mx += dst_add_x; } e_y += abs_src_cy; while(e_y>abs_dst_cy) { ny+=src_add_y; e_y-=abs_dst_cy; } my+=dst_add_y; } } else { // 半透明コピー(ブレンド有り) for(iy=iy_start;iy<iy_end;iy++){ mx = mx_start; nx = nx_start; e_x= e_x_start; d_pix.set_pos(mx, my); for(ix=ix_start;ix<ix_end;ix++){ s_pix.set_pos(nx, ny); s_pix.to_blend_draw(d_pix, rate); // 描画 d_pix+=dst_add_x; // インクリメント e_x += abs_src_cx; while(e_x>=abs_dst_cx) { nx+=src_add_x; e_x-=abs_dst_cx; } mx += dst_add_x; } e_y += abs_src_cy; while(e_y>abs_dst_cy) { ny+=src_add_y; e_y-=abs_dst_cy; } my+=dst_add_y; } } return 0; }; //==========矩形コピー========== // 矩形コピー(to) GT_IMG::to_draw(int dst_x, int dst_y, int cx, int cy, GT_IMG *p_img, int src_x, int src_y, int rate, int flag){ return from_draw(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); } // 矩形コピー(from) GT_IMG::from_draw(int dst_x, int dst_y, int cx, int cy, GT_IMG *p_img, int src_x, int src_y, int rate, int flag){ if (!p_img) return -1; if (!p_img->m_pbits || !m_pbits) return -1; // マイナス座標の補正 if (dst_x<0){ cx+= dst_x; src_x-=dst_x; dst_x=0; }; if (dst_y<0){ cy+= dst_y; src_y-=dst_y; dst_y=0; }; if (src_x<0){ cx+= src_x; dst_x-=src_x; src_x=0; }; if (src_y<0){ cy+= src_y; dst_y-=src_y; src_y=0; }; // 限界コピー幅の補正 if ((dst_x+cx)>m_width) { cx= m_width -dst_x;}; if ((dst_y+cy)>m_height) { cy= m_height-dst_y;}; if ((src_x+cx)>p_img->m_width) { cx=p_img->m_width -src_x;}; if ((src_y+cy)>p_img->m_height) { cy=p_img->m_height-src_y;}; switch(m_bit_count){ case 1: switch(p_img->m_bit_count){ case 1: from_draw_set_alpha<1 , 1 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 4: from_draw_set_alpha<1 , 4 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 8: from_draw_set_alpha<1 , 8 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 16: from_draw_set_alpha<1 , 16>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 24: from_draw_set_alpha<1 , 24>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 32: from_draw_set_alpha<1 , 32>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; } break; case 4: switch(p_img->m_bit_count){ case 1: from_draw_set_alpha<4 , 1 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 4: from_draw_set_alpha<4 , 4 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 8: from_draw_set_alpha<4 , 8 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 16: from_draw_set_alpha<4 , 16>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 24: from_draw_set_alpha<4 , 24>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 32: from_draw_set_alpha<4 , 32>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; } break; case 8: switch(p_img->m_bit_count){ case 1: from_draw_set_alpha<8 , 1 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 4: from_draw_set_alpha<8 , 4 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 8: from_draw_set_alpha<8 , 8 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 16: from_draw_set_alpha<8 , 16>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 24: from_draw_set_alpha<8 , 24>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 32: from_draw_set_alpha<8 , 32>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; } break; case 16: switch(p_img->m_bit_count){ case 1: from_draw_set_alpha<16, 1 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 4: from_draw_set_alpha<16, 4 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 8: from_draw_set_alpha<16, 8 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 16: from_draw_set_alpha<16, 16>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 24: from_draw_set_alpha<16, 24>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 32: from_draw_set_alpha<16, 32>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; } break; case 24: switch(p_img->m_bit_count){ case 1: from_draw_set_alpha<24, 1 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 4: from_draw_set_alpha<24, 4 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 8: from_draw_set_alpha<24, 8 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 16: from_draw_set_alpha<24, 16>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 24: from_draw_set_alpha<24, 24>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 32: from_draw_set_alpha<24, 32>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; } break; case 32: switch(p_img->m_bit_count){ case 1: from_draw_set_alpha<32, 1 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 4: from_draw_set_alpha<32, 4 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 8: from_draw_set_alpha<32, 8 >(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 16: from_draw_set_alpha<32, 16>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 24: from_draw_set_alpha<32, 24>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; case 32: from_draw_set_alpha<32, 32>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); break; } break; } return 0; } // 矩形コピーのインライン・テンプレート template <int dst_bit, int src_bit> GT_IMG::from_draw_set_alpha(int dst_x, int dst_y, int cx, int cy, GT_IMG *p_img, int src_x, int src_y, int rate, int flag){ if (is_alpha()){ if (p_img->is_alpha()) return from_draw_pixput<dst_bit, 1, src_bit, 1>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); else return from_draw_pixput<dst_bit, 1, src_bit, 0>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); } else { if (p_img->is_alpha()) return from_draw_pixput<dst_bit, 0, src_bit, 1>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); else return from_draw_pixput<dst_bit, 0, src_bit, 0>(dst_x, dst_y, cx, cy, p_img, src_x, src_y, rate, flag); } return 0; } // 矩形コピーのインライン・テンプレート template <int dst_bit, int dst_alpha, int src_bit, int src_alpha> GT_IMG::from_draw_pixput(int dst_x, int dst_y, int cx, int cy, GT_IMG *p_img, int src_x, int src_y, int rate, int flag){ PIXEL_ITR<dst_bit, dst_alpha> d_pix; PIXEL_ITR<src_bit, src_alpha> s_pix; if (rate<0) return -1; else if (rate>=255) rate=255; d_pix.init(m_pbits, m_alpha, m_byte_width, m_width, m_height, &m_col_table); s_pix.init(p_img->m_pbits, p_img->m_alpha, p_img->m_byte_width, p_img->m_width, p_img->m_height, &p_img->m_col_table); int ix, iy; if (rate>=255){ // 不透明コピー for(iy=0;iy<cy;iy++){ s_pix.set_pos(src_x, src_y+iy); d_pix.set_pos(dst_x, dst_y+iy); for(ix=0;ix<cx;ix++){ s_pix.to_draw(d_pix); d_pix++;s_pix++; } } } // 半透明コピー else if (flag & ID_NOBLEND) { // 半透明コピー(ブレンド無し) for(iy=0;iy<cy;iy++){ s_pix.set_pos(src_x, src_y+iy); d_pix.set_pos(dst_x, dst_y+iy); for(ix=0;ix<cx;ix++){ s_pix.to_no_blend_draw(d_pix, rate); d_pix++;s_pix++; } } } else { // 半透明コピー(ブレンド有り) for(iy=0;iy<cy;iy++){ s_pix.set_pos(src_x, src_y+iy); d_pix.set_pos(dst_x, dst_y+iy); for(ix=0;ix<cx;ix++){ s_pix.to_blend_draw(d_pix, rate); d_pix++;s_pix++; } } } return 0; }; //==========矩形描画========== // 矩形塗りつぶしのインライン・テンプレート template <int d_bit> inline void GT_IMG::fill_pixput(int x, int y, int cx, int cy, BYTE r, BYTE g, BYTE b, int rate, int flag){ PIXEL_ITR<d_bit,0> d_pix; d_pix.init(m_pbits, m_alpha, m_byte_width, m_width, m_height, &m_col_table); if (rate<0) rate=0; if (rate>=255) rate=255; int ix, iy; BYTE col_index; if (d_bit<=8 && rate>=255){ // (パレット版・不透明) col_index=m_col_table.get_col_index<d_bit>(r*rate/255, g*rate/255, b*rate/255); for(iy=0;iy<cy;iy++){ d_pix.set_pos(x, y+iy); for(ix=0;ix<cx;ix++){ d_pix.set_col(col_index); d_pix++; } } } else if (flag & ID_NOBLEND) { // 色ブレンド無し for(iy=0;iy<cy;iy++){ d_pix.set_pos(x, y+iy); for(ix=0;ix<cx;ix++){ d_pix.set_col_no_blend(r, g, b, rate); d_pix++; } } } else { // 色ブレンド有り for(iy=0;iy<cy;iy++){ d_pix.set_pos(x, y+iy); for(ix=0;ix<cx;ix++){ d_pix.set_col(r, g, b, rate); d_pix++; } } } }; // 矩形塗りつぶし GT_IMG::fill(int x, int y, int cx, int cy, BYTE r, BYTE g, BYTE b, int rate, int flag){ if (!m_pbits) return -1; if (cx<0) { x+=cx; cx=-cx; }; if (cy<0) { y+=cy; cy=-cy; }; // マイナス座標の補正 if (x<0) { cx+=x; x=0; }; if (y<0) { cy+=y; y=0; }; // 限界コピー幅の補正 if ((x+cx)>=m_width) { cx=m_width -x;}; if ((y+cy)>=m_height){ cy=m_height-y;}; // コピー switch(m_bit_count){ case 1 : fill_pixput<1> (x, y, cx, cy, r, g, b, rate, flag); break; case 4 : fill_pixput<4> (x, y, cx, cy, r, g, b, rate, flag); break; case 8 : fill_pixput<8> (x, y, cx, cy, r, g, b, rate, flag); break; case 16: fill_pixput<16>(x, y, cx, cy, r, g, b, rate, flag); break; case 24: fill_pixput<24>(x, y, cx, cy, r, g, b, rate, flag); break; case 32: fill_pixput<32>(x, y, cx, cy, r, g, b, rate, flag); break; } return 0; } // コンストラクタ GT_IMG::GT_IMG(){ m_col_mask =NULL; m_alpha =NULL; m_width = m_height = m_byte_width = m_bit_count =0; m_pbits =NULL; } // デストラクタ GT_IMG::~GT_IMG(){ destroy(); } // GIMG 破棄 GT_IMG::destroy(){ m_width=0; m_height=0; m_byte_width=0; m_bit_count=0; if (m_pbits) delete[] m_pbits; m_pbits = NULL; if (m_col_mask) delete[] m_col_mask; m_col_mask = NULL; m_col_table.destroy(); return 0; }; // GIMG 作成 GT_IMG::create(int cx, int cy, int a_bit_count, int a_color_size){ int i, palette_len, info_size; destroy(); // ファイルが開けたら既存データ破棄 if (cx<=0 || cy<=0) return -1; if (a_bit_count!=1 && a_bit_count!=4 && a_bit_count!=8 && a_bit_count!=16 && a_bit_count!=24 && a_bit_count!=32) return -1; if (a_bit_count<=8 && a_color_size==0) palette_len=1<<a_bit_count; // 8bit以下でパレット色数指定無しなら else palette_len=a_color_size; // パレット・メモリ確保 m_col_table.make(palette_len); /* バッファの1ラインの長さを計算 */ m_byte_width=4*((cx*a_bit_count+31)/32); m_pbits = new BYTE[m_byte_width*cy]; ZeroMemory(m_pbits, m_byte_width*cy); if (!m_pbits) return -1; m_width= cx; m_height=cy; m_bit_count=a_bit_count; // パレット自動配色 // 適当な基本色 RGBTRIPLE rgb[8]={ {0,0,0},{255, 255, 255}, {0,0,255}, {255,0,0}, {0,255,0}, {255, 255,0}, {255,0,255},{0,255,255} }; for(i=0;i<min(palette_len, 8);i++){ m_col_table.add_col(rgb[i].rgbtRed, rgb[i].rgbtGreen, rgb[i].rgbtBlue); } return 0; } // パレットに色設定 inline GT_IMG::set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b){ if (m_col_table.m_cols_len<=index) return -1; m_col_table.set_col(index, r, g, b); return 0; } // カラーマスク設定 GT_IMG::set_col_mask(UINT r, UINT g, UINT b){ if (!m_col_mask) m_col_mask = new unsigned long[3]; m_col_mask[0] = r; m_col_mask[1] = g; m_col_mask[2] = b; } // 1点ピクセル取得 DWORD GT_IMG::get_pixel(int x, int y){ if (!m_pbits) return 0; if (x<0 || x>=m_width || y<0 || y>=m_height) return 0; BYTE *ppix; ppix=m_pbits+(m_height-y-1)*m_byte_width + (x*m_bit_count>>3); switch(m_bit_count){ case 1: return 0x01 & (*ppix >> (7-(x&7))); case 4: return 0x0f & (*ppix >> ((x&1)?0:4)); case 8: return *ppix ; case 16: return *(WORD*)ppix; case 24: return 0x00FFffFF & *(DWORD*)ppix; case 32: return *(DWORD*)ppix ; } return 0; } // 1点ピクセル書きこみ GT_IMG::set_pixel(int x, int y, DWORD col){ if (!m_pbits) return 0; if (x<0 || x>=m_width || y<0 || y>=m_height) return 0; BYTE *ppix; ppix=m_pbits+(m_height-y-1)*m_byte_width + (x*m_bit_count>>3); switch(m_bit_count){ case 1: *ppix &= ~(1 <<(7-(x&7))); *ppix |= ((bool)col) <<(7-(x&7)); break; case 4: *ppix &= 0x0f << ((x&1)?4:0); *ppix |= (0x0f & col) << ((x&1)?0:4); break; case 8: *ppix = (BYTE)col; break; case 16: *(WORD*)ppix = (WORD)col; break; case 24: *(RGBTRIPLE*)ppix = *(RGBTRIPLE*)&col; break; case 32: *(DWORD*)ppix = *(DWORD*)&col; break; } return 0; } // ======== GT_DIB ================================== class GT_DIB : public GT_IMG{ public : HDC m_hdc; HBITMAP m_hbmp; GT_DIB(); ~GT_DIB(); // DC 適用 apply_dc(HDC hdc); apply_dc(HWND hwnd); // 作成と破棄 create(int cx, int cy, int a_bit_count, int a_color_size=0); virtual destroy(); // カラー apply_palette_all(); set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b); }; // コンストラクタ GT_DIB::GT_DIB(){ m_hdc = NULL; m_hbmp = NULL; } // デストラクタ GT_DIB::~GT_DIB(){ destroy(); } // HDCパレット設定(全て) GT_DIB::apply_palette_all(){ return m_col_table.apply_palette_all(m_hdc); } // パレットに色設定 inline GT_DIB::set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b){ return m_col_table.set_pal_col(m_hdc, index, r, g, b); } // DC有効化 GT_DIB::apply_dc(HDC hdc){ if (m_hdc) { DeleteDC(m_hdc); m_hdc=NULL; } m_hdc = CreateCompatibleDC(hdc); SelectObject(m_hdc, m_hbmp); return 0; } // DC有効化(HWND hwnd) GT_DIB::apply_dc(HWND hwnd){ if (m_hdc) { DeleteDC(m_hdc); m_hdc=NULL; } HDC hwnd_hdc = GetDC(hwnd); m_hdc = CreateCompatibleDC(hwnd_hdc); SelectObject(m_hdc, m_hbmp); ReleaseDC(hwnd, hwnd_hdc); return 0; } // 破棄 GT_DIB::destroy(){ if (m_hdc) { DeleteDC(m_hdc); m_hdc=NULL; } if (m_hbmp) { DeleteObject(m_hbmp); m_hbmp=NULL; } // if (m_pbits) delete[] m_pbits; m_pbits = NULL; m_width=0; m_height=0; m_byte_width=0; m_bit_count=0; if (m_col_mask) delete[] m_col_mask; m_col_mask = NULL; m_col_table.destroy(); return 0; } // 作成 GT_DIB::create(int cx, int cy, int a_bit_count, int a_color_size){ BITMAPINFO *bmp_info; int i, palette_entry, info_size; destroy(); // 作成済みメモリを破棄する if (cx<=0 || cy<=0) return -1; if (a_bit_count!=1 && a_bit_count!=4 && a_bit_count!=8 && a_bit_count!=16 && a_bit_count!=24 && a_bit_count!=32) return -1; palette_entry=1; if (a_color_size!=0) palette_entry=a_color_size; else if (a_bit_count<=8) palette_entry=1<<a_bit_count; // 8bit以下でパレット色数指定無しなら info_size=sizeof(BITMAPINFOHEADER) + (palette_entry-1)*sizeof(RGBQUAD)+1; bmp_info = (BITMAPINFO*)malloc(info_size); if (!bmp_info) return -1; ZeroMemory(bmp_info, info_size); // 適当な基本色 RGBTRIPLE rgb[8]={ {0,0,0},{255, 255, 255}, {0,0,255}, {255,0,0}, {0,255,0}, {255, 255,0}, {255,0,255},{0,255,255} }; m_col_table.make(palette_entry); for(i=0;i<min(palette_entry, 8);i++){ bmp_info->bmiColors[i].rgbBlue = rgb[i].rgbtBlue; bmp_info->bmiColors[i].rgbGreen = rgb[i].rgbtGreen; bmp_info->bmiColors[i].rgbRed = rgb[i].rgbtRed; bmp_info->bmiColors[i].rgbReserved = 0; m_col_table.add_col(rgb[i].rgbtRed, rgb[i].rgbtGreen, rgb[i].rgbtBlue); } /* BITMAPINFO構造体設定 */ bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmp_info->bmiHeader.biWidth=cx; bmp_info->bmiHeader.biHeight=cy; bmp_info->bmiHeader.biPlanes=1; bmp_info->bmiHeader.biBitCount=a_bit_count; bmp_info->bmiHeader.biCompression=BI_RGB; bmp_info->bmiHeader.biSizeImage=0; bmp_info->bmiHeader.biXPelsPerMeter=0; bmp_info->bmiHeader.biYPelsPerMeter=0; bmp_info->bmiHeader.biClrUsed=palette_entry; bmp_info->bmiHeader.biClrImportant=0; m_hbmp = CreateDIBSection(NULL, bmp_info, DIB_RGB_COLORS, (VOID**)&m_pbits, NULL, 0); if (!m_hbmp) { free(bmp_info); return -1; } m_width= cx; m_height=cy; m_bit_count=a_bit_count; /* バッファの1ラインの長さを計算 */ m_byte_width=4*((m_width*m_bit_count+31)/32); ZeroMemory(m_pbits, m_byte_width*m_height); free(bmp_info); return 0; } |
gt_img_08.cpp |
// 拡大縮小コピー #include <stdio.h> #include <windows.h> #include "resource_08.h" #include "gt_img_08.h" GT_DIB gt_dib_1, gt_dib_2, *src_dib=NULL; POINT gt_dib_1_pos, gt_dib_2_pos; int dst_cx, dst_cy, src_x, src_y, src_cx, src_cy; static OPENFILENAME ofn = {0}; static char filename[MAX_PATH]; POINT start_po, mou_po; RECT paste_rc, copy_rc, select_rc; int select_rc_valid=0, copy_rc_valid=0; int rate=255; dialog(HWND hwnd, char *a_str){ return MessageBox(hwnd, a_str, TEXT("error"), MB_OK); } // 枠線を反転描画する patblt_rect_frame(HDC hdc, RECT rc){ RECT rc2, rc3; HRGN hrgn, hrgn2, hrgn3; rc2.left = min(rc.left, rc.right); rc2.top = min(rc.top, rc.bottom); rc2.right = max(rc.left, rc.right); rc2.bottom= max(rc.top, rc.bottom); rc3.left = rc2.left +1; rc3.top = rc2.top +1; rc3.right = rc2.right -1; rc3.bottom= rc2.bottom-1; hrgn = CreateRectRgnIndirect(&rc2); hrgn2 = CreateRectRgnIndirect(&rc3); hrgn3 = CreateRectRgn(0,0,0,0); CombineRgn(hrgn3, hrgn, hrgn2, RGN_DIFF); SelectObject(hdc, hrgn3); GetClipBox(hdc, &rc2); PatBlt(hdc, rc2.left, rc2.top, rc2.right, rc2.bottom, PATINVERT); if (hrgn) DeleteObject(hrgn); if (hrgn2) DeleteObject(hrgn2); if (hrgn3) DeleteObject(hrgn3); } // メニュー on_command(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){ switch(LOWORD(wp)) { case IDM_MAKE_DIB_0: case IDM_MAKE_DIB_1: case IDM_MAKE_DIB_4: case IDM_MAKE_DIB_8: case IDM_MAKE_DIB_16: case IDM_MAKE_DIB_24: case IDM_MAKE_DIB_32: gt_dib_1.create(201, 151, LOWORD(wp)-IDM_MAKE_DIB_0, 0); gt_dib_1.apply_dc(hwnd); gt_dib_2_pos.x = gt_dib_1.m_width+gt_dib_1_pos.x+20; InvalidateRect(hwnd, NULL, 1); break; case IDM_OPEN: ofn.Flags = OFN_FILEMUSTEXIST; if (!GetOpenFileName(&ofn)) break; gt_dib_1.load_dib(filename); gt_dib_1.apply_dc(hwnd); gt_dib_1.apply_palette_all(); InvalidateRect(hwnd, NULL, 1); gt_dib_2_pos.x = gt_dib_1.m_width+gt_dib_1_pos.x+40; break; case IDM_OPEN2: ofn.Flags = OFN_FILEMUSTEXIST; if (!GetOpenFileName(&ofn)) break; gt_dib_2.load_dib(filename); gt_dib_2.apply_dc(hwnd); gt_dib_2.apply_palette_all(); InvalidateRect(hwnd, NULL, 1); break; case IDM_SAVE_DIB: ofn.Flags = 0; if (!GetSaveFileName(&ofn)) break; gt_dib_1.save_dib(filename); break; case IDM_COPY: if (!select_rc_valid) { dialog(hwnd, "コピー元の範囲を指定してください"); break; } copy_rc = select_rc; if (copy_rc.left<(gt_dib_1.m_width + gt_dib_1_pos.x +10)){ // 画像1からコピー src_dib = >_dib_1; src_x = copy_rc.left - gt_dib_1_pos.x; src_y = copy_rc.top - gt_dib_1_pos.y; } else { // 画像2からコピー src_dib = >_dib_2; src_x = copy_rc.left - gt_dib_2_pos.x; src_y = copy_rc.top - gt_dib_2_pos.y; } select_rc_valid = 0; copy_rc_valid=1; src_cx = copy_rc.right-copy_rc.left; src_cy = copy_rc.bottom-copy_rc.top; InvalidateRect(hwnd, NULL, 1); break; case IDM_PASTE: if (!copy_rc_valid) { dialog(hwnd, "コピー元を指定してください"); break; } if (!select_rc_valid) { dialog(hwnd, "コピー先の範囲を指定してください"); break; } paste_rc=select_rc; select_rc_valid = 0; dst_cx = paste_rc.right-paste_rc.left; dst_cy = paste_rc.bottom-paste_rc.top; if (paste_rc.left<(gt_dib_1.m_width + gt_dib_1_pos.x +10)){ // 画像1に貼り付け gt_dib_1.from_elastic_draw( paste_rc.left - gt_dib_1_pos.x, paste_rc.top - gt_dib_1_pos.y, dst_cx, dst_cy, src_dib, src_x, src_y, src_cx, src_cy, rate ); } else { // 画像2に貼り付け gt_dib_2.from_elastic_draw( paste_rc.left - gt_dib_2_pos.x, paste_rc.top - gt_dib_2_pos.y, dst_cx, dst_cy, src_dib, src_x, src_y, src_cx, src_cy, rate ); } InvalidateRect(hwnd, NULL, 1); break; case IDM_ALPHA_100: case IDM_ALPHA_90 : case IDM_ALPHA_80 : case IDM_ALPHA_70 : case IDM_ALPHA_60 : case IDM_ALPHA_50 : case IDM_ALPHA_40 : case IDM_ALPHA_30 : case IDM_ALPHA_20 : case IDM_ALPHA_10 : case IDM_ALPHA_0 : rate = ((LOWORD(wp) - IDM_ALPHA_0)*255)/100; break; } } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { HDC hdc; PAINTSTRUCT ps; static char s[50]; RECT rc; static int mou_down=0; HMENU hmenu_sub, hmenu_parent; switch (msg) { case WM_PAINT: GetClientRect(hwnd , &rc); hdc = BeginPaint(hwnd, &ps); // gt_dib_1 if (gt_dib_1.m_hdc){ BitBlt( hdc, gt_dib_1_pos.x, gt_dib_1_pos.y, gt_dib_1.m_width, gt_dib_1.m_height, gt_dib_1.m_hdc, 0, 0, SRCCOPY); } sprintf(s, "gt_dib_1\nヨコ %d X タテ %d %dビット", gt_dib_1.m_width, gt_dib_1.m_height, gt_dib_1.m_bit_count); rc.left=gt_dib_1_pos.x; rc.top=gt_dib_1.m_height + gt_dib_1_pos.y; if (gt_dib_1.m_hdc)rc.right=gt_dib_1.m_width + gt_dib_1_pos.x; DrawText(hdc, s, -1, &rc, DT_WORDBREAK ); // gt_dib_2 if (gt_dib_2.m_hdc){ BitBlt( hdc, gt_dib_2_pos.x, gt_dib_2_pos.y, gt_dib_2.m_width, gt_dib_2.m_height, gt_dib_2.m_hdc, 0, 0, SRCCOPY); } sprintf(s, "gt_dib_2\nヨコ %d X タテ %d %dビット", gt_dib_2.m_width, gt_dib_2.m_height, gt_dib_2.m_bit_count); GetClientRect(hwnd , &rc); rc.top=gt_dib_2.m_height + gt_dib_2_pos.y; rc.left=gt_dib_2_pos.x; DrawText(hdc, s, -1, &rc, DT_WORDBREAK ); if (select_rc_valid) patblt_rect_frame(hdc, select_rc); if (copy_rc_valid) patblt_rect_frame(hdc, copy_rc); EndPaint(hwnd, &ps); break; case WM_COMMAND: on_command(hwnd, msg, wp, lp); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.lpstrFilter = TEXT("bmp files {*.bmp}\0*.bmp\0") TEXT("All files {*.*}\0*.*\0\0"); ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = filename; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST; gt_dib_1_pos.x= gt_dib_1_pos.y=40; gt_dib_2_pos.x= 250; gt_dib_2_pos.y= 40; break; case WM_LBUTTONDOWN: if (!mou_down){ hdc=GetDC(hwnd); if (select_rc_valid) patblt_rect_frame(hdc, select_rc); ReleaseDC(hwnd, hdc); GetCursorPos(&start_po); ScreenToClient(hwnd, &start_po); mou_down=1; } break; case WM_LBUTTONUP: if (mou_down){ mou_down=0; GetCursorPos(&mou_po); ScreenToClient(hwnd, &mou_po); select_rc.left = start_po.x; select_rc.top = start_po.y; select_rc.right = mou_po.x; select_rc.bottom= mou_po.y; InvalidateRect(hwnd, NULL, 1); select_rc_valid=1; } mou_down=0; break; case WM_RBUTTONUP: hmenu_parent = LoadMenu(GetModuleHandle(NULL), TEXT("GT_DIB_MENU_R")); hmenu_sub = GetSubMenu(hmenu_parent, 0); // 描画位置を保持 GetCursorPos(&start_po); ScreenToClient(hwnd, &start_po); // ポップアップ GetCursorPos(&mou_po); TrackPopupMenu(hmenu_sub, TPM_LEFTALIGN | TPM_TOPALIGN, mou_po.x, mou_po.y, 0, hwnd, NULL); DestroyMenu(hmenu_sub); DestroyMenu(hmenu_parent); break; case WM_MOUSEMOVE: if (mou_down){ hdc=GetDC(hwnd); GetClientRect(hwnd , &rc); if (mou_down==2) patblt_rect_frame(hdc, select_rc); mou_down=2; GetCursorPos(&mou_po); ScreenToClient(hwnd, &mou_po); select_rc.left = start_po.x; select_rc.top = start_po.y; select_rc.right = mou_po.x; select_rc.bottom= mou_po.y; patblt_rect_frame(hdc, select_rc); ReleaseDC(hwnd, hdc); } break; } return DefWindowProc(hwnd, msg, wp, lp); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { HWND hwnd; MSG msg; WNDCLASS winc; winc.style = CS_HREDRAW | CS_VREDRAW; winc.lpfnWndProc = WndProc; winc.cbClsExtra = winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL, IDI_APPLICATION); winc.hCursor = LoadCursor(NULL, IDC_ARROW); winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); winc.lpszMenuName = TEXT("GT_DIB_MENU"); winc.lpszClassName = TEXT("GT_IMG"); if (!RegisterClass(&winc)) return 1; hwnd = CreateWindow( TEXT("GT_IMG"), TEXT("拡大縮小コピー"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 600, 280, NULL, NULL, hInstance, NULL ); if (hwnd == NULL) return 1; while (GetMessage(&msg, NULL, 0, 0 )) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } |