画像の上から半透明で TXET を表示

VC++ で画像の上から半透明で TEXT 文字を表示します。

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

プロジェクトの設定

  1. my.lib に登録されている Object Class を使うので my.h をインクルードして my.lib をリンクしています。
    Object Class のソースコードは Object Class Library から取得して下さい。
    BACKBUF *Back は BACKBUF Object Class の定義です。
    JPEG *Jpeg は JPEG Object Class の 定義です。
    SURFACE *Surface は SURFACE Object Class の 定義です。
    g_RC は画像の上から文字を表示する矩形領域で、マウスがクリックされた座標を起点に計算されます。
    ImgFile[] は JPEG 画像ファイルの名前です。ウインドウサイズに合わせた画像を設定して下さい。
        /*****************************************/
        /*★ 半透明処理のプログラム    前田 稔 ★*/
        /*****************************************/
        #include    <windows.h>
        #include    "My.h"
        #pragma     once
        #pragma     comment(lib,"my.lib")
    
        HINSTANCE       g_hInst;
        HWND            g_hWnd;
        BACKBUF         *Back= NULL;            // Back Buffer Object
        JPEG            *Jpeg= NULL;            // JPEG Object Class
        SURFACE         *Surface;               // SURFACE Object Class
    
        RECT            g_RC= { 100, 50, 200, 100 };
        char            ImgFile[]= "ffx2s.jpg"; // 480*240
        
  2. CALLBACK 関数の WM_CREATE: では AppInit() 関数を呼ぶだけで、全ての処理は関数の中で行います。
            case WM_CREATE:
                AppInit(hWnd);
                break;
        
  3. WM_PAINT: では現在 BackBuffer に設定されている描画を描画します。
            case WM_PAINT:          // 裏画面の HDC を描画
                hdc = BeginPaint(hWnd,&ps);
                BitBlt(hdc,0,0,Jpeg->Width,Jpeg->Height,Back->hBackDC,0,0,SRCCOPY);
                EndPaint(hWnd, &ps);
                break;
        
  4. WM_LBUTTONDOWN: で JPEG 画像の上から TEXT 文字を半透明で描画します。
    その手順は、クリックされた座標を起点にして g_RC 構造体を設定します。
    JPEG 画像の矩形部分を Surface に転送して Surface->Wipe(0.5f) で明度を半分にします。
    明度を下げる方法は 画像の fadeout を参照して下さい。
    Back Buffer に元の JPEG 画像を貼り付けて、その上から半透明処理した矩形部分を重ねます。
    Back Buffer の矩形領域(g_RC) に文字の背景を透明にして TEXT を描画します。
            case WM_LBUTTONDOWN:    // 左ボタンをクリック
                // マウスの座標から矩形領域を設定
                g_RC.left= LOWORD(lp);
                g_RC.top= HIWORD(lp);
                g_RC.right= g_RC.left+Surface->Width;
                g_RC.bottom= g_RC.top+Surface->Height;
                // 画像の矩形領域を半透明処理
                Jpeg->Show(Surface->hBmpDC,0,0,Surface->Width,Surface->Height,g_RC.left,g_RC.top);
                Surface->Wipe(0.5f);
                // Back Buffer に元の JPEG 画像を貼り付け
                Jpeg->Show(Back->hBackDC,0,0);
                // 半透明処理した矩形(Surface)を上から貼り付け
                BitBlt(Back->hBackDC,LOWORD(lp),HIWORD(lp),Surface->Width,Surface->Height,Surface->hBmpDC,0,0,SRCCOPY);
                // 半透明処理した矩形に、背景を透明にした文字を描画
                SetBkMode(Back->hBackDC,TRANSPARENT);
                SetTextColor(Back->hBackDC,RGB(255,255,0));
                DrawText(Back->hBackDC,"半透明です",-1,&g_RC,DT_CENTER|DT_SINGLELINE|DT_VCENTER);
                InvalidateRect(hWnd,NULL,FALSE);
                break; 
        
  5. WM_CLOSE: では、終了前にリソースを開放して下さい。
            case WM_CLOSE: // クローズ
                SAFE_DELETE(Back);
                SAFE_DELETE(Jpeg);
                SAFE_DELETE(Surface);
                DestroyWindow(hWnd);
                break;
        
  6. JPEG 画像をロードして、裏画面と 24bit DIB を作成する関数です。
    JPEG Object Class を生成して画像を入力します。
    BackBuffer Object Class を生成して、起動時に表示する画像を転送します。
    SURFACE Object Class を g_RC のサイズで生成します。
    rgbMask.rgbRed= 100; は半透明処理する矩形の範囲を「赤緑青」で強調するマスクです。
    この行のコメントを外すと、矩形部分が赤っぽくなります。
        void  AppInit(HWND hwnd)
        {
            // JPEG 画像のロード(ImgFile)
            Jpeg= new JPEG(hwnd);
            Jpeg->Load(ImgFile);
            // 裏画面の作成
            Back= new BACKBUF(hwnd);
            // 裏画面にビットマップを貼り付け
            Jpeg->Show(Back->hBackDC,0,0);
            // 24bit DIB 作成
            Surface= new SURFACE(hwnd,g_RC.right-g_RC.left,g_RC.bottom-g_RC.top);
            //Surface->rgbMask.rgbRed= 100;
        }
        
  7. WinMain() は何時もと同じように画像サイズに合わせてウインドウを表示するだけです。

【演習】

  1. プログラムを完成させて下さい。
  2. rgbMask に適当な値を設定して、TEXT 表示部分の背景色に反映させて下さい。
        // 明度を rate レベルに下げる
        for(dy=0; dy<Height; dy++)
            for(dx=0; dx<Width; dx++)
            {
                b = (WORD)Data[(dy*Width+dx)*3];
                g = (WORD)Data[(dy*Width+dx)*3+1];
                r = (WORD)Data[(dy*Width+dx)*3+2];
                Data[(dy*Width+dx)*3] =   (BYTE)((b+(WORD)rgbMask.rgbBlue)*rate);
                Data[(dy*Width+dx)*3+1] = (BYTE)((g+(WORD)rgbMask.rgbGreen)*rate);
                Data[(dy*Width+dx)*3+2] = (BYTE)((r+(WORD)rgbMask.rgbRed)*rate);
            }
        

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