第7回 画像ファイルの読込みと表示

 

BTMemoではJPEG等の画像ファイルのリンクを開いて画像を表示することができます。

私自身は画像ファイルのファイルフォーマットなど一切知らないのですが、

OLE関連のAPIを使用すると比較的簡単に画像ファイルの読込みと表示を行うことができます。

 

もちろんこれで全ての形式の画像ファイルを処理できるわけではなく、処理できるのは

ビットマップ形式、アイコン形式、メタファイル形式、GIF形式、JPEG形式だけです。

またこれらの形式でもさまざまなバリエーションがあり、その全てを扱うことができるものなのかどうか

確認しておりません。(今のところ表示できないファイルはありませんでした)

 

 

(1)画像ファイルからビットマップハンドルを取り出す

//ファイルのパス名を指定して、画像データを取り出す関数を仮定します。

void GetImage( char *pszFileName )

{

        // 画像ファイルのパス名をOLEのバリアント型に変換します

        COleVariant varName(pszFileName);

 

        //OLEを介して画像ファイルにリンクします

        LPDISPATCH pDispatch;

        OleLoadPictureFile(varName, &pDispatch);

 

        //OLEのインタフェースを取り出します

        CPictureHolder *pPictureHolder = new CPictureHolder;

        pPictureHolder ->SetPictureDispatch((LPPICTUREDISP)pDispatch);

        IPicture *pPicture = pPictureHolder ->m_pPict;

 

        //取得したインタフェースを利用してビットマップハンドルを得ます

        OLE_HANDLE hBmp;

        pPicture ->get_Handle(&hBmp);

 

        //ここで取得したビットマップを処理します。

        HBITMAP hBmp2 = (HBITMAP) hBmp; //キャストすればそのままビットマップハンドルとして使用できます

                                      //通常(?)はビットマップハンドルから画像情報を取り出しておきます

 

        //使い終わったビットマップハンドルは削除しましょう

        DeleteObject((HBITMAP) hBmp);

 

        //使い終わったクラスも破棄しましょう

        delete pPictureHolder ;

}

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

備考:

BTMemoの最初の版ではこの方式を使用していました。

BTMemoでは画像を直接貼りこむことができますが、そこではビットマップハンドルをベースに処理を構築してあるので、

下位レベルの処理を共有できて便利だったからです。

 

しかし、画像表示の際は StretchDIBits などを使用することになりますが、これらを使うと、画像を縮小したとき綺麗に表示できませんでした、

そのため、今ではこの方法は使用していません。

 

 

 

(2)画像ファイルからピクチャーを取り出す

//ファイルのパス名を指定して、ピクチャーを取り出す関数を仮定します。

LPPICTURE GetImage(char *pszFileName)

{

        // ファイルをグローバルメモリに読み込みます

        DWORD nReadByte;

        HANDLE hFile = CreateFile(szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

        LONG lSize = GetFileSize(hFile, NULL);

        HGLOBAL hGlobal = ::GlobalAlloc(GPTR, lSize);

        ::ReadFile(hFile, hGlobal, lSize, &nReadByte, NULL);

        ::CloseHandle(hFile);

 

        // ファイルの内容をストリームに変換します

        LPSTREAM pstm = NULL;

        ::CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);

 

        //ストリームからピクチャを取り出します

        LPPICTURE pPicture;

        ::OleLoadPicture(pstm, lSize, FALSE, IID_IPicture, (LPVOID *)&pPicture);

 

        //使い終わったメモリを廃棄します

        ::GlobalFree(hGlobal);

 

        return pPicture;

}

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

備考:

ここで返却されたピクチャーを描画する場合は pPicture->Render(); を使用します。

これを使うことで縮小画像が綺麗に表示できるようになりました。

なお、この関数ではY軸の方向がGDIの座標系とは反対方向に向いているので注意が必要です。

(GDIと同じつもりで描画すると上下反対に表示されてしまいます)

また、ここで返却されたピクチャーが不要になった場合は、pPicture->Release(); を使用してイメージ情報を開放する必要があります。

 

今のBTMemoは、基本的にこの方法を使用しています。もっとも当初は

・ピクチャーを保持していたのでメモリを多量に消費していた

・表示のたびにRender()を使用して画像縮小していたので、表示が重かった

などの問題点がありました。今では多少工夫してまして、縮小した結果の画像データを保持するように変更してあり、

使用メモリ量を抑え、描画も高速化してます(当社比)

 

 

 

(3)上記で扱えないフォーマットの画像ファイルを処理するには

これに関して私が助言できることは何も有りません。

基本的には個々のファイルフォーマットを調べて自分で処理を組み立てる以外に有りません。

 

しかし、スージープラグインといった先人の努力の結果を利用させていただくことも可能です。

(参考出品レベルですが、BTMemoでもスージープラグインを利用することが可能です)

 

中途半端な知識しかないので、ここでは詳しい説明はいたしません。本家WEBページを直接ご覧下さい。