首页 > 解决方案 > 如何增加位图像素大小?

问题描述

我正在努力寻找增加 win32 位图中像素大小的方法。有什么办法吗?

我在下面做了一个小的win32程序。当你运行它时,你应该得到一个窗口,中间有一个非常小的红点。您可以使用向上、向下、向左和向右箭头键来控制圆点。

/* compile: gcc test.c -o test -lgdi32 -Wl,-subsystem,windows */
// TODO fast way to update? resize pixel size? best coding practices?

#include <windows.h>

#define WND_WIDTH 500
#define WND_HEIGHT 500

#define ID_TIMER 1

void DrawBitmap(HDC hdc, RECT *rect, BITMAPINFO info, void *bmpMem)
{
    int width = rect->right - rect->left;
    int height = rect->bottom - rect->top;
    
    StretchDIBits(hdc,
                  0,
                  0,
                  info.bmiHeader.biWidth,
                  info.bmiHeader.biHeight,
                  0,
                  0,
                  width,
                  height,
                  bmpMem,
                  &info,
                  DIB_RGB_COLORS,
                  SRCCOPY);
}

void UpdateBitmap(BITMAPINFO info, void *bmpMem, POINT pix)
{
    int width = info.bmiHeader.biWidth;
    int height = info.bmiHeader.biHeight;
    
    BYTE *pixel = (BYTE *) bmpMem;
    
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            if (x == pix.x && y == pix.y)
            {
                *pixel++ = 0;   /* blue */
                *pixel++ = 0;   /* green */
                *pixel++ = 255; /* red */
                *pixel++ = 255; /* alpha */
            }
            else
            {
                *pixel++ = 0;   /* blue */
                *pixel++ = 0;   /* green */
                *pixel++ = 0;   /* red */
                *pixel++ = 255; /* alpha */
            }
        }
    }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static BITMAPINFO info;
    static void *bmpMem;
    static POINT pixel;
    
    switch (msg)
    {
    case WM_CREATE:
    {
        RECT rcClient;
        
        GetClientRect(hWnd, &rcClient);
        
        int width = rcClient.right - rcClient.left;
        int height = rcClient.bottom - rcClient.top;
        
        info.bmiHeader.biSize = sizeof(info.bmiHeader);
        info.bmiHeader.biWidth = width;
        info.bmiHeader.biHeight = height;
        info.bmiHeader.biPlanes = 1;
        info.bmiHeader.biBitCount = 32;
        info.bmiHeader.biCompression = BI_RGB;
        info.bmiHeader.biSizeImage = 0;
        info.bmiHeader.biXPelsPerMeter = 0;
        info.bmiHeader.biYPelsPerMeter = 0;
        info.bmiHeader.biClrUsed = 0;
        info.bmiHeader.biClrImportant = 0;
        
        bmpMem = VirtualAlloc(0, width * height * 4, MEM_COMMIT, PAGE_READWRITE);
        
        pixel.x = width / 2;
        pixel.y = height / 2;
        
        if(!SetTimer(hWnd, ID_TIMER, 50, NULL))
        {
            MessageBox(hWnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
            PostQuitMessage(1);
        }
        
        break;
    }/*
    case WM_PAINT:
    {
        RECT rcClient;
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        
        GetClientRect(hWnd, &rcClient);
        DrawBitmap(hdc, &rcClient, info, bmpMem);
        
        EndPaint(hWnd, &ps);
        break;
    }*/
    case WM_TIMER:
    {
        RECT rcClient;
        HDC hdc = GetDC(hWnd);
        
        GetClientRect(hWnd, &rcClient);
        UpdateBitmap(info, bmpMem, pixel);
        DrawBitmap(hdc, &rcClient, info, bmpMem);
        
        ReleaseDC(hWnd, hdc);
        break;
    }
    case WM_KEYDOWN:
    {
        switch (wParam)
        {
        case VK_LEFT: pixel.x -= 1; break;
        case VK_RIGHT: pixel.x += 1; break;
        case VK_UP: pixel.y += 1; break;
        case VK_DOWN: pixel.y -= 1; break;
        }
        break;
    }
    case WM_CLOSE:
        DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        KillTimer(hWnd, ID_TIMER);
        VirtualFree(bmpMem, 0, MEM_RELEASE);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    const TCHAR szClassName[] = TEXT("MyClass");
    
    WNDCLASS wc;
    HWND hWnd;
    MSG msg;
    
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = szClassName;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    
    if (!RegisterClass(&wc))
    {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
            MB_ICONEXCLAMATION | MB_OK);
        return 1;
    }
    
    hWnd = CreateWindow(szClassName,
                        TEXT("Title"),
                        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, /* this window style prevents window resizing */
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        WND_WIDTH,
                        WND_HEIGHT,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);
    
    if (hWnd == NULL)
    {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
            MB_ICONEXCLAMATION | MB_OK);
        return 1;
    }
    
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    return (int) msg.wParam;
}

我想增加位图中小红点和所有其他像素的大小。我试图像这样减小宽度和高度

    switch (msg)
    {
    case WM_CREATE:
    {
        //RECT rcClient;

        //GetClientRect(hWnd, &rcClient);

        int width = 30;
        int height = 30;

我希望在中心看到一个大红点,但我得到了白屏。如何编辑代码以显示更大的像素?

标签: c++cwinapiwin32gui

解决方案


您正在 UpdateBitmap 中创建单个红色像素:

if (x == pix.x && y == pix.y)
{
    *pixel++ = 0;   /* blue */
    *pixel++ = 0;   /* green */
    *pixel++ = 255; /* red */
    *pixel++ = 255; /* alpha */
}

如果你想要一个更大的“点” - 在某处定义一个半径:

int r = 17;

并将您的条件更改为

if ((x - pix.x)* (x - pix.x) + (y - pix.y)* (y - pix.y) <= r*r)

要缩放整个位图,请修改DrawBitmap

void DrawBitmap(HDC hdc, RECT* rect, BITMAPINFO info, void* bmpMem)
{
    int width = rect->right - rect->left;
    int height = rect->bottom - rect->top;
    int scale = 7;
    StretchDIBits(hdc,
        -(info.bmiHeader.biWidth * scale - width) / 2,
        -(info.bmiHeader.biHeight * scale - height) / 2,
        info.bmiHeader.biWidth * scale,
        info.bmiHeader.biHeight * scale,
        0,
        0,
        width,
        height,
        bmpMem,
        &info,
        DIB_RGB_COLORS,
        SRCCOPY);
}

StretchDIBits将源区域(由 指定)拉伸(或缩小)0, 0, width, height到目标区域。在这个例子中,我将目的地的大小放大了scale- 所以图像会被拉伸。负偏移量是将图像“居中”在目标上;你可以0,0用来保持左上角的锚点。


推荐阅读