プロが教えるわが家の防犯対策術!

はじめまして。
現在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だと考え、それに表示するようプログラムを組みました。

画素情報(グレースケールの輝度情報)のみ既知である状態からビットマップをダイアログに表示するためには他に方法があるのでしょうか?
上記のプログラムにおける間違い、またその他の方法についてアドバイスを頂けたらと思います。

よろしくお願いいたします。

A 回答 (2件)

 こんにちは。


 パレットサイズ(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(...)

//開放は必要ない
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/10/04 20:40

リソースエディタでピクチャーコントロールの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 );
    • good
    • 1
この回答へのお礼

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

pbuf[ y * 1280 + ( x * 4 ) + 0 ]
ですね。
丁寧に解説いただきありがとうございました。

お礼日時:2008/10/04 20:53

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A