OleLoadPictureによるJpeg画像データの読み込み

VC++でWIN32APIベースの「画像を使うプログラム」を作っていると、意外に困ることが多いのが「画像の読み書き」です。Jpeg(jpgファイル)やPNG、GIFなどWindows標準のアプリでそのまま使える画像形式が、簡単には読み書きできません。

もっとも、jpgなど一部画像形式についてはOleLoadPictureを使用することで、比較的簡単に読み込めるようです。今回は、OleLoadPictureのテストとして「Jpeg画像データを読み込んだメモリブロック」をデコードし、32ビットDIBを作ってみることにしましょう。

OleLoadPicture()は、その名の通りOLEの機能を利用する形になるため、やや特殊な「手続き」「データ形式」が必要になります。OleLoadPicture()がデータとして受け取るのは、メモリブロック(バッファ)ではなくIStreamインターフェースを実装するオブジェクトで、データから作成された画像はIPictureインターフェースを持つオブジェクトに格納されます。
これらのオブジェクトは、使用後にRelease()を呼び出して解放する手続きも必要です。

まず、jpgファイルをメモリに読み込んでIStreamのオブジェクトを作ってみましょう。

ファイルの読み込み処理は普通にファイルを開いてReadFile()で行い、読み込むメモリは「移動可能メモリブロック」をロックする形で作成します。これは、IStreamは移動可能なメモリから作成する必要があるからです。

今回は、GlobalAlloc()にGMEM_MOVEABLEを指定して移動可能なメモリブロックを確保し、ロックしてからファイルのデータを書き込んでみました。

後は、ロックをはずせば「Jpeg画像データを読み込んだ移動可能メモリブロック」の出来上がり。これをCreateStreamOnHGlobal()に渡して、IStreamを作りましょう。

/* 画像ファイルオープン */
hFile = CreateFile(lpszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

/* ファイルサイズ取得 */
dwFileSize = GetFileSize(hFile, NULL);

/* 画像ファイルデータ格納用メモリブロック確保 */
hBuf = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);

/* メモリブロックをロックしアドレスを取得 */
lpBuf = GlobalLock(hBuf);

/* 画像ファイルのデータをメモリブロックに読み込む */
ReadFile(hFile, lpBuf, GetFileSize(hFile, NULL), &dwLoadSize, NULL);

CloseHandle(hFile);

/* メモリブロックのロック解除 */
GlobalUnlock(hBuf);

/* メモリブロックからIStreamを作成 */
CreateStreamOnHGlobal(hBuf, TRUE, &isImage);

画像データを読み込むためのIStreamができたら、OleLoadPicture()に渡してIPictureを取得します。

/* 画像ファイルのストリームから画像オブジェクトを作成 */
OleLoadPicture(isImage, dwFileSize, FALSE, &IID_IPicture, (LPVOID*)&ipicImage);

続いて、IPictureからGDIのHBITMAPとしても利用できるハンドルを取得します。HBITMAPが取得できたら、後はBITMAPのDIB変換と同様の方法でDIBを作成しましょう。

これら一連の処理は、関数loadImage()にまとめてあります。

プログラムソース表示(VisalC++用Cソースファイル)

ソース中で読み込む画像ファイルを指定しているので、ここを適当なjpgファイルのパスに書き換えて実行してみてください。Vistaで試してみると、OleLoadPictureはjpgだけでなくGIFを読み込むこともできますが、pngには未対応のようですね。

Visual VC++ 2008 Expressではそのままビルドできますが、コンパイラによってはライブラリ周りの設定が必要かもしれません。


プログラミング資料庫 > Windowsプログラミング研究室