FC2ブログ

ホーム > DIBファイルフォーマット > ビットマップリソースの読み込み

ビットマップリソースの読み込み



ビットマップリソース (リソースタイプ RT_BITMAP(2))は、デバイス独立ビットマップ(DIB形式)として格納されおり、以下のような構造をしています。

  1. BITMAPINFO構造体
  2. ピクセルデータ





32ビットアルファDIBの作成のためにBITMAPV5HEADER構造体を使用するので、「stdafx.h」の内容のうち、下記の赤字部分を訂正して下さい。

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently


#pragma once

#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#endif

// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.

#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.
#define WINVER 0x0500 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. ←0x0400から、0x0500に変更してください。
#endif

#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later.
#define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target Windows 2000 or later. ←0x0400から、0x0500に変更してください。
#endif

#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0500 // Change this to the appropriate value to target Windows Me or later. ←0x0410から、0x0500に変更してください。
#endif

#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
#define _WIN32_IE 0x0500 // Change this to the appropriate value to target IE 5.0 or later. ←0x0400から、0x0500に変更してください。
#endif

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit

#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions



DLL/EXEファイルを開いてモジュールハンドルを取得し、同じ名前の_LoadDIBFromResource関数を呼び出します。

//DLL/EXEファイルからビットマップリソースを読み込む
HBITMAP __stdcall _LoadDIBFromResource(LPCTSTR lpszExeName,LPCTSTR lpName,LPDWORD lpdwCompression)
{
HMODULE hModule=::LoadLibraryEx(lpszExeName,NULL,
LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
if (!hModule) return FALSE;
HBITMAP hBitmap=_LoadDIBFromResource(hModule,lpName,lpdwCompression);
::FreeLibrary(hModule);
return hBitmap;
}


入力されたリソースモジュールハンドルから、指定したリソース名のビットマップリソース をグローバルメモリーに展開し、_CreateDIBIndirect関数を呼び出します。

//ピットマップリソースの読み込み
HBITMAP __stdcall _LoadDIBFromResource(HMODULE hModule,LPCTSTR lpName,LPDWORD lpdwCompression)
{
//ビットマップリソース内で、指定したリソース名のリソースハンドルを取得します。
HRSRC hResInfo=::FindResource(hModule,(LPCTSTR)lpName,FreeLibrary);
if (!hResInfo) return FALSE;

//リソースをグローバルメモリにロードします。
HGLOBAL hGlobal=::LoadResource(hModule,hResInfo);
if (!hGlobal) return FALSE;

//メモリ内の指定されたリソースをロックします。
LPVOID pGlobal=::LockResource(hGlobal);
if (!pGlobal) return FALSE;

//指定したリソースのサイズ( バイト数)を取得します。
DWORD dwResSize=::SizeofResource(hModule,hResInfo);
if (!dwResSize) return FALSE;

//BITMAPINFO構造体からDIBを作成します。
HBITMAP hBitmap=_CreateDIBIndirect((BITMAPINFO*)pGlobal,dwResSize);
if (!hBitmap) return FALSE;

//第三引数のlpdwCompressionパラメータが有効な場合は、圧縮方法を保存しておきます。
if (AfxIsValidAddress(lpdwCompression,sizeof(DWORD)))
*lpdwCompression=((BITMAPINFO*)pGlobal)->bmiHeader.biCompression;

return hBitmap;
}


BITMAPINFO構造体 から始まるメモリーを読み込んでDIBを作成します。

//BITMAPINFO構造体からDIBを作成します。
HBITMAP __stdcall _CreateDIBIndirect(BITMAPINFO* pBmi,DWORD dwBmiSize)
{
ASSERT(AfxIsValidAddress(pBmi,dwBmiSize,0));
//入力されたBITMAPINFO構造体が有効ではないか、DIBでない場合は、
//FALSEを返して終了します。

if ((pBmi->bmiHeader.biSize<sizeof(BITMAPINFOHEADER))||
(pBmi->bmiHeader.biSize>sizeof(BITMAPV5HEADER))) return FALSE;

//BITMAPINFO構造体から各値を取得します。--------------------------------------
UINT width=pBmi->bmiHeader.biWidth; //DIBの幅
UINT height=abs(pBmi->bmiHeader.biHeight); //DIBの高さ(絶対値)
UINT nBpp=pBmi->bmiHeader.biBitCount; //DIBのビットカウント

DWORD widthBytes=WIDTHBYTES(nBpp*width); //ビットマップバイト幅の算出
DWORD dwSizeImage=widthBytes*height; //ピクセルデータのバイト数
DWORD dwCompression=pBmi->bmiHeader.biCompression; //圧縮方法

//カラーテーブルのサイズを算出------------------------------------------------
DWORD dwClrUsed=pBmi->bmiHeader.biClrUsed; //使用色数
UINT nColors=0; //カラーテーブルのエントリー数を0にする
//カラーテーブルがあって使用色数が0でないなら、エントリー数は使用色数を、
//それ以外は2のnBpp乗を代入する

if (nBpp<=8) nColors=(dwClrUsed)?dwClrUsed:1<<nBpp;
DWORD dwSizeOfColorTable=sizeof(RGBQUAD)*nColors;

//マスクビットフィールドがあればそのサイズを算出します。----------------------
DWORD dwBitFields=(((nBpp==16)||(nBpp==32))&& //ビットカウントが16/32ビットで
(dwCompression==BI_BITFIELDS))?sizeof(DWORD)*3:0; //圧縮方法がBI_BITFIELDSなら12byte、
//それ以外は0byteにする


//BITMAPINFO構造体のサイズを算出する
DWORD dwSizeOfBitmapInfo=((nBpp==32)&&(dwCompression==BI_BITFIELDS))?
pBmi->bmiHeader.biSize:
sizeof(BITMAPINFOHEADER)+dwSizeOfColorTable+dwBitFields;

//算出したサイズがメモリーサイズより大きいときはFALSEを返して終了する。
if (dwSizeOfBitmapInfo>dwBmiSize) return FALSE;

//BITMAPINFO構造体を格納するバッファの確保
BITMAPINFO* pBmpInfo=(BITMAPINFO*)(new BYTE[dwSizeOfBitmapInfo]);

//メモリー上にあるBITMAPINFO構造体をコピーする
::CopyMemory(pBmpInfo,pBmi,dwSizeOfBitmapInfo);

//ランレングス圧縮されたDIBの場合は、DIB作成時にエラーにならないように
//BITMAPINFOHEADER構造体のbiCompressionをBI_RGBに戻しておきます。

if ((dwCompression==BI_RLE4)||(dwCompression==BI_RLE8))
pBmpInfo->bmiHeader.biCompression=BI_RGB;

//読み込んだBITMAPINFO構造体から、DIBセクションを作成します。
LPVOID pvBits=0;
HBITMAP hBitmap=::CreateDIBSection(0,pBmpInfo,DIB_RGB_COLORS,&pvBits,NULL,NULL);

//BITMAPINFO構造体はもういらないのでメモリーを解放します。
delete[]pBmpInfo;
//DIBの作成に失敗したらFALSEを返して終了します。
if (!hBitmap) return FALSE;


//メモリー上のピクセルデータの先頭アドレスを算出します。
BYTE* pBitsImage=(BYTE*)pBmi+dwSizeOfBitmapInfo;
//メモリー上のピクセルデータのサイズ(バイト)を算出します。
DWORD dwBytesInRes=min(dwSizeImage,dwBmiSize-dwSizeOfBitmapInfo);

//それぞれの圧縮形式に合わせて、イメージピクセルを読み込みます。-------------------
BOOL bResult=FALSE;
switch(dwCompression){
case BI_RGB:
case BI_BITFIELDS:
//圧縮してない場合は、ピクセルデータをそのままコピーします。
::CopyMemory(pvBits,pBitsImage,dwBytesInRes);
bResult=TRUE;
break;
case BI_RLE4:
//4ビットランレングス圧縮の場合は、_DecodeRle4関数を呼び出して解凍します。
{
//CMemFileクラスを作成してメモリーを結び付けます。
CMemFile infile(pBitsImage,dwBytesInRes);
bResult=_DecodeRle4(pvBits,dwSizeImage,width,height,&infile);
infile.Close();
}
break;
case BI_RLE8:
//8ビットランレングス圧縮の場合は、_DecodeRle8関数を呼び出して解凍します。
{
//CMemFileクラスを作成してメモリーを結び付けます。
CMemFile infile(pBitsImage,dwBytesInRes);
bResult=_DecodeRle8(pvBits,dwSizeImage,width,height,&infile);
infile.Close();
}
break;
default:
break;
}

//読み込みエラーがある場合は、作成したDIBを削除した後
//FALSEを返して終了します。

if (!bResult){
::DeleteObject(hBitmap);
return FALSE;
}

return hBitmap;
}


hBitmapの内容が、読み込んだDIBファイルから作成したDIBのハンドルになります。

サンプルプログラム(VisualC++net2003ソリューション)DIBFileTest02.zip

上記のzipファイルをダウンロードしてからWinRAR等で解凍し、DIBFileTest02フォルダー内にある「DIBFileTest.sln」を開きます。「F5」キーを押すと、ビルド確認のダイヤログが表示されるので「Yes」を選択してソリューションをビルドします。



ビルドが終わると直ちにプログラムが自動起動してウィンドウが表示されます。ウィンドウのメニューで「ファイル」/「開く」を選択して、「ファイルを開く」ダイヤログを表示させます。



Debugフォルダー内の「DIBFileTest.exe」を選択し、「開く」ボタンを押すと、「リソース名を選択してください。」ダイヤログが表示されるので、コンボボックスで130番を選択します。



最後に下のような画像が表示されるか確認します。





スポンサーサイト



コメント: 0

この記事へのコメント
ブログ著者にのみ知らせます。

Trackback+Pingback: 0

TrackBack URL for this entry
http://hiroshi0945.blog75.fc2.com/tb.php/11-c29bea2e
Listed below are links to weblogs that reference
ビットマップリソースの読み込み from マルチメディアファイルフォーマット

Home > DIBファイルフォーマット > ビットマップリソースの読み込み

タグクラウド
ブロとも申請フォーム

この人とブロともになる

ブロとも一覧

このページの先頭へ戻る