LoadImageのLR_CREATEDIBSECTION時の処理

[戻る]
メアリ 2005/06/27(月) 15:02:16
はじめまして。初めて投稿させていただきます。
環境はwin2000 .NET win32アプリで作成しています。

8bitのビットマップを読込みビットマップ構造体より2倍のサイズを持つ
ビットマップを作成しようとしています。
 CBitmap cbmp1,cbmp2;
 HBITMAP hBmp = (HBITMAP)LoadImage( AfxGetApp()->m_hInstance, "bit08.bmp",
        IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
 cbmp1.Attach(hBmp);
 cbmp1.GetBitmap( &bmp );             // ビットマップの詳細を取得
 bmp.bmHeight = bmp.bmHeight << 1;    // 2倍
 bmp.bmWidth = bmp.bmWidth  << 1;    // 2倍
 bmp.bmWidthBytes = (bmp.bmBitsPixel/8)*bmp.bmWidth;
 cbmp2.CreateBitmapIndirect(&bmp);

を実行するとCreateBitmapIndirectで0が返ってきます。
LoadImageのLR_CREATEDIBSECTIONフラグを消すと正常に0以外が返ってきます。
LR_CREATEDIBSECTIONフラグを追加した時の処理はどうすればいいのでしょうか?
ご教授おねがいします。

メアリ 2005/06/27(月) 16:47:52
すいません。
環境間違えました。MFCダイアログベースです。

シャノン 2005/06/27(月) 19:36:20
> bmp.bmWidthBytes = (bmp.bmBitsPixel/8)*bmp.bmWidth;

この計算じゃダメじゃないですか?
WidthBytes は4の倍数に揃えなければなりません。
例えば、BitsPixel が 24 で Width が 5 だったら、上の式では 24 / 8 * 5 = 15 ですが、
最寄の4の倍数に揃えるため、実際には 16 にしなければなりません。

メアリ 2005/06/28(火) 10:26:57
シャノンさん、ご返答ありがとうございます。
BitsPixel = 8; Width = 160; 一定なのですがエラーが返ってきます。
どうもbmHeightかbmWidthで読込んだbmp値より1pixelでも大きく指定すると
CreateBitmapIndirectでエラーが返るみたいです。
読込んだビットマップより2倍の領域を確保したい場合は
CreateBitmapIndirect関数を使用するのではないのでしょうか…?

dairygoods 2005/06/28(火) 10:39:42
> bmp.bmHeight = bmp.bmHeight << 1;    // 2倍
> bmp.bmWidth = bmp.bmWidth  << 1;    // 2倍
> bmp.bmWidthBytes = (bmp.bmBitsPixel/8)*bmp.bmWidth;

これらを修正しておいて、
bmp.bmBits ほったらかしなのがマズいような...

メアリ 2005/06/28(火) 17:45:17
dairygoodsさん ご返答ありがとうございます。
bmp.bmBitsは変更無しでいいかと思ってました…。
調べてみましたが領域が2倍時のピクセルビットの配列の変更の仕方がよく分かりません…。
宜しかったらご教授お願いします。

dairygoods 2005/06/29(水) 10:05:28
> 調べてみましたが領域が2倍時のピクセルビットの配列の変更の仕方がよく分かりませ
ん…。

長さが、bmHeight × bmWidthBytes × (BitsPixel/8) で、
各ピクセルの値が、左上から順番に格納されます。

メアリ 2005/06/29(水) 18:10:37
dairygoodsさんありがとうございます。
LPBYTE bmByte =new BYTE[bmp.bmHeight * bmp.bmWidthBytes * (bmp.bmBitsPixel/8)];
bmp.bmBits = bmByte;
で0以外が返るようになりました。
しかし作成したCBitmapに画像をセットし保存するとモノクロ1bitで表現されています。
LR_CREATEDIBSECTIONフラグを消すと正常?にOS/2形式で保存されるのでソースが間違って
いるわけではないと思うのですが…。
読込む画像が8bitなのにwindow形式8bitとして保存する為にはやはりRGBQUADを使うしか
ないのでしょうか?

メアリ 2005/06/29(水) 18:23:40
すいません。8bitで保存できました。
がやはり画像が表示されません。
LR_CREATEDIBSECTIONフラグを消すとOS/2形式で正常に保存されるのは
変わらないのですが…
LR_CREATEDIBSECTIONフラグを入れることでなにか別の処理が必要になるのでしょうか?

シャノン 2005/06/29(水) 18:44:27
> LPBYTE bmByte =new BYTE[bmp.bmHeight * bmp.bmWidthBytes * 
(bmp.bmBitsPixel/8)];
> bmp.bmBits = bmByte;

これでは、ピクセルデータを格納するためのメモリ領域を確保しただけで、その中身は不定で
す。
これに、ビットマップのピクセルデータを格納してやらなければなりません。

メアリ 2005/06/29(水) 19:29:11
シャノンさんご返答有難うございます。
ピクセルデータですか…調べてもピンとこない…
まだまだ勉強不足ですね。
理解できるように頑張ってみます。

dairygoods 2005/06/29(水) 20:02:05
> ピクセルデータですか…調べてもピンとこない…

点の色情報が配列に入ってるだけですよ。

例えば、1つの点の情報が8ビットの2x2のビットマップなら、
char bits[4];
bits[0] = 0; // 左上(0,0)の点は、0番目の色
bits[1] = 1; // 右上(1,0)の点は、1番目の色
bits[2] = 0; // 左下(0,1)の点は、0番目の色
bits[3] = 3; // 右下(1,1)の点は、3番目の色

メアリ 2005/06/30(木) 10:25:56
dairygoodsさん、ご返答有難うございます。
> 例えば、1つの点の情報が8ビットの2x2のビットマップなら
>char bits[4];
>bits[0] = 0; // 左上(0,0)の点は、0番目の色
>bits[1] = 1; // 右上(1,0)の点は、1番目の色

ということは読込んだビットマップの左上から1ドットづつの色を取得して順番に
配列に入れるということなんでしょうか?

シャノン 2005/06/30(木) 11:00:38
> ということは読込んだビットマップの左上から1ドットづつの色を取得して順番に
> 配列に入れるということなんでしょうか?

そうです。ただし、2点注意。

1.今回、2倍に拡大したビットマップを作るのですから、ピクセルのマップ先の座標を計算する
必要があります。
つまり、元ピクセルがこう

■□
□■

だったら、これを

■×□×
××××
□×■×
××××

にしなければなりません
(×は拡大によって新たに生まれたピクセル。どうにかして補完する必要があります)。

例えばこう。

■■□□
■■□□
□□■■
□□■■

2.あまり気にとめなくていいことだと思いますが、

> 読込んだビットマップの左上から

一般にビットマップはボトムアップ、つまり、下から上へと描画されます。
ファイルの先頭にあるデータは、画像の左下ピクセルのものになります。

メアリ 2005/06/30(木) 13:19:44
シャノンさん、分かりやすい説明有難うございます。
領域を2倍にして読込んだビットマップを縦横斜めに同じ画像を計4枚を表示させる場合の
bmBits はこんな感じになるのでしょうか?
LPBYTE bmByte =new BYTE[bmp.bmHeight * bmp.bmWidthBytes * (bmp.bmBitsPixel/8)];
LPBYTE pBuff = new BYTE[bmp.bmHeight * bmp.bmWidthBytes];

for( nCnt=0; nCnt < 4; nCnt++ ){
  cbmp2.GetBitmapBits(bmp.bmWidthBytes * bmp.bmWidth, pBuff);
  for( int i=0; i< bmp.bmHeight; i++  ){
    ::memcpy( &(bmByte[ (i * bmp.bmWidthBytes * 2) +
    ((nCnt%2)*bmp.bmWidthBytes) + ((nCnt/2)*bmp.bmHeight*2*bmp.bmWidthBytes) ]),
    &(pBuff[i * bmp.bmWidthBytes]), bmp.bmWidthBytes );
  }
}
bmp.bmBits = bmByte;
cbmp2.CreateBitmapIndirect(&bmp);

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