• ベストアンサー

MFC - ダイアログボックスのPictureControlへの画像表示

はじめまして。 現在MFCにおいて、ダイアログ形式のアプリケーションを作成しています。環境はVisual Studio 2005になります。 内容はWebカメラからのキャプチャを行い、そのキャプチャされた画像をダイアログ上に配置したPictureControlへ表示するというものです。 キャプチャされた画像は、1チャネルのグレースケールでありunsigned char型の1次元配列で格納されています。よってビットマップとして表示するには自身で構造体BITMAPINFOを作成しなければなりません。現状以下のように作成したのですが、うまく表示されません。 画像サイズは 320×240 です。 PictureControlのIDを IDC_BITMAP と設定し、 画素情報が格納されている配列を m_pbit とします。 int i; CWnd *pWnd = GetDlgItem( IDC_BITMAP ); CDC *Capt = pWnd->GetDC(); BITMAPINFO bmif; bmif.bmiHeader.biBitCount   =8; bmif.bmiHeader.biClrImportant =0; bmif.bmiHeader.biClrUsed    =256; bmif.bmiHeader.biCompression  =0; bmif.bmiHeader.biHeight     =240; bmif.bmiHeader.biPlanes     =1; bmif.bmiHeader.biSize      =sizeof(BITMAPINFOHEADER); bmif.bmiHeader.biSizeImage   =320*240; bmif.bmiHeader.biWidth     =320; bmif.bmiHeader.biXPelsPerMeter =0; bmif.bmiHeader.biYPelsPerMeter =0; for(i=0; i<256; i++){  bmif.bmiColors[i].rgbBlue = i;  bmif.bmiColors[i].rgbGreen = i;  bmif.bmiColors[i].rgbRed  = i;  bmif.bmiColors[i].rgbReserved = 0; } SetDIBitsToDevice(Capt->m_hDC, 0, 0, 320, 240, 0, 0, 0, 240, m_pbit, &bmif, DIB_RGB_COLORS); グレースケール画像なので配列bmiColorsは全て同色としました。 また、PictureControlのTypeをオーナ描画など全てのTypeを試しましたが、表示されませんでした。 必ずPictureControlに描画しなければならないという決まりはないのですが、ダイアログボックスにビットマップを表示するにはPictureControlだと考え、それに表示するようプログラムを組みました。 画素情報(グレースケールの輝度情報)のみ既知である状態からビットマップをダイアログに表示するためには他に方法があるのでしょうか? 上記のプログラムにおける間違い、またその他の方法についてアドバイスを頂けたらと思います。 よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

 こんにちは。  パレットサイズ(biClrUsedの数字)の分だけRGBQUADの配列を拡張して割り当てないといけません。  正しくは、以下です。実際には、予め割り当てておくのが良いでしょう。 //割り当てる LPBITMAPINFO pbmi = static_cast<LPBITMAPINFO>(::malloc(sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 256))); pbmi->bmiHeader.biBitCount=8; pbmi->bmiHeader.biClrImportant=0; pbmi->bmiHeader.biClrUsed=256; pbmi->bmiHeader.biCompression=0; pbmi->bmiHeader.biHeight=240; pbmi->bmiHeader.biPlanes=1; pbmi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biSizeImage=320*240; pbmi->bmiHeader.biWidth=320; pbmi->bmiHeader.biXPelsPerMeter=0; pbmi->bmiHeader.biYPelsPerMeter=0; for(i=0;i<256;i++) { pbmi->bmiColors[i].rgbBlue=i; pbmi->bmiColors[i].rgbGreen=i; pbmi->bmiColors[i].rgbRed=i; pbmi->bmiColors[i].rgbReserved=0; } ::SetDIBitsToDevice(Capt->m_hDC, 0, 0, 320, 240, 0, 0, 0, 240, m_pbit, pbmi, DIB_RGB_COLORS); //開放する ::free(pbmi); -------------------------------------------------------------------------------------------------------------- 強引ですが、以下の様なやり方も出来ます。 struct BMI { BITMAPINFOHEADER bmiHeader; RGBQUAD arrPalette[256]; }; //キャストする BMI bmi; LPBITMAPINFO pbmi = reinterpret_cast<LPBITMAPINFO>(&bmi); //ヘッダとパレットの代入をする pbmi->bmiHeader.biBitCount=... //使用する ::SetDIBitsToDevice(...) //開放は必要ない

happy-hack
質問者

お礼

返信ありがとうございました。 BITMAPINFOHEADER + RGBQUADのメモリ領域を確保しなければいけなかったのですね。適切なアドバイスに感謝します。 キャプチャの方も無事にPictureControlへ出力することができました。 ありがとうございます。

その他の回答 (1)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

リソースエディタでピクチャーコントロールのTypeは変更なさいましたか? ピクチャーコントロールを追加しただけではTypeは『フレーム』になっています この状態では ピクチャーコントロールに対してSetBitmapを行ってもイメージを表示しません Typeを『ビットマップ』に変更しましょう プロパティIDも『IDC_STATIC』以外にしたほうがいいでしょう CBitmapクラスを使うというのも一つの手ですよ ダイアログクラスのメンバーに CBbitmap m_bmpObj などを追加して ピクチャーボックスにセットするときに m_bmpObj.DeleteObject(); // orgBmp[320 x 240]にグレースケールのデータがあるとして char* pbuf = (char*)calloc( 320*240, sizeof(RGBQUAD) ) for ( int y = 0; y < 240; y++ ) {   for ( int x = 0; x < 320; x++ ) {     pbuf[ y * 1280 * ( x * 4 ) + 0 ] = orgBmp[ y * 320 + x ];     pbuf[ y * 1280 * ( x * 4 ) + 1 ] = orgBmp[ y * 320 + x ];     pbuf[ y * 1280 * ( x * 4 ) + 2 ] = orgBmp[ y * 320 + x ];     pbuf[ y * 1280 * ( x * 4 ) + 3 ] = 0;   } } m_bmpObj.CreateBitmap( 320, 240, 1, 32, pbuf ); // m_ctlPictureはピクチャーボックスのコントロール変数 m_ctlPicture.SetBitmap( m_bmpObj ); // または // ((CStatic*)GetDlgItem(IDC_PICTURE1))->SetBitmap( m_bmpObj ); free( pbuf );

happy-hack
質問者

お礼

返信ありがとうございます。 確かにCBitmapクラスを使用し、1チャネルを3チャネルに変換後に表示する方法もありますね。参考にさせていただきます。ただ pbuf[ y * 1280 * ( x * 4 ) + 0 ] は pbuf[ y * 1280 + ( x * 4 ) + 0 ] ですね。 丁寧に解説いただきありがとうございました。