ホーム > カテゴリ > C/C++ >

減色/増色シリーズ - ビットマップを1677万色(24bit)で保存(C/C++版)

減色/増色シリーズ - ビットマップを1677万色(24bit)で保存するサンプルです。

サンプルの実行画面

ソースコード

[Sample97.c]

//--------------------------------------------------------------------------------------
//  ■減色/増色シリーズ - ビットマップを1677万色(24bit)で保存 -■ Sample NO.97
//
//--------------------------------------------------------------------------------------

#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))

LRESULT CALLBACK  WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
int  WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow);
void Save24bit(HWND hwnd,const char *Filename);
int OpenDiaog(HWND hwnd,LPCSTR Filter,char *FileName,DWORD Flags);

HBITMAP hBitmap=NULL;     //ビットマップのハンドル

 
/////////////////////////////////////////////////////////////////////////////
//
//  Save24bit  
//
void Save24bit(HWND hwnd,const char *Filename )
{
  int        Dummy;
  HDC        hMem,hDC;
  BITMAP     BMP;
  BITMAPINFO BI;   
  BYTE       *buffer;
  DWORD      _Size,work;
  HANDLE     hFile;
  BITMAPFILEHEADER  BF;
   
  //初期情報を設定
  ZeroMemory(&BI,sizeof(BITMAPINFO));
  ZeroMemory(&BF,sizeof(BITMAPFILEHEADER));
  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=24;
  BI.bmiHeader.biCompression=BI_RGB;

  //24bitビットマップデータサイズを算出
  _Size=((24 * BI.bmiHeader.biWidth + 31) / 32) * 4 * abs(BI.bmiHeader.biHeight);

  //BITMAPFILEHEADERの準備
  BF.bfType=0x4D42;
  BF.bfOffBits=40+14;
  BF.bfSize=_Size+BF.bfOffBits;

  buffer=(BYTE *)malloc(_Size);

  //メモリビットマップ作成
  hDC=GetDC(hwnd);
  hMem = CreateCompatibleDC(hDC);
  SelectObject(hMem,hBitmap);
  //24bitに変換
  Dummy=GetDIBits(hMem, hBitmap, 0,BMP.bmHeight,buffer,&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,&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",                  //登録されたクラス名のアドレス 
           "減色/増色シリーズ - ビットマップを1677万色(24bit)で保存 -",             //ウインドウ名
           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))
                     {
                         Save24bit(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_sample97.zip 3,390 バイト

動作環境

このサンプルは 「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:00553