メモリ上でのビットマップ描画

[戻る]
ビットマッパー(ビギナー) 2002/10/18(金) 00:47:47
はじめまして。
現在あるデータを白黒ビットマップに変換するプログラムを作成しております。
(※ウインドウには表示せずにファイルに保存します。)
変換の際、Polygonファンクションを使用したいのですが、このファンクションを
使用するには、DCのハンドルが必要です。そこで、

hBitmap = CreateDIBSection( NULL , bmpInfo , DIB_RGB_COLORS , (void **) 
&bPixelBits , NULL , 0 );
(ここでビットマップを作成)

bPixelBits = ( BYTE *) malloc ( 128*786 );
(XGAの大きさを持つビットマップ領域を確保)

for( i=0 ; i<128*768 ; i++ )  //ビットマップ初期化
   *( bPixelBits + i )= 0xFF ;

hdcmem = CreateCompatibleDC ( NULL );
(メモリデバイスコンテキストを取得)

SelectObject( hdcmem , hBitmap );
(メモリデバイスコンテキストにGDIビットマップオブジェクトを選択)

SetPolyFillMode( hdcmem , WINDING );
Polygon(hdcmem , po , 8);
(描画)

といいうような流れでbPixelBitsが指す領域にピクセルデータを格納していきたいと
考えております。しかし、実際には、初期化されたままで、うまく格納されていません。

私自身、大きな勘違いをしているかもしれませんが、よろしくおねがいします。

ビットマッパー(ビギナー) 2002/10/18(金) 00:50:28
〜追記〜
開発環境
OS  : Windows2000
Ver : VC++6.0
MFCは使用しておりません。

以上です。

2002/10/18(金) 01:43:23
> hBitmap = CreateDIBSection( NULL , bmpInfo , DIB_RGB_COLORS ,
> (void **) &bPixelBits , NULL , 0 );
>(ここでビットマップを作成)

が成功していることは確認なさっているのでしょうか?
引数 pPixelBits にはDIBの画像へのポインターがこのAPIに
成功した場合渡ってくることはご存知ですね?
勿論、ポインター bmpInfo が指す BITMAPINFO 構造体の中身がどうなって
いるか分らないのでこのAPI呼び出しに続く

> bPixelBits = ( BYTE *) malloc ( 128*786 );
>(XGAの大きさを持つビットマップ領域を確保)
で何をしようとしているのか(*1)が上手く捉えられないのですが、少なくとも
せっかくもらってきたポインターを壊してしまうかもしれないことは分ります

(*1: 何ビットカラー(ピクセルのビット数)のDIBにしているのかが不明
なのでXGAの広さが 128 * 786 で十分なのかは私にはわかりません。
それに8ビットカラー以下ならパレットがあるので扱いが少し面倒になります
もし、パレットが必要な場合はパレットも作成して、自分のパレットが有効に
なるようにしなければ適切な画像は出ないかもしれません)

仮に CreateDIBSection APIに成功したとしても pPixelBits の値を
変えているのであなたが初期化したと思っているのはDIBセクションの
預かり知らぬ領域です

ビットマッパー(ビギナー) 2002/10/18(金) 02:12:25
さっそくのお返事ありがとうございます。

>引数 pPixelBits にはDIBの画像へのポインターがこのAPIに
>成功した場合渡ってくることはご存知ですね?

pPixelBitsにはDIB画像へのポインターのポインタがはいるのですよね?
もしそうであるならばこのpPixelBitsのアドレスがはいるということで、
実際にはDIB画像へのポインタでは無いような気がするのですが・・・。

