Win32 GDI:AlphaBlend()没有正确使用常量alpha值

时间:2017-11-01 14:10:23

标签: c++ winapi gdi

最后提供的代码使用AlphaBlend()绘制一个红色3x3px矩形网格,其中包含随机常数alpha值。然而,输出结果并非如此"相当"随机:

sample_output

注意沿x轴运行恒定的alpha。

可能导致这种情况的原因是什么?

P.S。通过调试器步进产生预期的输出。

产生输出的代码:

void draw_mark(HDC hdc, int x, int y, 
               COLORREF mark_clr, int mark_w, int mark_h, BYTE alpha);

void produce_output(HWND hWnd) {
    InvalidateRect(hWnd, NULL, TRUE);
    UpdateWindow(hWnd);

    const int grid_w = 64, grid_h = 64;
    const int mark_sz = 3;
    HDC hdc = GetDC(hWnd);
    for(int y = 0; y < grid_h; ++y) {
        for(int x = 0; x < grid_w; ++x) {
            BYTE rnd_alpha = rand();    // use random alpha for each mark
            draw_mark(hdc, x * mark_sz, y * mark_sz, 
                      RGB(255,0,0), mark_sz, mark_sz, rnd_alpha);
        }
    }

    // clean-up
    ReleaseDC(hWnd, hdc);
}

// draws a [mark_w x mark_h] rectangle at (x,y) with alpha
void draw_mark(HDC hdc, int x, int y, 
               COLORREF mark_clr, int mark_w, int mark_h, BYTE alpha) 
{
    HDC hdcMem = CreateCompatibleDC(NULL);
    HBITMAP hbm = CreateCompatibleBitmap(hdc, mark_w, mark_h);
    HGDIOBJ hOldBmp = SelectObject(hdcMem, hbm);

    for(int x = 0; x < mark_w; ++x) {
        for(int y = 0; y < mark_h; ++y) {
            SetPixel(hdcMem, x, y, mark_clr);
        }
    }
    POINT marker_center{mark_w / 2, mark_h / 2};
    SetPixel(hdcMem, marker_center.x, marker_center.y, RGB(255, 255, 255));

    BLENDFUNCTION bf{};
    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.AlphaFormat = 0;             // ignore source per-pixel alpha and...
    bf.SourceConstantAlpha = alpha; // ...use constant alpha provided instead

    AlphaBlend(hdc, 
               x - marker_center.x, y - marker_center.y, 
               mark_w, mark_h,  
               hdcMem, 0, 0, mark_w, mark_h, bf);

    // clean-up
    SelectObject(hdcMem, hOldBmp);
    DeleteObject(hbm);
    DeleteDC(hdcMem);
};

编辑 - 当我更多地了解它时,我注意到了其他问题:

1-当AlphaBlend()目的地是内存DC时输出正常,但在窗口DC时则不正常。所以这个问题与直接在屏幕上显示有关。

2- Corrupt输出与使用rand()功能无关。用BYTE rnd_alpha = rand();替换++alpha也会产生类似的损坏输出。

3-更有趣的是,将帖子暂停在内循环中,例如Sleep(some_duration)似乎可以减少损坏。 some_duration越高,腐败越少。这是一个示例输出:

enter image description here

首先输出到存储器DC,然后到窗口,产生第一个输出。其余的直接到窗口。注意随着线程暂停时间的减少,腐败如何增加(即输出变得不那么随机)。

0 个答案:

没有答案