αチャンネル付の画像を表示する

VC++ で32bit BMP の画像をαチャンネルを使って Alph Blending して表示します。
32ビット BMP では、RGB の24ビットだけが有効で、一般的にαビットは使われていません。
このページではαチャンネル付きで保存した画像を Alph Blending して表示します。
αチャンネル付きの画像を作成するには専用のソフトが必要です。

Photoshop の画像

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

プロジェクトの設定

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

【演習】

  1. プログラムを完成させて下さい。
  2. αチャンネル付きの画像を作成するには専用のソフトが必要で、私は Photoshop 7.0 を使いました。
    αチャンネル(8 bit)には「モノクロ 256色」のイメージが格納されています。
    Photoshop の古いバージョンではαチャンネル付きの画像を保存できないかも知れません。 (;_;)
  3. 私のダウンロードサイト(AlphaBMP.html)からαチャンネル付きの画像を作成するアプリを提供しています。
    基本となる画像とマスク画像を入力して、[ファイル][BMP32で保存]で簡単に作成することが出来ます。
  4. αチャンネル付きの画像には DirectX の DDS 形式もあります。
    こちらは無料で配布されているので、誰でも手に入れることができます。 (●^o^●)
    DDS 形式の説明は αチャンネル付の DDS 画像ファイルを表示する を参照して下さい。

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