ビットマップを保存する(RLE圧縮対応)(C/C++版)
ビットマップを保存する(RLE圧縮対応)サンプルです。
サンプルの実行画面
ソースコード
[Sample79.c]
//--------------------------------------------------------------------------------------
// ■ビットマップを保存する(RLE圧縮対応)■ Sample NO.79
//
//--------------------------------------------------------------------------------------
#include <windows.h>
HBITMAP hBitmap=NULL;
#define IDM_MENU 100
#define IDM_SUBMENU1 101
#define IDM_SUBMENU2 102
int OpenDiaog(HWND hwnd,LPCSTR Filter,char *FileName,DWORD Flags);
int SaveDiaog(HWND hwnd,LPCSTR Filter,char *FileName,DWORD Flags);
void SaveBMP(const char *FileName,HBITMAP hBMP);
//ウインドウを中央にする為にX座標(LEFT)とY座標(TOP)算出するマクロ
#define ScreenCenterX(Width) ((0)<((int)((GetSystemMetrics(SM_CXSCREEN)- Width) / 2)) ? ((int)((GetSystemMetrics(SM_CXSCREEN)- Width) / 2)) :(0))
#define ScreenCenterY(Height) ((0)<((int)((GetSystemMetrics(SM_CYSCREEN)- Height) / 2)) ? ((int)((GetSystemMetrics(SM_CYSCREEN)- Height) / 2)) :(0))
//いつものプロシージャ
HWND CreateMainWindow(int Width,int Height,LPCTSTR Caption,HINSTANCE hInstance,int nCmdShow,WNDPROC lpfnWndProc, DWORD dwstyle,DWORD dwExstyle,LPCTSTR MenuID,HICON hIcon);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
//----------------------------------------------------------
//■関数 SaveBMP
//■用途 ビットマップオブジェクトをファイルに保存する
//■引数
// FileName ...親ウインドウのハンドル
// hBMP ...ビットマップオブジェクト
//■備考
// ビットマップオブジェクトはCreateDIBSection()の呼び出し
// で作成されたビットマップでないとエラーになります。
//----------------------------------------------------------
void SaveBMP(const char *FileName,HBITMAP hBMP)
{
BITMAPFILEHEADER BMPFileHeader;
DIBSECTION DIB;
HANDLE hFile=NULL;
DWORD Work;
int Colors=0;
RGBQUAD *RGBQuad;
HDC hMem,hDC;
//ファイル作成
hFile = CreateFile(FileName, GENERIC_WRITE, 0,NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
if (hFile!=NULL)
{
//初期化
ZeroMemory(&BMPFileHeader,sizeof(BITMAPFILEHEADER));
//BITMAPINFO構造体の取得
GetObject(hBMP, sizeof(DIBSECTION), &DIB);
//BITMAPFILEHEADER構造体の設定----->
BMPFileHeader.bfType=0x4D42;
//カラーパレットのサイズを計算
if (DIB.dsBmih.biClrUsed==0)
{
switch (DIB.dsBmih.biBitCount)
{
case 1: Colors=2; break;
case 4: Colors=16; break;
case 8: Colors=256; break;
}
}
else
{
switch (DIB.dsBmih.biBitCount)
{
case 1: Colors=DIB.dsBmih.biClrUsed; break;
case 4: Colors=DIB.dsBmih.biClrUsed; break;
case 8: Colors=DIB.dsBmih.biClrUsed; break;
}
}
//LoadImageで読込んだ画像はbiSizeImageが0の場合は絶対にない。だから、イメージデータサイズを計算しなくてもOK。
BMPFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+Colors*sizeof(RGBQUAD);
BMPFileHeader.bfSize=BMPFileHeader.bfOffBits+DIB.dsBmih.biSizeImage;
//ファイルに書き込み----->
//BITMAPFILEHEADERの書き込み
WriteFile(hFile,&BMPFileHeader,sizeof(BITMAPFILEHEADER),&Work,NULL);
//BITMAPINFOHEADERの書き込み
WriteFile(hFile,&(DIB.dsBmih),sizeof(BITMAPINFOHEADER),&Work,NULL);
//カラーパレットの書き込み
if (Colors!=0)
{
hDC=GetDC(0);
hMem = CreateCompatibleDC(hDC);
SelectObject(hMem, hBMP);
RGBQuad=(RGBQUAD *)malloc(Colors*sizeof(RGBQUAD));
GetDIBColorTable(hMem,0,Colors,RGBQuad);
WriteFile(hFile,RGBQuad,Colors*sizeof(RGBQUAD),&Work,NULL);
free(RGBQuad);
DeleteDC(hMem);
ReleaseDC(0,hDC);
}
//イメージデータの書き込み
WriteFile(hFile,DIB.dsBm.bmBits,DIB.dsBmih.biSizeImage,&Work,NULL);
CloseHandle(hFile);
}
}
//------------------------------------------------------
//■関数 OpenDiaog
//■用途 「ファイルを開く」ダイアログを表示する
//■引数
// hwnd ...親ウインドウのハンドル
// Filter ...フィルター
// FileName ...ファイルのフルパス名(戻り値)
// Flags ...ダイアログのフラグ
//■戻り値
// ファイルを選択 true
//------------------------------------------------------
int OpenDiaog(HWND hwnd,LPCSTR Filter,char *FileName,DWORD Flags)
{
OPENFILENAME OFN;
ZeroMemory(&OFN,sizeof(OPENFILENAME));
OFN.lStructSize = sizeof(OPENFILENAME);
OFN.hwndOwner = hwnd;
OFN.lpstrFilter =Filter;
OFN.lpstrFile =FileName;
OFN.nMaxFile = MAX_PATH*2;
OFN.Flags = Flags;
OFN.lpstrTitle = "ファイルを開く";
return (GetOpenFileName(&OFN));
}
//------------------------------------------------------
//■関数 SaveDiaog
//■用途 「名前を付けて保存」ダイアログを表示する
//■引数
// hwnd ...親ウインドウのハンドル
// Filter ...フィルター
// FileName ...ファイルのフルパス名(戻り値)
// Flags ...ダイアログのフラグ
//■戻り値
// ファイルを選択 true
//------------------------------------------------------
int SaveDiaog(HWND hwnd,LPCSTR Filter,char *FileName,DWORD Flags)
{
OPENFILENAME OFN;
ZeroMemory(&OFN,sizeof(OPENFILENAME));
OFN.lStructSize = sizeof(OPENFILENAME);
OFN.hwndOwner = hwnd;
OFN.lpstrFilter =Filter;
OFN.lpstrFile =FileName;
OFN.nMaxFile = MAX_PATH*2;
OFN.Flags = Flags;
OFN.lpstrTitle = "名前を付けて保存";
return (GetSaveFileName(&OFN));
}
//------------------------------------------------------
//■関数 CreateMainWindow
//■用途 メインウインドウを作成する
//■引数
// Width ...ウインドウの横幅
// Height ...ウインドウの縦幅
// Caption ...タイトル名
// hInstance ...インスタンスハンドル
// nCmdShow ...ウインドウの表示形態
// lpfnWndProc ...コールバックプロシージャ
// dwstyle ...ウインドウスタイル
// dwExstyle ...拡張ウインドウスタイル
// MenuID ...メニューのID
// hIcon ...アイコン
//■戻り値
// ウインドウのハンドル
//------------------------------------------------------
HWND CreateMainWindow(int Width,int Height,LPCTSTR Caption,HINSTANCE hInstance,int nCmdShow,WNDPROC lpfnWndProc, DWORD dwstyle,DWORD dwExstyle,LPCTSTR MenuID,HICON hIcon)
{
HWND hWnd; //メインウインドウのハンドル
WNDCLASS myClass; //WNDCLASS構造体
//WNDCLASS構造体を0で初期化
ZeroMemory(&myClass,sizeof(WNDCLASS));
//--->WNDCLASS構造体の設定&ウインドウクラスの登録
myClass.style =CS_HREDRAW | CS_VREDRAW; //ウインドウスタイルを設定
myClass.lpfnWndProc = lpfnWndProc; //コールバックプロシージャへのポインタ
myClass.hInstance=hInstance; //インスタンスハンドルを設定
myClass.hCursor=LoadCursor(NULL, IDC_ARROW); //カーソルの設定(Windows標準リソースを使用)
myClass.hbrBackground=(HBRUSH)COLOR_WINDOW; //ウインドウの背景を設定(デフォルトカラー)
myClass.lpszClassName="TForm"; //クラス名の設定(Borland Delphi風)
myClass.hIcon =hIcon; //アイコンの指定
myClass.lpszMenuName=MenuID; //メニューの設定
//ウィンドウ クラスを登録
RegisterClass(&myClass);
//--->ウインドウの作成&表示
//メインウインドウの生成
hWnd = CreateWindowEx(
dwExstyle, //拡張ウインドウスタイル
"TForm", //登録されたクラス名のアドレス
Caption, //ウインドウ名
dwstyle, //ウインドウスタイルを設定
ScreenCenterX(Width), //X座標の位置設定
ScreenCenterY(Height),//Y座標の位置設定
Width, //横幅を設定
Height, //縦幅を設定
NULL, //親ウインドウを設定
NULL, //メニューを設定
hInstance, //インスタンスを識別
NULL); //作成したウインドウに渡すデータへのポインタ
//ウインドウの表示(表示方法はnCmdShowに従う)
ShowWindow(hWnd, nCmdShow);
return(hWnd);
}
//--------------------------------------------------------
//■関数 WinMain
//■用途 メインの関数
//■引数
// hInstance ...現在のインスタンスのハンドル
// hPrevInstance...以前のインスタンスのハンドル
// pszCmdLine ...コマンド ラインのアドレス
// nCmdShow ...ウィンドウの表示状態
//--------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
//メインウインドウを作成
CreateMainWindow(400,400,"ビットマップを保存する(RLE圧縮対応)",hInstance,nCmdShow,(WNDPROC)WindowProc,
WS_OVERLAPPEDWINDOW|WS_TABSTOP,WS_EX_CONTROLPARENT,MAKEINTRESOURCE(IDM_MENU),LoadIcon(NULL,MAKEINTRESOURCE(IDI_APPLICATION)));
//送られてくるメッセージを翻訳してプロシージャに渡す
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
//------------------------------------------------------
// ■関数 WindowProc
// ■用途 メインウインドウに送られるメッセージを処理
// ■引数
// hwnd ...ウインドウのハンドル
// uMsg ...メッセージID
// wParam ...第1メッセージ パラメータ
// lParam ...第2メッセージ パラメータ
//------------------------------------------------------
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
char FileName[MAX_PATH*2];
BITMAP BMPINFO;
HDC hMem,hDC;
RECT Rect;
HBRUSH hBrush;
switch (uMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_SUBMENU1 :
//初期化(これをしないとごみが入る)
ZeroMemory(FileName,MAX_PATH*2);
//「ファイルを開く」ダイアログを表示
if (OpenDiaog(hwnd,"BMP Files(*.bmp)\0*.bmp\0",
FileName,OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY))
{
//ビットマップのロード
DeleteObject(hBitmap);
//LR_CREATEDIBSECTIONフラグを使用しているに注目
//(これを指定しないとSaveBMP()がうまく動作致しません。)
hBitmap =(HBITMAP)LoadImage((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),FileName,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
//強制再描画
hDC=GetDC(hwnd);
hBrush=CreateSolidBrush(RGB(192,192,192));
GetWindowRect(hwnd,&Rect);
FillRect (hDC,&Rect,hBrush);
DeleteObject(hBrush);
ReleaseDC(hwnd,hDC);
SendMessage(hwnd,WM_PAINT,0,0);
}
break;
case IDM_SUBMENU2 :
if (hBitmap!=NULL)
{
//初期化(これをしないとごみが入る)
ZeroMemory(FileName,MAX_PATH*2);
//「名前を付けて保存」ダイアログを表示
if (SaveDiaog(hwnd,"BMP Files(*.bmp)\0*.bmp\0",
FileName,OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT))
{
SaveBMP(FileName,hBitmap);
}
}
break;
}
case WM_PAINT:
//ビットマップの描画
if (hBitmap!=NULL)
{
hDC=GetDC(hwnd);
GetObject(hBitmap, sizeof(BITMAP), &BMPINFO);
hMem = CreateCompatibleDC(hDC);
SelectObject(hMem, hBitmap);
BitBlt(hDC,0,0, BMPINFO.bmWidth,BMPINFO.bmHeight, hMem, 0, 0, SRCCOPY);
DeleteDC(hMem);
ReleaseDC(hwnd,hDC);
}
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
break;
case WM_DESTROY:
DeleteObject(hBitmap);
PostQuitMessage(0);
break;
default: return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}
return (0);
}
ソースコード一式のダウンロード
capi_sample79.zip 4,083 バイト
動作環境
このサンプルは 「Windows98」及び「Microsoft Visual C++5.0」「Borland C++ Compiler 5.5」で確認しております。環境が異なる場合は正常に動作しない場合もございますのでご了承下さい。
Visual C++5.0でのコンパイル
VC5.0でサンプルをコンパイルする場合は新規プロジェクト(Win32Application)を作成後、各ファイルを追加してビルドしてください。
Borland C++ Compiler 5.5でのコンパイル
BCC5.5でサンプルをコンパイルする場合は「bcc32.exe」で*.c又は*.cppファイルをコンパイルします。リソースがある場合は「brc32.exe」で*resファイルを付与してください。
サンプルについて
このWindows APIサンプル集(C/C++版)は2000年頃にC/C++言語の学習の為に作成したものです。コードはエレガントではなく「初心者レベルのコーディング」です。仕事などの業務で利用する際にはエラー処理やメモリ解放などの再確認を必ずして下さい。
スポンサーリンク
関連記事
公開日:2015年03月19日
記事NO:00535
プチモンテ ※この記事を書いた人
![]() | |
![]() | 💻 ITスキル・経験 サーバー構築からWebアプリケーション開発。IoTをはじめとする電子工作、ロボット、人工知能やスマホ/OSアプリまで分野問わず経験。 画像処理/音声処理/アニメーション、3Dゲーム、会計ソフト、PDF作成/編集、逆アセンブラ、EXE/DLLファイルの書き換えなどのアプリを公開。詳しくは自己紹介へ |
| 🎵 音楽制作 BGMは楽器(音源)さえあれば、何でも制作可能。歌モノは主にロック、バラード、ポップスを制作。歌詞は抒情詩、抒情的な楽曲が多い。楽曲制作は🔰2023年12月中旬 ~ | |









