Last active
August 29, 2015 14:16
-
-
Save hotwatermorning/fcc674dc4e56dac9b365 to your computer and use it in GitHub Desktop.
Draw bitmap image to memory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// DrawBitmap.cpp | |
// バイト列にビットマップデータを書き込んでウィンドウに表示。 | |
#include <cassert> | |
#include <cstdint> | |
#include <algorithm> | |
#include <memory> | |
#define WIN32_LEAN_AND_MEAN // Windows ヘッダーから使用されていない部分を除外します。 | |
// Windows ヘッダー ファイル: | |
#include <windows.h> | |
#include <tchar.h> | |
// グローバル変数: | |
HINSTANCE hInst; // 現在のインターフェイス | |
TCHAR szTitle[] = L"BITMAP_TEST_WINDOW"; // タイトル バーのテキスト | |
TCHAR szWindowClass[] = L"BITMAP_TEST_WINDOW_CLASS"; // メイン ウィンドウ クラス名 | |
// このコード モジュールに含まれる関数の宣言を転送します: | |
ATOM MyRegisterClass(HINSTANCE hInstance); | |
BOOL InitInstance(HINSTANCE, int); | |
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); | |
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); | |
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, | |
_In_opt_ HINSTANCE hPrevInstance, | |
_In_ LPTSTR lpCmdLine, | |
_In_ int nCmdShow) | |
{ | |
UNREFERENCED_PARAMETER(hPrevInstance); | |
UNREFERENCED_PARAMETER(lpCmdLine); | |
MSG msg; | |
MyRegisterClass(hInstance); | |
// アプリケーションの初期化を実行します: | |
if (!InitInstance (hInstance, nCmdShow)) | |
{ | |
return FALSE; | |
} | |
// メイン メッセージ ループ: | |
while (GetMessage(&msg, NULL, 0, 0)) | |
{ | |
TranslateMessage(&msg); | |
DispatchMessage(&msg); | |
} | |
return (int) msg.wParam; | |
} | |
// | |
// 関数: MyRegisterClass() | |
// | |
// 目的: ウィンドウ クラスを登録します。 | |
// | |
ATOM MyRegisterClass(HINSTANCE hInstance) | |
{ | |
WNDCLASSEX wcex; | |
wcex.cbSize = sizeof(WNDCLASSEX); | |
wcex.style = CS_HREDRAW | CS_VREDRAW; | |
wcex.lpfnWndProc = WndProc; | |
wcex.cbClsExtra = 0; | |
wcex.cbWndExtra = 0; | |
wcex.hInstance = hInstance; | |
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); | |
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); | |
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); | |
wcex.lpszMenuName = NULL; | |
wcex.lpszClassName = szWindowClass; | |
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); | |
return RegisterClassEx(&wcex); | |
} | |
// | |
// 関数: InitInstance(HINSTANCE, int) | |
// | |
// 目的: インスタンス ハンドルを保存して、メイン ウィンドウを作成します。 | |
// | |
// コメント: | |
// | |
// この関数で、グローバル変数でインスタンス ハンドルを保存し、 | |
// メイン プログラム ウィンドウを作成および表示します。 | |
// | |
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) | |
{ | |
HWND hWnd; | |
hInst = hInstance; // グローバル変数にインスタンス処理を格納します。 | |
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, | |
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); | |
if (!hWnd) | |
{ | |
int x = GetLastError(); | |
assert(x == 0); | |
return FALSE; | |
} | |
ShowWindow(hWnd, nCmdShow); | |
UpdateWindow(hWnd); | |
return TRUE; | |
} | |
int const bitmap_height = 300; | |
int const bitmap_width = 400; | |
HWND src_window; | |
HDC back_dc; | |
HBITMAP old_bitmap; | |
BITMAPINFO bitmap_info; | |
std::unique_ptr<std::int32_t[]> bitmap_data; | |
void SetupBitmap(HWND hWnd, int cx, int cy); | |
void CleanupBitmap(); | |
void UpdateBitmap(std::int32_t *data, int cx, int cy); | |
int interval_millisec = 10; | |
// | |
// 関数: WndProc(HWND, UINT, WPARAM, LPARAM) | |
// | |
// 目的: メイン ウィンドウのメッセージを処理します。 | |
// | |
// WM_COMMAND - アプリケーション メニューの処理 | |
// WM_PAINT - メイン ウィンドウの描画 | |
// WM_DESTROY - 中止メッセージを表示して戻る | |
// | |
// | |
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | |
{ | |
switch (message) | |
{ | |
case WM_CREATE: { | |
SetupBitmap(hWnd, bitmap_width, bitmap_height); | |
SetTimer(hWnd, 0, interval_millisec, NULL); | |
UpdateWindow(hWnd); | |
UpdateBitmap(bitmap_data.get(), bitmap_width, bitmap_height); | |
return 0; | |
} | |
case WM_TIMER: { | |
UpdateBitmap(bitmap_data.get(), bitmap_width, bitmap_height); | |
InvalidateRect(hWnd, NULL, FALSE); | |
break; | |
} | |
case WM_COMMAND: { | |
int wmId, wmEvent; | |
wmId = LOWORD(wParam); | |
wmEvent = HIWORD(wParam); | |
// 選択されたメニューの解析: | |
switch (wmId) | |
{ | |
case 0: | |
default: | |
return DefWindowProc(hWnd, message, wParam, lParam); | |
} | |
break; | |
} | |
case WM_PAINT: { | |
PAINTSTRUCT ps; | |
HDC hdc; | |
hdc = BeginPaint(hWnd, &ps); | |
RECT rc; | |
GetClientRect(hWnd, &rc); | |
StretchDIBits(hdc, 0, 0, rc.right, rc.bottom, 0, 0, bitmap_width, bitmap_height, bitmap_data.get(), &bitmap_info, DIB_RGB_COLORS, SRCCOPY); | |
EndPaint(hWnd, &ps); | |
break; | |
} | |
case WM_DESTROY: { | |
KillTimer(hWnd, 0); | |
CleanupBitmap(); | |
PostQuitMessage(0); | |
break; | |
} | |
default: | |
return DefWindowProc(hWnd, message, wParam, lParam); | |
} | |
return 0; | |
} | |
//====================================================================== | |
// Color functions | |
//====================================================================== | |
struct RGBColor | |
{ | |
double r_; | |
double g_; | |
double b_; | |
RGBColor(double r, double g, double b) | |
: r_(r) | |
, g_(g) | |
, b_(b) | |
{} | |
}; | |
struct HSVColor | |
{ | |
double hue_; | |
double saturation_; | |
double brightness_; | |
HSVColor(double hue, double saturation, double brightness) | |
: hue_(hue) | |
, saturation_(saturation) | |
, brightness_(brightness) | |
{} | |
}; | |
RGBColor HSVToRGB(double hue, double saturation, double brightness) | |
{ | |
assert(0 <= hue && hue <= 1.0); | |
assert(0 <= saturation && saturation <= 1.0); | |
assert(0 <= brightness && brightness <= 1.0); | |
double r = brightness; | |
double g = brightness; | |
double b = brightness; | |
if (saturation > 0.0f) { | |
hue *= 6.0f; | |
int const i = (int)hue; | |
double const f = hue - (float)i; | |
switch (i) { | |
default: | |
case 0: | |
g *= 1 - saturation * (1 - f); | |
b *= 1 - saturation; | |
break; | |
case 1: | |
r *= 1 - saturation * f; | |
b *= 1 - saturation; | |
break; | |
case 2: | |
r *= 1 - saturation; | |
b *= 1 - saturation * (1 - f); | |
break; | |
case 3: | |
r *= 1 - saturation; | |
g *= 1 - saturation * f; | |
break; | |
case 4: | |
r *= 1 - saturation * (1 - f); | |
g *= 1 - saturation; | |
break; | |
case 5: | |
g *= 1 - saturation; | |
b *= 1 - saturation * f; | |
break; | |
} | |
} | |
return RGBColor(r, g, b); | |
} | |
HSVColor RGBToHSV(double r, double g, double b) | |
{ | |
assert(0 <= r && r <= 1.0); | |
assert(0 <= g && g <= 1.0); | |
assert(0 <= b && b <= 1.0); | |
double max = r > g ? r : g; | |
max = max > b ? max : b; | |
double min = r < g ? r : g; | |
min = min < b ? min : b; | |
double h = max - min; | |
if (h > 0.0f) { | |
if (max == r) { | |
h = (g - b) / h; | |
if (h < 0.0f) { | |
h += 6.0f; | |
} | |
} else if (max == g) { | |
h = 2.0f + (b - r) / h; | |
} else { | |
h = 4.0f + (r - g) / h; | |
} | |
} | |
h /= 6.0f; | |
double s = (max - min); | |
if (max != 0.0f) | |
s /= max; | |
double v = max; | |
return HSVColor(h, s, v); | |
} | |
RGBColor HSVToRGB(HSVColor const &c) | |
{ | |
return HSVToRGB(c.hue_, c.saturation_, c.brightness_); | |
} | |
HSVColor RGBToHSV(RGBColor const &c) | |
{ | |
return RGBToHSV(c.r_, c.g_, c.b_); | |
} | |
//====================================================================== | |
// Bitmap functions | |
//====================================================================== | |
void SetupBitmap(HWND hWnd, int cx, int cy) | |
{ | |
src_window = hWnd; | |
HDC dc = GetDC(src_window); | |
back_dc = CreateCompatibleDC(dc); | |
HBITMAP back_bitmap = CreateCompatibleBitmap(dc, bitmap_width, bitmap_height); | |
bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); | |
bitmap_info.bmiHeader.biWidth = cx; | |
bitmap_info.bmiHeader.biHeight = cy; | |
bitmap_info.bmiHeader.biPlanes = 1; | |
bitmap_info.bmiHeader.biBitCount = 32; | |
bitmap_info.bmiHeader.biCompression = BI_RGB; | |
bitmap_data = std::make_unique<std::int32_t[]>(cx * cy); | |
GetDIBits(dc, back_bitmap, 0, cy, bitmap_data.get(), &bitmap_info, DIB_RGB_COLORS); | |
old_bitmap = (HBITMAP)SelectObject(back_dc, back_bitmap); | |
DeleteObject(back_bitmap); | |
ReleaseDC(src_window, dc); | |
} | |
void CleanupBitmap() | |
{ | |
SelectObject(back_dc, old_bitmap); | |
ReleaseDC(src_window, back_dc); | |
} | |
void UpdateBitmap(std::int32_t *bitmap, int cx, int cy) | |
{ | |
for(int y = 0; y < cy; ++y) { | |
for(int x = 0; x < cx; ++x) { | |
double hue = (x + y * cx) / (double)(cx * cy - 1); | |
auto rgb = HSVToRGB(hue, 1.0, 1.0); | |
int r = std::min<int>(static_cast<int>(rgb.r_ * 256), 255); | |
int g = std::min<int>(static_cast<int>(rgb.g_ * 256), 255); | |
int b = std::min<int>(static_cast<int>(rgb.b_ * 256), 255); | |
bitmap[x + y * cx] = r * (1 << 16) + g * (1 << 8) + b * (1 << 0); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment