C++ C++;在给定的像素数据数组上绘制矩形

C++ C++;在给定的像素数据数组上绘制矩形,c++,winapi,C++,Winapi,我将图像数据作为RGB数据的多维数组读取,并希望在WM_PAINT中的某个位置将其绘制在窗体上 我知道如何从文件中读取整个位图并在某个位置绘制: case WM_PAINT: PAINTSTRUCT ps; HDC hdc; BITMAP bitmap; HDC hdcMem; HGDIOBJ oldBitmap;

我将图像数据作为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;
但不是如何将特定像素数据作为位图显示在窗体上。我已经找了好几天了

感谢您的帮助。

基本上,请使用

以下是最低限度的示例用法:

#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;
}
#包括
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM);
int WINAPI WinMain(HINSTANCE HINSTANCE、HINSTANCE HPPreInstance、LPSTR lpCmdLine、int nCmdShow)
{
MSG={0};
WNDCLASS wc={0};
wc.lpfnWndProc=WndProc;
wc.hInstance=hInstance;
wc.hbrBackground=(HBRUSH)(彩色背景);
wc.lpszClassName=L“createdibsection_示例”;
如果(!注册表类(&wc))
返回1;
如果(!CreateWindow(wc.lpszClassName,
L“createdibsection示例”,
WS|U重叠窗口| WS|U可见,
0,0,640,480,0,0,hInstance,NULL)
返回2;
while(GetMessage(&msg,NULL,0,0)>0)
发送消息(&msg);
返回0;
}
HBITMAP CreateBitmapAndFillPtrToItsData(无符号字符**ptr_数据,整数wd,整数hgt)
{
HDC hdcScreen=GetDC(NULL);
BITMAPINFO bmi;
memset(&bmi,0,sizeof(BITMAPINFO));
bmi.bmiHeader.biSize=sizeof(BitMapInfo头文件);
bmi.bmiHeader.biWidth=wd;
bmi.bmiHeader.biHeight=-hgt;//自上而下
bmi.bmiHeader.biPlanes=1;
bmi.bmiHeader.biBitCount=32;
bmi.bmiHeader.biCompression=BI_RGB;
自动bmp=CreateDIBSection(hdcScreen,&bmi,DIB_RGB_颜色,(void**)ptr_数据,NULL,NULL);
ReleaseDC(空,hdcScreen);
返回bmp;
}
无效CopyInPixelData(无符号字符*ptr_数据,整数wd,整数hgt)
{
//这只是一个用于教程目的的示例…生成一个红色圆圈
//在白色字段中…实际代码将从文件加载,等等。
int c_x=wd/2;
国际货币基金组织=hgt/2;
int半径=c_x;
int i=0;
对于(int y=0;y如果((x-c_x)*(x-c_x)+(y-c_y)*(y-c_y)从像素数据创建位图。查看函数,如
CreateDibSection()
CreateDIBitmap()
SetDIBits()
setDibitToDevice()
,等等。然后像通常一样将位图绘制到表单上。谢谢,按照它所采用的格式,如何在ptr_数据中设置特定的x,y rgb点?像素格式取决于在BitMapinFoHeader结构中传递的biCompression和biBitCount值。我刚刚更新了上面的代码,以便更宽容。当你传递BI时_RGB作为双压缩,你说的是tou将只列出RGB值,然后biBitCount表示每个像素有多少位,通常是24位或32位,即每个像素有三个字节,alpha是否有一个字节。数据是逐行排列的,必须是DWORD对齐的。如果你设置了每个像素32位,就像我现在看到的那样,你不需要e担心填充行/对齐。