问题
The code provided at the end draws a grid of red 3x3px rectangles with a random constant alpha value using AlphaBlend()
. The output however, turns out not "quite" random:
Notice runs of constant alpha along x-axis.
What might be causing this?
P.S. Stepping though the debugger produces the expected output.
Code to produce output:
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);
};
EDIT - As I look more into it, here are the additional issues I have noticed:
1- Output is normal when AlphaBlend()
destination is a memory DC, but not when a window DC. So the issue has to do with bliting directly to screen.
2- Corrupt output is unrelated to use of rand()
function. Replacing BYTE rnd_alpha = rand();
with ++alpha
also produces somewhat similar corrupt outputs.
3- More interestingly, suspending the thread in the inner loop such as Sleep(some_duration)
seems to reduce the corruption. Higher the some_duration
, less the corruption. Here is a sample output:
First output is generated by first blitting to a memory DC, then to window. The rest is directly to the window. Notice how corruption increases(i.e. output becomes less random) as thread suspension time decreases.
来源:https://stackoverflow.com/questions/47056848/win32-gdi-alphablend-not-using-constant-alpha-value-correctly