拡張メタファイルをビットマップに変換するには


勉強中  2007-01-30 01:37:25  No: 64319

拡張メタファイルを読み込み、そのファイルをビットマップファイルに変換する方法についてご教授願います。
#Visual Basicについては過去ログにありましたが、Visual C++ではどのように使えばよいか分かりませんでしたので。

環境は、Visual C++ 6.0です。


gak  2007-01-30 02:43:01  No: 64320

1、GetEnhMetaFile() で拡張メタファイルハンドル取得
2、PlayEnhMetaFile() でメモリDCに描画
3、GetDIBits() でPixelBit情報取得(or 元から CreateDIBSection() で HBITMAP を作成)
4、BMPヘッダを付けてファイルに保存

若しくは

1、Gdiplus の Gdiplus::Image クラスに読み込み
2、Gdiplus::Image::Save() で保存


勉強中  2007-01-30 05:04:43  No: 64321

早速の回答ありがとうございます。

C言語で作成しようと考えており(C++は分からないので(泣))、
前者の3について教えてください。

GetDIBitsにはHBITMAP等のパラメタが必要と思われますが、
どのようなものを指定すればよいのでしょうか?
#BITMAPを作成していないのに、BITMAPのハンドルを渡す??

できれば3〜の処理について、詳しく教えてください。
#例などがあると助かります。

<特に分からない点>
・GetDIBits()に渡すパラメタ:HBITMAPには何を渡せばよいのでしょう?
・BITMAPのサイズについて   :EMFと同じサイズとできるのでしょうか?
                             EMFのRECT構造体から計算??


gak  2007-01-30 21:48:37  No: 64322

----------------
 HENHMETAFILE emf;
 ENHMETAHEADER header;
 SIZE size
 RECT rect;
 HDC pdc, hdc;
 HBITMAP hbm;
 HGDIOBJ old;

 emf = GetEnhMetaFile(...);
 GetEnhMetaFileHeader(emf, sizeof(header), &header);
 pdc = GetDC(NULL);
 /* 0.01mm -> pixel */
 size.cx = ::MulDiv(header.rclFrame.right - header.rclFrame.left, GetDeviceCaps(pdc, LOGPIXELSX), 2540);
 size.cy = ::MulDiv(header.rclFrame.bottom - header.rclFrame.top, GetDeviceCaps(pdc, LOGPIXELSY), 2540);
 hdc = CreateCompatibleDC(pdc);
 hbm = CreateCompatibleBitmap(pdc, size.cx, size.cy);
 old = SelectObject(hdc, hbm);
 SetRect(&rect, 0, 0, size.cx, size.cy);
 /* GetEnhMetaFilePaletteEntries() */
 PlayEnhMetaFile(hdc, emf, &rect);
 SelectObject(hdc, old);
    :
 GetDibits(, hbm, ...);
    :
----------------

画面色深度が16Bit環境等で色情報が欠損するのが嫌なら CreateCompatibleBitmap() では無く
CreateDIBSection() の使用(GetDibits() は不要になる)を勧める
ていうかこのケースでは処理速度等の面から見ても CreateDIBSection() の方が良さそう


シャノン  2007-01-30 23:01:27  No: 64323

> 画面色深度が16Bit環境等で色情報が欠損するのが嫌ならCreateCompatibleBitmap() では無く
> CreateDIBSection() の使用(GetDibits() は不要になる)を勧める

その場合、
・16bitのDCにPlayEnhMetaFileすることになる
・24bitのビットマップを16bitのDCに選択することになる
という2点には問題が無いのだろうか。

あと、元ファイルが256色以下だった場合、パレットも再現した方がよいのではないか?
ただ、元ファイルが256色以下であればパレットエントリ数からビット数が求められるかもしれないが、16Bit以上だったらわかんないんだよなぁ(メタファイルヘッダにビット深度はない。メタファイル作成時のDCの色深度だと思うのだが)。
とりあえず24Bitで作っておけばいいか。


gak  2007-01-31 00:32:51  No: 64324

> ・16bitのDCにPlayEnhMetaFileすることになる
> ・24bitのビットマップを16bitのDCに選択することになる
> という2点には問題が無いのだろうか。
昔、塗り潰し(どっちだったかは忘れたが FillRect() か CDC::FillSolidRect())した際、
CompatibleなBitmapを16BitのDCに選択したものでは色情報が欠損したが、
24bitのビットマップを16bitのDCに選択したものでは大丈夫だった。
この事等から CreateDIBSection() で作成したHBITMAPはその辺りを旨い事してくれるのだろう、
と勝手に思っている。(到底正しいとは断言できないし、公式な情報も知らない)

> あと、元ファイルが256色以下だった場合、パレットも再現した方がよいのではないか?
yes(仕様にも依るだろうけど)
ソースが長くなるのが嫌だったのでソースではコメント化して省いた…


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加