我正在读取RGB数据的多维数组形式的图像数据,并希望将其绘制在WM_PAINT中某个位置的表单上
我知道如何从文件中读取整个位图并将其绘制在某个位置:
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc;
BITMAP bitmap;
HDC hdcMem;
HGDIOBJ oldBitmap;
hdc = BeginPaint(hwnd, &ps);
hdcMem = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(hdcMem, hBitmap);
GetObject(hBitmap, sizeof(bitmap), &bitmap);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBitmap);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
break;
但不是如何处理特定像素数据作为表单上的位图的问题。我一直在寻找真实的日子。
任何帮助表示赞赏。
答案 0 :(得分:4)
基本上,使用CreateDibSection(...)。
下面的最小用法示例:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = L"createdibsection_example";
if (!RegisterClass(&wc))
return 1;
if (!CreateWindow(wc.lpszClassName,
L"createdibsection example",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480, 0, 0, hInstance, NULL))
return 2;
while (GetMessage(&msg, NULL, 0, 0) > 0)
DispatchMessage(&msg);
return 0;
}
HBITMAP CreateBitmapAndFillPtrToItsData(unsigned char** ptr_data, int wd, int hgt)
{
HDC hdcScreen = GetDC(NULL);
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = wd;
bmi.bmiHeader.biHeight = -hgt; // top-down
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
auto bmp = CreateDIBSection(hdcScreen, &bmi, DIB_RGB_COLORS, (void**) ptr_data, NULL, NULL);
ReleaseDC(NULL, hdcScreen);
return bmp;
}
void CopyInPixelData(unsigned char* ptr_data, int wd, int hgt)
{
// this is just an example for tutorial purposes ... generate a red circle
// in a white field ... real code would load from a file, etc.
int c_x = wd / 2;
int c_y = hgt / 2;
int radius = c_x;
int i = 0;
for (int y = 0; y < hgt; y++) {
for (int x = 0; x < wd; x++) {
if ((x-c_x)*(x-c_x) + (y-c_y)*(y-c_y) <= radius*radius) {
ptr_data[i++] = 0;
ptr_data[i++] = 0;
ptr_data[i++] = 255;
ptr_data[i++] = 0;
} else {
ptr_data[i++] = 255;
ptr_data[i++] = 255;
ptr_data[i++] = 255;
ptr_data[i++] = 0;
}
}
}
}
HBITMAP CreateBitmapFromPixelDataExample(int wd, int hgt)
{
// create a bitmap such that we get a pointer to where its data is stored
unsigned char* ptr_data;
auto bitmap = CreateBitmapAndFillPtrToItsData( &ptr_data, wd, hgt );
// fill in some pixel data...
CopyInPixelData( ptr_data, wd, hgt );
return bitmap;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HBITMAP bitmap;
switch (message)
{
case WM_CREATE: {
bitmap = CreateBitmapFromPixelDataExample(85, 85);
} break;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_PAINT: {
RECT r;
GetClientRect(hWnd, &r);
auto hdc_bitmap = CreateCompatibleDC(NULL);
auto hbm_old = (HBITMAP)SelectObject(hdc_bitmap, bitmap);
PAINTSTRUCT ps;
auto hdc = BeginPaint(hWnd, &ps);
// clear bkgd
FillRect(hdc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
// paint in the bitmap we generated from pixel data...
BitBlt(hdc, 10, 10, 85, 85, hdc_bitmap, 0, 0, SRCCOPY);
EndPaint(hWnd, &ps);
SelectObject(hdc_bitmap, hbm_old);
DeleteDC(hdc_bitmap);
} break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}