/* HSL色空間の利用 2005/ 3/29 宍戸 輝光 */ #include #include #pragma comment(lib, "shlwapi.lib") LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); BOOL readBMP(LPCTSTR); void func(); HINSTANCE g_hInstance; HWND g_hwMain; LPBYTE g_lpDIB = NULL; LPBITMAPINFO g_lpbiInfo; LPDWORD g_lpdwPixel; int g_iWidth, g_iHeight; int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance, PSTR szCmdLine,int iCmdShow){ MSG msg; WNDCLASS wndclass; g_hInstance = hInstance; /* ウインドウクラス設定 */ wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "CHSL"; RegisterClass(&wndclass); /* メインウインドウ作成 */ g_hwMain = CreateWindow("CHSL", "HSL色空間の利用", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 560, 480, NULL, NULL, hInstance, NULL); DragAcceptFiles(g_hwMain, TRUE); /* ドラッグ&ドロップ受入 */ ShowWindow(g_hwMain, iCmdShow); while (GetMessage(&msg, NULL, 0, 0)) { /* メッセージループ */ TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam) { HDROP hDrop; HDC hdc; PAINTSTRUCT ps; TCHAR lpszFn[MAX_PATH + 1], lpszTmp[64]; static HWND hwBtn; int x, y, r, g, b; switch (iMsg) { case WM_CREATE: /* ボタン作成 */ hwBtn = CreateWindow("BUTTON", "実行", WS_CHILD|WS_VISIBLE, 224, 4, 72, 28, hwnd, (HMENU)0, g_hInstance, NULL); EnableWindow(hwBtn, FALSE); return 0; case WM_DROPFILES: /* ファイルがドロップされた時の処理 */ hDrop = (HDROP)wParam; /* HDROPを取得 */ DragQueryFile(hDrop, 0, lpszFn, 256); /* ファイル名を取得 */ /* BMP読み込み */ if (readBMP(lpszFn)) { EnableWindow(hwBtn, TRUE); } DragFinish(hDrop); /* 終了処理 */ /* ウインドウを再描画 */ InvalidateRgn(hwnd, NULL, TRUE); return 0; case WM_MOUSEMOVE: /* マウスカーソルの座標取得 */ x = LOWORD(lParam) - 4; y = g_iHeight - (HIWORD(lParam) - 34); if (g_lpDIB == NULL || x < 0 || x >= g_iWidth || y >= g_iHeight || y < 0) { return 0; } /* ピクセルのRGB成分算出 */ r = (g_lpdwPixel[x + y * g_iWidth] & 0x00ff0000) >> 16; g = (g_lpdwPixel[x + y * g_iWidth] & 0x0000ff00) >> 8; b = g_lpdwPixel[x + y * g_iWidth] & 0x000000ff; /* ウインドウタイトルに成分表示 */ wsprintf(lpszTmp, "(%d,%d):%d,%d,%d", x, y, r, g, b); SetWindowText(hwnd, lpszTmp); return 0; case WM_COMMAND: if (LOWORD(wParam) == 0 && g_lpDIB != NULL) { /* 実行ボタン */ /* HSL処理 */ func(); /* ウインドウを再描画 */ InvalidateRgn(hwnd, NULL, FALSE); } return 0; case WM_PAINT: hdc=BeginPaint(hwnd,&ps); if (g_lpDIB != NULL) { /* ビットマップが読み込まれていれば */ StretchDIBits(hdc, 4, 34, g_iWidth, g_iHeight, 0, 0, g_iWidth, g_iHeight, g_lpdwPixel, g_lpbiInfo, DIB_RGB_COLORS, SRCCOPY); /* DIBを画面に描画 */ } EndPaint(hwnd, &ps); return 0; case WM_DESTROY : if (g_lpDIB != NULL) { /* DIB用メモリ解放 */ HeapFree(GetProcessHeap(), 0, g_lpDIB); } PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; } BOOL readBMP(LPCTSTR lpszFn) { /* ビットマップ読み込み */ DWORD offset, dummy; LPBYTE lpBuf, lpPix; LPBITMAPINFO lpWrkBM; HANDLE fh; int i, j, iLength; fh = CreateFile(lpszFn, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /* ファイルオープン */ /* ファイル読み込みバッファ確保 */ lpBuf = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, GetFileSize(fh, NULL)); ReadFile(fh, lpBuf, GetFileSize(fh, NULL), &dummy, NULL); lpWrkBM = (LPBITMAPINFO)(lpBuf + sizeof(BITMAPFILEHEADER)); offset = *(LPDWORD)(lpBuf + 10); lpPix = lpBuf + offset; /* ビットマップバッファの先頭アドレス */ CloseHandle(fh); /* 24ビットフルカラービットマップでなければ無効 */ if (lpBuf[0] != 'B' || lpWrkBM->bmiHeader.biBitCount != 24) { HeapFree(GetProcessHeap(), 0, lpBuf); MessageBox(g_hwMain, "このファイルは使えません。", "エラー", MB_OK); return FALSE; } /* ビットマップの大きさ保存 */ g_iWidth = lpWrkBM->bmiHeader.biWidth; g_iHeight = lpWrkBM->bmiHeader.biHeight; if (g_iWidth % 4 == 0) { /* バッファの1ラインの長さを計算 */ iLength = g_iWidth * 3; } else { iLength = g_iWidth * 3 + (4 - (g_iWidth * 3) % 4); } if (g_lpDIB != NULL) { /* 以前確保したバッファを解放 */ HeapFree(GetProcessHeap(), 0, g_lpDIB); } g_lpDIB = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFO) + iLength * g_iHeight * 4); g_lpbiInfo = (LPBITMAPINFO)g_lpDIB; g_lpdwPixel = (LPDWORD)(g_lpDIB + sizeof(BITMAPINFO)); g_lpbiInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); g_lpbiInfo->bmiHeader.biWidth = g_iWidth; g_lpbiInfo->bmiHeader.biHeight = g_iHeight; g_lpbiInfo->bmiHeader.biPlanes = 1; g_lpbiInfo->bmiHeader.biBitCount = 32; g_lpbiInfo->bmiHeader.biCompression = BI_RGB; /* BMP内のピクセルを32ビット化してコピー */ for (i = 0;i < g_iHeight;i++) for (j = 0;j < g_iWidth; j++) CopyMemory(g_lpdwPixel + j + i * g_iWidth, lpPix + j * 3 + i * iLength, 3); HeapFree(GetProcessHeap(), 0, lpBuf); return TRUE; } /* 下位24ビットのうち、1-8ビット目と17-24ビット目を入れ替える */ DWORD RGBcvCOLORREF(DWORD dwSrc) { DWORD dw3 = (dwSrc & 0x00ff0000) >> 16; DWORD dw2 = dwSrc & 0x0000f000; DWORD dw1 = (dwSrc & 0x000000ff) << 16; return dw1 | dw2 | dw3; } void func() { /* HSLをいじる */ WORD wH, wL, wS; for (int i = 0;i < g_iHeight;i++) { for (int j = 0;j < g_iWidth; j++) { /* (j, i)のRGBをHSLに変換 */ ColorRGBToHLS(RGBcvCOLORREF(g_lpdwPixel[j + i * g_iWidth]), &wH, &wL, &wS); /* Hを60加算 */ wH += 60; /* 0-239に丸める */ wH %= 240; /* 処理したHSLをRGBに戻してピクセルに設定 */ g_lpdwPixel[j + i * g_iWidth] = RGBcvCOLORREF(ColorHLSToRGB(wH, wL, wS)); } } InvalidateRect(g_hwMain, NULL, FALSE); }