1
3

More than 5 years have passed since last update.

画像表示を含む自分用アプリの雛形(2) Direct2D化-1

Posted at

雛形(1)で書いたGDIによる画像表示(フレームバッファの作成)のコードを流用して、Direct2Dに変更してみます。
利点としては、画像の半透明、変形、重ね合わせがしやすい、表示座標が整数に制限されない
といったところでしょうか。(もちろん、線描画でアンチエイリアスのきれいな線がかけるってのもあります)

参照:) 画像表示を含む自分用アプリの雛形(1)

ヘッダーにincudeファイルの設定追加

Direct2Dに機能追加されるごとにヘッダーファイルが変わるんですが、対応をあまりよく調べてません。
とりあえず、今回はここらへんを使っておきます。

#include <d2d1_2.h>
#pragma comment(lib, "d2d1.lib")

グローバル変数の追加

サンプルなんで、安直にグローバル変数を使います。

ID2D1Factory1       *pD2D_Factory;
ID2D1DCRenderTarget *pDCRT;
ID2D1Bitmap         *pD2D_Bitmap;
const D2D1_PIXEL_FORMAT D2D_PixelFormat=D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);

Initialize()/Uninitialize()に初期化/終了コードを追加

Direct2Dではレンダーターゲットを選べるのですが、
今回は雛形(1)の修正、ということでDCRenderTargetにして、元の最終フレームDCにBindDC()します。

  HDC hdc=GetDC(NULL);
  hFrameDC=CreateCompatibleDC(NULL);
  hFrameBMP=CreateCompatibleBitmap(hdc, FrameWidth, FrameHeight);
  ReleaseDC(NULL, hdc);
  hOldFrameBMP=(HBITMAP)SelectObject(hFrameDC, hFrameBMP);

  D2D1_RENDER_TARGET_PROPERTIES render_props;
  render_props=D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D_PixelFormat,
                                            96.f, 96.f, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT);
  pD2D_Factory->CreateDCRenderTarget(&render_props, &pDCRT);

  RECT rect={0, 0, FrameWidth, FrameHeight};
  pDCRT->BindDC(hFrameDC, &rect);

  pDCRT->Release();
  pD2D_Factory->Release();
  CoUninitialize();

レンダーターゲットにD2DBitmapを作成、追加

24bitBGRビットマップファイルを読み込んで32bitBGRAに変換し、D2DBitmapとしてレンダーターゲットに追加します。
雛形(1)の修正の名残で、CreateDIBSection()で用意したバッファに書き込んだ32bitBGRAデータを
CreateBitmap()に渡してD2DBitmapを作成していますが、
CreateBitmap()にNULLを渡してレンダーターゲットに空のD2DBitmapを作っておき、
後からCopyFromMemory()で32bitBGRAデータをそこに書き込むこともできます。

      FILE *fp=fopen(ffilename, "rb");
      if(fp!=NULL){
        BITMAPFILEHEADER bf;
        fread(&bf, sizeof(BITMAPFILEHEADER), 1, fp);
        BITMAPINFOHEADER bi;
        fread(&bi, sizeof(BITMAPINFOHEADER), 1, fp);
        if(bi.biBitCount==24){
          if(hImageBMP1!=NULL){ DeleteObject(hImageBMP1); hImageBMP1=NULL; }

          ImageWidth1=bi.biWidth;
          ImageHeight1=bi.biHeight;

          BITMAPINFO *BitmapInfo=(BITMAPINFO *)calloc(sizeof(BITMAPV5HEADER), 1);

          BITMAPV5HEADER biv5={};
          memcpy(&biv5, &bi, sizeof(bi));
          biv5.bV5Size=sizeof(BITMAPV5HEADER);
          biv5.bV5BitCount=32;
          biv5.bV5SizeImage=((ImageWidth1*biv5.bV5BitCount+31)/32*4)*ImageHeight1;
          biv5.bV5Compression=BI_BITFIELDS;
          biv5.bV5RedMask  =0x00ff0000;
          biv5.bV5GreenMask=0x0000ff00;
          biv5.bV5BlueMask =0x000000ff;
          biv5.bV5AlphaMask=0xff000000;

          memcpy(&(BitmapInfo->bmiHeader), &biv5, sizeof(biv5));
          hImageBMP1=CreateDIBSection(NULL, BitmapInfo, DIB_RGB_COLORS, (void **)(&ImageBuffer1), NULL, 0);
          free(BitmapInfo);

          unsigned char *tbuf=(unsigned char *)malloc(bi.biSizeImage);
          fread(tbuf, bi.biSizeImage, 1, fp);

          int src_stride=(ImageWidth1*bi.biBitCount+31)/32*4;
          for(int i=0; i<ImageHeight1; i++){
            for(int j=0; j<ImageWidth1; j++){
              *(ImageBuffer1+i*ImageWidth1*4+j*4+0)=*(tbuf+(bi.biHeight-1-i)*src_stride+j*3+0); // B
              *(ImageBuffer1+i*ImageWidth1*4+j*4+1)=*(tbuf+(bi.biHeight-1-i)*src_stride+j*3+1); // G
              *(ImageBuffer1+i*ImageWidth1*4+j*4+2)=*(tbuf+(bi.biHeight-1-i)*src_stride+j*3+2); // R
              *(ImageBuffer1+i*ImageWidth1*4+j*4+3)=0xff;                                       // A
            }
          }
          free(tbuf);
        }
        fclose(fp);
        if(pD2D_Bitmap!=NULL) pD2D_Bitmap->Release();
        pDCRT->CreateBitmap(D2D1::SizeU(ImageWidth1, ImageHeight1),
                            ImageBuffer1, ImageWidth1*32/8,
                            D2D1::BitmapProperties(D2D_PixelFormat), &pD2D_Bitmap);
      }
    }

WM_PAINT時の描画コードの追加

追加したD2DBitmapを最終フレームに描画して、それをBitBlt()します。

  case WM_PAINT:
    {
      if(pD2D_Bitmap!=NULL){
        pDCRT->BeginDraw();
        pDCRT->SetTransform(D2D1::Matrix3x2F::Identity());
        pDCRT->DrawBitmap(pD2D_Bitmap, D2D1::RectF(0.f, 0.f, (float)ImageWidth1, (float)ImageHeight1),
                          1.f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
        pDCRT->EndDraw();
      }
      HDC hdc=GetDC(hDlgImg);
      BitBlt(hdc, 0, 0, FrameWidth, FrameHeight, hFrameDC, 0, 0, SRCCOPY);
      ReleaseDC(hDlgImg, hdc);
      ValidateRect(hDlgImg, NULL);
    }
    break;
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3