Как избежать SetPixel (), но все же быть в состоянии указать цвет для каждого пикселя? - PullRequest
0 голосов
/ 03 января 2019

Функция WINAPI SetPixel() очень медленная, но она позволяет задавать цвет для отдельного пикселя.

Функции WINAPI, такие как LineTo() и Polyline(), используют цвет пераэто выбирается в контексте устройства, который является одним цветом.

При использовании этих функций рисование выполняется намного быстрее, чем SetPixel(), но выбор отдельного цвета пикселя теряется.

Какможно ли указать цвет для каждого отдельного пикселя и получить выгоду от скорости, аналогичной скорости Polyline()?

Рассмотрим следующий код:

#include <Windows.h>
#include <math.h>

int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    PSTR lpCmdLine,
    int iCmdShow)
{
    const char szAppName[] = "App";
    const char szWinName[] = "Draw gfx";

    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wndclass.lpfnWndProc = WndProc;
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))
    {
        return 0;
    }

    HWND hwnd;
    hwnd = CreateWindow(
        szAppName,
        szWinName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    if (!hwnd)
    {
        return 0;
    }

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(
    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    static POINT apt[256];
    static int iApt = sizeof(apt) / sizeof(*apt);

    static int cxClient;
    static int cyClient;

    HDC hdc;
    PAINTSTRUCT ps;

    switch (message)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        HPEN hPen;
        hPen = CreatePen(PS_SOLID, 1, RGB(255, 215, 0));
        SelectObject(hdc, hPen);

        // Set the array of points
        for (int i = 0; i < iApt; i++)
        {
            apt[i].x = i * cxClient / iApt;
            apt[i].y = (cyClient / 4 * (1 - sin((2 * 3.14159) * i / iApt)));
        }

        //draw using Polyline()
        Polyline(hdc, apt, iApt);

        // draw using SetPixel()
        int b;
        b = 0;
        for (int i = 0; i < iApt; i++)
        {
            // descend 100 pixels to not overwrite previous curve
            apt[i].y += 100;

            // draw
            SetPixel(hdc, apt[i].x, apt[i].y, RGB(0, 0, b));
            b++;
        }

        DeleteObject(hPen);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(
        hwnd,
        message,
        wParam,
        lParam);
}

PS: я знаю, чтовторая кривая пунктирная, в отличие от результата Polyline (), но сейчас это не мое дело.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...