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

グラフィックエフェクト- モザイク(C/C++版)

グラフィックエフェクト- モザイクのサンプルです。

サンプルの実行画面

ソースコード

[Sample94.c]

//--------------------------------------------------------------------------------------
//  ■グラフィックエフェクト- モザイク -■ Sample NO.94
//
//--------------------------------------------------------------------------------------

#include <windows.h>

#define IDM_MENU  101
#define IDM_ON    102
#define IDM_NONE  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 Mozaiku(HWND hwnd);

HBITMAP hBitmap=NULL;  //ビットマップのハンドル
HBITMAP hTempBMP=NULL; //テンポラリビットマップのハンドル
HDC     hTempMem=NULL; //テンポラリメモリデバイスコンテキスト
BOOL    OK;            //フラグ    
 
/////////////////////////////////////////////////////////////////////////////
//
//  Mozaiku  
//         VBレベルの手法なので遅いです(^^;  
//         高速に処理したい人はGetDIBits()APIなどを使いましょう。
//         
void Mozaiku(HWND hwnd)
{
  BITMAP  BMPINFO;   
  HDC     hMem,hDC; 
  int     X,Y,i;
  BYTE    R,G,B;
  DWORD   RGBColor;
  BYTE    work[8][3];
    
  hDC=GetDC(hwnd);
  GetObject(hBitmap, sizeof(BITMAP), &BMPINFO);
  //メモリビットマップ作成
  hMem    = CreateCompatibleDC(hDC);
  SelectObject(hMem, hBitmap);
  //テンポラリメモリビットマップ作成
  hTempMem = CreateCompatibleDC(hDC);
  hTempBMP = CreateCompatibleBitmap(hDC, BMPINFO.bmWidth, BMPINFO.bmHeight);
  SelectObject(hTempMem, hTempBMP);
   
  for (Y=0;Y<BMPINFO.bmHeight;Y++)
  {
   for (X=0;X<BMPINFO.bmWidth;X++)
   {   
       if (X%8==0)
       {
        for (i=0;i<8;i++)
        {
         RGBColor=GetPixel(hMem, X+i, Y);
         //エラーだったら最初の色を取得
         if (RGBColor== CLR_INVALID) RGBColor=GetPixel(hMem, X, Y);
         R=GetRValue(RGBColor); G=GetGValue(RGBColor); B=GetBValue(RGBColor);
         work[i][0]=R;work[i][1]=G;work[i][2]=B;
        } 
        
        //横ライン8ピクセル分の平均値(本当は縦横ブロック単位で行う方が良い。)
        R=(work[0][0]+work[1][0]+work[2][0]+work[3][0]+
           work[4][0]+work[5][0]+work[6][0]+work[7][0]) /8;
        G=(work[0][1]+work[1][1]+work[2][1]+work[3][1]+
           work[4][1]+work[5][1]+work[6][1]+work[7][1]) /8;
        B=(work[0][2]+work[1][2]+work[2][2]+work[3][2]+
           work[4][2]+work[5][2]+work[6][2]+work[7][2]) /8;

        for (i=0;i<8;i++)
        {
         SetPixelV(hTempMem, X+i, Y,RGB(R,G,B)); 
        }
       }
   }  
  }   
  DeleteDC(hMem);    
  ReleaseDC(hwnd,hDC);
}

/////////////////////////////////////////////////////////////////////////////
//
//  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",                  //登録されたクラス名のアドレス 
           "グラフィックエフェクト- モザイク -",     //ウインドウ名
           WS_OVERLAPPEDWINDOW,                    //ウインドウスタイルを設定
           ScreenCenterX(300),                     //X座標の位置設定
           ScreenCenterY(300),                     //Y座標の位置設定
           300,                                    //横幅を設定
           300,                                    //縦幅を設定
           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_CREATE:
         //ビットマップのロード
         hBitmap =(HBITMAP)LoadImage((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),"Sample94.bmp",IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); 
         if (hBitmap==NULL)
         {
          MessageBox(hwnd,"Sample94.bmpがありません。","エラー",MB_OK);
          PostQuitMessage(0);
         }
         else
         {
          //先にモザイク画像を作成 
              Mozaiku(hwnd);         
         }
         break;
  case WM_PAINT:
        { 
          BITMAP      BMPINFO;    //BITMAP構造体
          HDC         hMem,hDC;   //メモリデバイスコンテキストのハンドル
                  
                  if (OK)
                  {
                   //モザイク画像表示
                   hDC=GetDC(hwnd);
                   GetObject(hBitmap, sizeof(BITMAP), &BMPINFO);
                   BitBlt(hDC,0,0, BMPINFO.bmWidth,BMPINFO.bmHeight, hTempMem, 0, 0, SRCCOPY);
                   ReleaseDC(hwnd,hDC);
                  }
                  else
                  {  
                   //ノーマル画像表示
                   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_COMMAND:
             switch(LOWORD(wParam))
             {
               case IDM_ON : 
                   CheckMenuItem(GetMenu(hwnd),IDM_ON,MF_BYCOMMAND |MF_CHECKED);
                   CheckMenuItem(GetMenu(hwnd),IDM_NONE,MF_BYCOMMAND |MF_UNCHECKED);
                   OK=TRUE;
                   SendMessage(hwnd,WM_PAINT,0,0);
                   break;
               case IDM_NONE:
                   CheckMenuItem(GetMenu(hwnd),IDM_ON,MF_BYCOMMAND |MF_UNCHECKED);
                   CheckMenuItem(GetMenu(hwnd),IDM_NONE,MF_BYCOMMAND |MF_CHECKED);
                   OK=FALSE;
                   SendMessage(hwnd,WM_PAINT,0,0);
                   break;
               case IDM_END:  
                   DeleteObject(hBitmap);
                   DeleteObject(hTempBMP);
                   DeleteObject(hTempMem);
                   PostQuitMessage(0);
                   break;
               default :return(DefWindowProc(hwnd, uMsg, wParam, lParam)); 
             }
             break;      
   case WM_DESTROY:
             DeleteObject(hBitmap);
             DeleteObject(hTempBMP);
             DeleteObject(hTempMem);             
             PostQuitMessage(0);
             break;
   default:return(DefWindowProc(hwnd, uMsg, wParam, lParam)); 
    }
  return (0);
}

ソースコード一式のダウンロード

capi_sample94.zip 37,382 バイト

動作環境

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