減色/増色シリーズ - ビットマップを256色(8bit)で保存(C/C++版)
減色/増色シリーズ - ビットマップを256色(8bit)で保存するサンプルです。
サンプルの実行画面
ソースコード
[Sample98.c]
//-------------------------------------------------------------------------------------- // ■減色/増色シリーズ - ビットマップを256色(8bit)で保存 -■ Sample NO.98 // //-------------------------------------------------------------------------------------- #include <windows.h> #define IDM_MENU 101 #define IDM_SAVE 102 #define IDM_OPEN 103 #define IDM_END 104 //ウインドウを中央にする為に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)) typedef struct { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[256]; }BITMAPINFO_8BIT; LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow); void Save8bit(HWND hwnd,const char *Filename); int OpenDiaog(HWND hwnd,LPCSTR Filter,char *FileName,DWORD Flags); int SaveDiaog(HWND hwnd,LPCSTR Filter,char *FileName,DWORD Flags); HBITMAP hBitmap=NULL; //ビットマップのハンドル ///////////////////////////////////////////////////////////////////////////// // // Save8bit // void Save8bit(HWND hwnd,const char *Filename ) { int Dummy; HDC hMem,hDC; BITMAP BMP; BYTE *buffer; DWORD _Size,work; HANDLE hFile; BITMAPFILEHEADER BF; BITMAPINFO_8BIT BI; ZeroMemory(&BF,14); GetObject(hBitmap, sizeof(BITMAP), &BMP); //BITMAPINFOの準備 BI.bmiHeader.biSize=40; BI.bmiHeader.biWidth=BMP.bmWidth; BI.bmiHeader.biHeight=BMP.bmHeight; BI.bmiHeader.biPlanes=1; BI.bmiHeader.biBitCount=8; BI.bmiHeader.biCompression=BI_RGB; //8bitビットマップデータサイズを算出 _Size=((8 * BI.bmiHeader.biWidth + 31) / 32) * 4 * abs(BI.bmiHeader.biHeight); //BITMAPFILEHEADERの準備 BF.bfType=0x4D42; BF.bfOffBits=40+14+1024; BF.bfSize=_Size+BF.bfOffBits; buffer=(BYTE *)malloc(_Size); //メモリビットマップ作成 hDC=GetDC(hwnd); hMem = CreateCompatibleDC(hDC); SelectObject(hMem,hBitmap); //8bitに変換 Dummy=GetDIBits(hMem, hBitmap, 0,BMP.bmHeight,buffer,(LPBITMAPINFO)&BI, DIB_RGB_COLORS); DeleteDC(hMem) ; ReleaseDC(hwnd,hDC); if (Dummy!=0) { //ファイル作成 hFile = CreateFile(Filename, GENERIC_WRITE, 0,NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL); //各ヘッダーの書きこみ WriteFile(hFile,&BF,14,&work,NULL); WriteFile(hFile,&BI,40+1024,&work,NULL); WriteFile(hFile,buffer,_Size,&work,NULL); CloseHandle(hFile); } else MessageBox(hwnd,"なんだが失敗しちゃったみたい(^^;","エラー",MB_OK); free(buffer); } ///////////////////////////////////////////////////////////////////////////// // // OpenDiaog // 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 // 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)); } ///////////////////////////////////////////////////////////////////////////// // // WinMain // int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; HWND hWnd; WNDCLASS myClass; ZeroMemory(&myClass,sizeof(WNDCLASS)); myClass.style =CS_HREDRAW | CS_VREDRAW; //ウインドウスタイルを設定 myClass.lpfnWndProc =(WNDPROC)WindowProc; //コールバックプロシージャへのポインタ myClass.hInstance =hInstance; //インスタンスハンドルを設定 myClass.hCursor =LoadCursor(NULL, IDC_ARROW);//カーソルの設定(Windows標準リソースを使用) myClass.hbrBackground =(HBRUSH)COLOR_WINDOW; //ウインドウの背景を設定(デフォルトカラー) myClass.lpszClassName ="Programming Library"; //クラス名の設定 myClass.hIcon =NULL; //アイコンの指定 myClass.lpszMenuName =MAKEINTRESOURCE(IDM_MENU); //メニューの設定 //ウィンドウ クラスを登録 RegisterClass(&myClass); //メインウインドウの生成 hWnd=CreateWindowEx( WS_EX_CONTROLPARENT | WS_EX_WINDOWEDGE, //拡張ウインドウスタイル "Programming Library", //登録されたクラス名のアドレス "減色/増色シリーズ - ビットマップを256色(8bit)で保存 -", //ウインドウ名 WS_OVERLAPPEDWINDOW, //ウインドウスタイルを設定 ScreenCenterX(460), //X座標の位置設定 ScreenCenterY(400), //Y座標の位置設定 460, //横幅を設定 400, //縦幅を設定 NULL, //親ウインドウを設定 NULL, //メニューを設定 hInstance, //インスタンスを識別 NULL); //作成したウインドウに渡すデータへのポインタ //ウインドウの表示(表示方法はnCmdShowに従う) ShowWindow(hWnd, nCmdShow); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); } ///////////////////////////////////////////////////////////////////////////// // // WindowProc // LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch (uMsg) { case WM_PAINT: { BITMAP BMPINFO; HDC hMem,hDC; HBRUSH hBrush; RECT Rect; //背景塗りつぶし hDC=GetDC(hwnd); hBrush=CreateSolidBrush(RGB(128,128,128)); GetClientRect(hwnd,&Rect); FillRect(hDC,&Rect,hBrush); DeleteObject(hBrush); if (hBitmap!=NULL) { //画像表示 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_COMMAND: { char FileName[MAX_PATH*2]; switch(LOWORD(wParam)) { case IDM_SAVE : if (hBitmap==NULL) { MessageBox(hwnd,"ビットマップが読込まれていません","エラー",MB_OK); break; } ZeroMemory(FileName,MAX_PATH*2); //「名前を付けて保存」ダイアログを表示 if (SaveDiaog(hwnd,"BMP(*.bmp)\0*.bmp\0\0", FileName,OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT)) { Save8bit(hwnd,FileName); } break; case IDM_OPEN : ZeroMemory(FileName,MAX_PATH*2); //「ファイルを開く」ダイアログを表示 if (OpenDiaog(hwnd,"BMP(*.bmp)\0*.bmp\0\0", FileName,OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY)) { if (hBitmap!=NULL) DeleteObject(hBitmap); //ビットマップのロード hBitmap =(HBITMAP)LoadImage((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),FileName,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); if (hBitmap==NULL) MessageBox(hwnd,"ビットマップがぶッ壊れています。","エラー",MB_OK); else SendMessage(hwnd,WM_PAINT,0,0); } break; case IDM_END: DeleteObject(hBitmap); PostQuitMessage(0); break; default :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_sample98.zip 3,428 バイト
動作環境
このサンプルは 「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:00554