画像の fadeout

VC++ で画像のピクセルデータに直接アクセスして、ピクセルごとの明度を下げながら fadeout します。

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

プロジェクトの設定

  1. JPEG Object Class を使うので my.h をインクルードして my.lib をリンクしています。
    言うまでもありませんが BMP 画像を使って fadeout することもできます。
    Object Class のソースコードは Object Class Library から取得して下さい。
  2. Dib(device-independent bitmap)Struct はピクセルデータを直接演算するための構造体です。
    JPEG *Jpeg は JPEG 画像を描画できる Object Class の 定義です。
    DibStruct Dib; で DibStruct 構造体を定義します。
    ImgFile[] は JPEG 画像ファイルの名前です。ウインドウサイズに合わせた画像を設定して下さい。
    Rate は fadeout の度合いで 1.0 で元の明度に、0.0 で真っ黒な画像になります。
        /*********************************************/
        /*★ JPEG Fade OUT のプログラム    前田 稔 ★*/
        /*********************************************/
        #define     NAME    "JPEG Fade OUT"
        #include    <windows.h>
        #include    "My.h"
        #pragma     once
        #pragma     comment(lib,"my.lib")
    
        typedef struct
        {   long            Width,Height;
            HBITMAP         hBmp;
            HDC             hBmpDC;
            LPBYTE          Data;               // 24bit DIB の BITMAP DATA
            LPBITMAPINFO    Info;               // BITMAP 構造体のヘッダー
        }   DibStruct;
    
        HINSTANCE       g_hInst;
        HWND            g_hWnd;
        JPEG            *Jpeg= NULL;            // JPEG Object Class
        DibStruct       Dib;                    // Fade OUT の画像を作成
    
        char            ImgFile[]= "ffx2s.jpg"; //480*240
        float           Rate= 1.0f;             //Fade OUT のレート
        
  3. CALLBACK 関数の WM_CREATE: では AppInit() 関数を呼ぶだけで、全ての処理は関数の中で行います。
            case WM_CREATE:
                AppInit(hWnd);
                break;
        
  4. WM_PAINT: では現在 Dib に設定されている画像を描画します。
            case WM_PAINT:          // Dib の画像を描画
                hdc = BeginPaint(hWnd,&ps);
                BitBlt(hdc,30,20,Jpeg->Width,Jpeg->Height,Dib.hBmpDC,0,0,SRCCOPY);
                EndPaint(hWnd, &ps);
                break;
        
  5. マウスの左クリックで画像の明度を 0.1 ずつ下げて画像を描画します。
    SetWipe(Rate) が明度を下げた画像を Dib に設定する関数です。
            case WM_LBUTTONDOWN:    // 左ボタンをクリック
                if (Rate>=0.1f)  Rate-= 0.1f;
                else             Rate=  0.0f;
                // Jpeg 画像を Dib.hBmp に転送して、明度を rate レベルに下げる
                SetWipe(Rate);
                InvalidateRect(hWnd,NULL,FALSE);
                break; 
        
  6. WM_CLOSE: では、終了前にリソースを開放して下さい。
            case WM_CLOSE:          // クローズ
                SAFE_DELETE(Jpeg);
                // DIB の開放
                DeleteDC(Dib.hBmpDC);
                DeleteObject(Dib.hBmp);
                GlobalFree(Dib.Info);
                DestroyWindow(hWnd);
                break;
        
  7. JPEG 画像をロードして、24bit DIB を作成する関数です。
    JPEG Object Class を生成して画像を入力します。
    Dib に JPEG 画像と同じサイズの 24 bit モードの DIB を作成します。
    CreateDIBSection() で DIB を生成して、ビットマップデータのポインタを Dib.Data に格納します。
    ロードした JPEG 画像を Dib にも転送しておきます。
    これはプログラムが起動された直後に実行される WM_PAINT: で画像が正常に描画されるようにするためです。
        void  AppInit(HWND hwnd)
        {   HDC      hDC;
    
            // JPEG 画像のロード(ImgFile)
            Jpeg= new JPEG(hwnd);
            Jpeg->Load(ImgFile);
            // 24bit DIB 作成
            // ビットマップインフォ構造体設定
            hDC = GetDC(hwnd);
            Dib.Info = (LPBITMAPINFO)GlobalAlloc(GPTR,sizeof(BITMAPINFO));
            Dib.Info-> bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
            Dib.Info-> bmiHeader.biWidth=Jpeg->Width;
            Dib.Info-> bmiHeader.biHeight=Jpeg->Height;
            Dib.Info-> bmiHeader.biPlanes=1;
            Dib.Info-> bmiHeader.biBitCount=24;        // 24 bit
            Dib.Info-> bmiHeader.biCompression=BI_RGB; // 非圧縮
            Dib.hBmp = CreateDIBSection(hDC,Dib.Info,0,(VOID**)&Dib.Data,NULL,0); 
            Dib.Width=  Jpeg->Width;        // DIB の幅
            Dib.Height= Jpeg->Height;       // DIB の高さ
            Dib.hBmpDC= CreateCompatibleDC(hDC);
            SelectObject(Dib.hBmpDC,Dib.hBmp);
            ReleaseDC(hwnd,hDC);
            // Dib に JPEG 画像を描画
            Jpeg->Show(Dib.hBmpDC,0,0);
        }
        
  8. Jpeg 画像を Dib.hBmp に転送して、明度を rate レベルに下げる関数です。
    DIB 構造体の Dib.Data[] がピクセルデータで、全てのピクセルの明度を rate のレベルに下げます。
        VOID  SetWipe(float rate)
        {   LONG    dx,dy;
            WORD    r,g,b;
    
            Jpeg->Show(Dib.hBmpDC,0,0);
            // 明度を rate レベルに下げる
            for(dy=0; dy<Jpeg->Height; dy++)
                for(dx=0; dx<Jpeg->Width; dx++)
                {
                    b = (WORD)Dib.Data[(dy*Jpeg->Width+dx)*3];
                    g = (WORD)Dib.Data[(dy*Jpeg->Width+dx)*3+1];
                    r = (WORD)Dib.Data[(dy*Jpeg->Width+dx)*3+2];
                    Dib.Data[(dy*Jpeg->Width+dx)*3] =   (BYTE)(b*rate);
                    Dib.Data[(dy*Jpeg->Width+dx)*3+1] = (BYTE)(g*rate);
                    Dib.Data[(dy*Jpeg->Width+dx)*3+2] = (BYTE)(r*rate);
                }
        }
        
  9. WinMain() は何時もと同じように画像サイズに合わせてウインドウを表示するだけです。

【演習】

  1. プログラムを完成させて下さい。
  2. マウスのクリックで fadeout していますが、タイマを設定してゆっくりしたペースで fadeout して下さい。

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