二枚の画像をブレンドしながら切り替える

VC++ で二枚の画像をピクセルブレンドしながら滑らかに切り替えます。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. my.lib に登録されている Object Class を使うので my.h をインクルードして my.lib をリンクします。
    Object Class のソースコードは Object Class Library から取得して下さい。
    *Img1, *Img2 は、切り替える二枚の画像を格納する IMAGE Object Class の定義です。
    *Surface は、画像をブレンドする SURFACE Object Class の定義です。
    File1[], File2[] は JPEG 画像ファイルの名前で、ウインドウサイズに合わせた二枚の画像を用意して下さい。
    Rate は wipe の度合いで 1.0 で Img1 の画像に、0.0 で Img2 の画像になります。
        /*******************************************************/
        /*★ 二枚の JPEG 画像を Wipe で切り替える    前田 稔 ★*/
        /*******************************************************/
        #include    <windows.h>
        #include    "My.h"
        #pragma     once
        #pragma     comment(lib,"my.lib")
    
        HINSTANCE       g_hInst;
        HWND            g_hWnd;
        IMAGE           *Img1= NULL;            // IMAGE Object Class
        IMAGE           *Img2= NULL;            // IMAGE Object Class
        SURFACE         *Surface;               // Surface Object Class
    
        char            File1[]= "c:\\data\\ffx2s.jpg";   // 480*240
        char            File2[]= "c:\\data\\GeoS.jpg";    // 480*240
        float           Rate= 1.0f;             // Blend のレート
        
  2. CALLBACK 関数の WM_CREATE: では AppInit() 関数を呼ぶだけで、全ての処理は関数の中で行います。
            case WM_CREATE:
                AppInit(hWnd);
                break;
        
  3. WM_PAINT: で二枚の画像をブレンドして描画します。
    Surface Object Class は画像をブレンドするために、二枚の Surface を持っています。
        HBITMAP         hBmp;               //画像の HBITMAP
        HBITMAP         hWBmp;              //ブレンド用の HBITMAP
        HDC             hBmpDC;             //画像の HDC
        HDC             hWBmpDC;            //ブレンド用の HDC
        LPBYTE          Data;               //画像の BITMAP DATA
        LPBYTE          WData;              //ブレンド用の BITMAP DATA
        
    AppInit() で上から重ねる画像(Img2)を、ブレンド用の hWBmpDC に格納しておきます。
    Img1->Show() で Surface->hBmpDC に元の画像を転送します。
    Surface->Blend() で Img1 と Img2 を Rate の割合でブレンドします。
        for(dy=0; dy<Dib1.Height; dy++)
            for(dx=0; dx<Dib1.Width; dx++)
            {
                b1 = (WORD)Dib1.Data[(dy*Dib1.Width+dx)*3];
                g1 = (WORD)Dib1.Data[(dy*Dib1.Width+dx)*3+1];
                r1 = (WORD)Dib1.Data[(dy*Dib1.Width+dx)*3+2];
                b2 = (WORD)Dib2.Data[(dy*Dib1.Width+dx)*3];
                g2 = (WORD)Dib2.Data[(dy*Dib1.Width+dx)*3+1];
                r2 = (WORD)Dib2.Data[(dy*Dib1.Width+dx)*3+2];
                Dib1.Data[(dy*Dib1.Width+dx)*3]   = (BYTE)(b1*rate + b2*(1.0f-rate));
                Dib1.Data[(dy*Dib1.Width+dx)*3+1] = (BYTE)(g1*rate + g2*(1.0f-rate));
                Dib1.Data[(dy*Dib1.Width+dx)*3+2] = (BYTE)(r1*rate + r2*(1.0f-rate));
            }
        
  4. ブレンドした画像を BitBlt() で描画します。
            case WM_PAINT:          // Surface1 を描画
                hdc = BeginPaint(hWnd,&ps);
                Img1->Show(Surface->hBmpDC,0,0);
                Surface->Blend(Surface->Data,Surface->WData,Rate);
                BitBlt(hdc,30,20,Img1->Width,Img1->Height,Surface->hBmpDC,0,0,SRCCOPY);
                EndPaint(hWnd, &ps);
                break;
        
  5. マウスの左クリックで Rate を 0.1 ずつ下げて Img1 から Img2 の画像に切り替えます。
    右クリックで Rate の値を 1.0 に戻します。
            case WM_LBUTTONDOWN:    // 左ボタンをクリック
                if (Rate>=0.1f)     Rate-= 0.1f;
                else                Rate=  0.0f;
                InvalidateRect(hWnd,NULL,FALSE);
                break; 
            case WM_RBUTTONDOWN:    // 右ボタンをクリック
                Rate= 1.0f;
                InvalidateRect(hWnd,NULL,FALSE);
                break; 
        
  6. WM_CLOSE: では、終了前にリソースを開放して下さい。
                SAFE_DELETE(Img1);
                SAFE_DELETE(Img2);
                SAFE_DELETE(Surface);
                DestroyWindow(hWnd);
                break;
        
  7. 二枚の JPEG 画像をロードして、24bit DIB の Surface を作成する関数です。
    二枚の IMAGE Object Class を生成して画像を入力します。
    JPEG 画像と同じサイズの Surface を作成します。
    上から重ねる画像(Img2)を、ブレンド用の hWBmpDC に格納しておきます。
        void  AppInit(HWND hwnd)
        {   // JPEG 画像のロード
            Img1= new IMAGE(hwnd);
            Img1->LoadFile(File1);
            Img2= new IMAGE(hwnd);
            Img2->LoadFile(File2);
            // Surface を作成
            Surface= new SURFACE(hwnd,Img1->Width,Img1->Height);
            Img2->Show(Surface->hWBmpDC,0,0);
        }
        
  8. WinMain() は何時もと同じように画像サイズに合わせてウインドウを表示するだけです。

【演習】

  1. プログラムを完成させて下さい。
  2. マウスのクリックで wipe していますが、タイマを設定してゆっくりしたペースで wipe して下さい。
  3. メニュー選択で wipe を始めるようにプログラムして下さい。

超初心者のプログラム入門(Win32API C++)