(*1: 何ビットカラー(ピクセルのビット数)のDIBにしているのかが不明
なのでXGAの広さが 128 * 786 で十分なのかは私にはわかりません。

白黒2ビットです。

>仮に CreateDIBSection APIに成功したとしても pPixelBits の値を
>変えているのであなたが初期化したと思っているのはDIBセクションの
>預かり知らぬ領域です

実際にはこのXGAの領域はどこで確保されているのでしょうか?
勉強不足で申し訳ありません・・・(T_T)

ご参考までに・・・私が設定しているビットマップのヘッダです。
// ビットマップのヘッダ設定
bmpFileHeader.bfType = 'M'*256+'B';
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
+8+128*768;
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+8;
rgbquad1.rgbBlue = 0x00;
rgbquad1.rgbGreen = 0x00;
rgbquad1.rgbRed = 0x00;
rgbquad1.rgbReserved = 0x00;
rgbquad2.rgbBlue = 0xFF;
rgbquad2.rgbGreen = 0xFF;
rgbquad2.rgbRed = 0xFF;
rgbquad2.rgbReserved = 0xFF;
bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biWidth = 1024;
bmpInfoHeader.biHeight = 768;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biBitCount = 1;
bmpInfoHeader.biCompression = BI_RGB;
bmpInfoHeader.biSizeImage = 128*768;
bmpInfoHeader.biXPelsPerMeter = 2834;
bmpInfoHeader.biYPelsPerMeter = 2834;
bmpInfoHeader.biClrUsed = 2;
bmpInfoHeader.biClrImportant = 2;

2002/10/18(金) 02:35:16
> pPixelBitsにはDIB画像へのポインターのポインタがはいるのですよね?
> もしそうであるならばこのpPixelBitsのアドレスがはいるということで、
> 実際にはDIB画像へのポインタでは無いような気がするのですが・・・。

CreateDIBSection の説明を NSDN ライブラリー(VCのヘルプ)
で調べてよく読みましょう

わざわざ void **ppvBits と仮引数で型の宣言をしていますよ
だからこそ、実引数では (void **)&pPixelBits としているのでしょう?

> 実際にはこのXGAの領域はどこで確保されているのでしょうか?
CreateDIBSection が確保します。だからこそ成功した場合にDIB
のイメージ領域のポインターが返せるのでしょう

ビットマッパー(ビギナー) 2002/10/18(金) 03:10:00
アドバイスありがとうございます。
どうもCreateDIBSection
hBitmap = CreateDIBSection( NULL , bmpInfo , DIB_RGB_COLORS , (void **) 
&bPixelBits , NULL , 0 );

ビットマッパー(ビギナー) 2002/10/18(金) 03:28:34
↑すいません。間違えました。

本題ですが、
どうもCreateDIBSectionが失敗していることがわかりました。
--------------------------------------------------------------------------
hBitmap = CreateDIBSection( NULL , bmpInfo , DIB_RGB_COLORS , (void **) 
&bPixelBits , NULL , 0 );
--------------------------------------------------------------------------

間違った箇所はわかったのですが・・・
まだメモリデバイスコンテキストを完全に理解していないため、どこをどう修正すればよいか
さっぱりです。

そもそも第一引数のには何のDCのハンドルを入れたらいいのでしょうか?

2002/10/18(金) 03:31:54
> アドバイスありがとうございます。

どういたしまして。
でも、アドバイスしたつもりは無いんですけどねー

最近はアドバイスという言葉の意味が変わったんでしょうか?

2002/10/18(金) 03:37:04
> そもそも第一引数のには何のDCのハンドルを入れたらいいのでしょうか?
扱いたいDCのハンドルでしょう

メモリーDCかもしれないし、ウィンドーのDCかもしれないし、
プリンターのDCかもしれないし、スクリーンのDCかもしれませんね

ビットマッパー(ビギナー) 2002/10/18(金) 04:10:30
>扱いたいDCのハンドルでしょう
となると私は、メモリーDCですね。
そこで、
---------------------------------------------------------------------------
hdcmem = CreateCompatibleDC ( NULL );
hBitmap = CreateDIBSection( hdcmem , (const BITMAPINFO*)&bmpInfoHeader , 
DIB_RGB_COLORS , (void **) &bPixelBits , NULL , 0 );
----------------------------------------------------------------------
と修正すると、CreateDIBSectionがうまく実行されました。

そして、実際にメモリをいじくれると思ったんですが、

for( i=0 ; i<128*768 ; i++ ) // ビットマップ初期化
  *( bPixelBits + i )= 0xFF ;

と実行して、出力されたビットマップを見てみますと、
ピクセルデータが入っておらず、ヘッダしかないビットマップが作成されてました。

このCreateDIBSectionの便利な面として、直接操作が可能であると思っていたのですが、
実際はどうなのでしょうか?

2002/10/18(金) 09:08:47
> 出力されたビットマップを見てみますと、
> ピクセルデータが入っておらず、ヘッダしかないビットマップが作成されてました。
>
> このCreateDIBSectionの便利な面として、直接操作が可能であると思っていたのですが、
> 実際はどうなのでしょうか?
どこにどのように出力したのですか?
もし、画面やプリンターに出力したのであればヘッダーしかないことは直ちには
分らないでしょうから、ファイルに出力したものと思いますが、そうだとしたら
どのような出力コードなのかが分らないと何とも言えません

ビットマッパー(ビギナー) 2002/10/18(金) 09:15:53
出力先はファイルです。
-----------------------------------------------------------------------------
wsprintf(strFileName , TEXT("bitmap.bmp") );
hFile = CreateFile(strFileName , GENERIC_WRITE , 0 , NULL , CREATE_ALWAYS , 
FILE_ATTRIBUTE_NORMAL , NULL);
    
WriteFile( hFile , &bmpFileHeader , sizeof (BITMAPFILEHEADER) , &dwBytes , 
NULL);
WriteFile( hFile , &bmpInfoHeader , sizeof (BITMAPINFOHEADER) , &dwBytes , 
NULL);
WriteFile( hFile , &rgbquad1 , 4 , &dwBytes , NULL);
WriteFile( hFile , &rgbquad2 , 4 , &dwBytes , NULL);
WriteFile( hFile , bPixelBits , 128*768 , &dwBytes , NULL);
------------------------------------------------------------------------------

for( i=0 ; i<128*768 ; i++ ) 
  *( bPixelBits + i )= 0xFF ;
実際にこの操作をすると、1024×768の領域全体に"1"が入っているものと思っていたのです
が、そうではありませんでした。

bPixelBits =(BYTE *)malloc (128*768)で領域を確保してやると、
上の操作でXGAのビットマップファイルを作ることができたのですが・・・・
(あたりまえですけど^^;)

ビットマッパー(ビギナー) 2002/10/18(金) 09:20:45
一つ気になる点があるんですが、

”メモリデバイスコンテキストを作成するためには、実デバイスのデバイスコンテキストハンド
ルがなければならない”とテキストに書いてあるんですけど、今回、特にウインドウに表示させ
ることもないので、このデバイスのデバイスコンテキストハンドルが存在してません。

実際には
hdcmem = CreateCompatibleDC ( NULL );
のようにhDCをNULLとしています。

このあたりは問題にならないのでしょうか?

2002/10/18(金) 10:22:56
こちらから質問しないと適切な状況が得られないというのはなんとか
ならないもんでしょうか?
(無意味にスレッドが長くなるだけですね)

ところで、あなたから提示のあった今回のファイル出力のコードから
判断する限り、妙なコードとは思えません(読解力が足りないだけ?)
> for( i=0 ; i<128*768 ; i++ ) 
>   *( bPixelBits + i )= 0xFF ;
> 実際にこの操作をすると、1024×768の領域全体に"1"が入っているものと思っていたのです
> が、そうではありませんでした。

pPixelBits が CreateDIBSection で得られた値をそのまま使っているとしたら私には
何が悪いのか分りません
ところで出力の結果はどのようにして検査なさったのでしょうか?
他に思いつく点は
for (i=0; i <128*768; i++) {
  *(pPixelBits +i) =0xff;
}
の結果 pPixelBits の指す領域の値はどうなっていたのでしょうか?
予定通りになっていたとしたら、ファイルに書き出す時点で適切な値のままだと
いうことは確かめましたか?

> hdcmem = CreateCompatibleDC ( NULL );
> のようにhDCをNULLとしています。

これも CreateCompatibleDC の解説をよく読めば分ることだと思います。
調べたけれど、それでも不安だということですか?

ビットマッパー(ビギナー) 2002/10/18(金) 11:00:05
>こちらから質問しないと適切な状況が得られないというのはなんとか
>ならないもんでしょうか?

島さん、ご迷惑おかけしました。
楽な方、楽な方へと向かっておりました。
気持ちを新たに気合を入れて頑張りたいと思います。

PS:たびたびコメントしていただきありがとうございました。

2002/10/18(金) 11:09:29
> 島さん、ご迷惑おかけしました。

そうではなくて、他人に自分の状況を適切に無駄なく、漏れなく
説明する努力をしましょうということですよ。迷惑だとは感じていませんし、
そのように受取られるとは思いもしませんでした

ビットマッパー(ビギナー) 2002/10/18(金) 14:10:45
[[解決]]
解決しました。
ありがとうございました。

古いスレッドには追加発言できません。