BITMAPV5HEADER getting RGBA keep A at 255

2019-08-15 14:45发布

问题:

I am obtaining a byte array of a screenshot by the following, this is done in ctypes, there is no issues with the ctypes, if I gave this a ctypes tag the ctypes folks would be confused, so I simplified out all the error checking etc to show you the procedure.

CreateDC('DISPLAY', null, null, null);

nWidth = GetDeviceCaps(hdcScreen, HORZRES); // 1280 // numbers are always divisilbe by 4
nHeight = GetDeviceCaps(hdcScreen, ostypes.CONST.VERTRES); // 1024
nBPP = GetDeviceCaps(hdcScreen, BITSPIXEL); // 32

hdcMemoryDC = ostypes.API('CreateCompatibleDC')(hdcScreen);

bmi = BITMAPV5HEADER();
bmi.bV5Size = BITMAPV5HEADER.size;
bmi.bV5Width = nWidth;
bmi.bV5Height = -1 * nHeight; // top-down
bmi.bV5Planes = 1;
bmi.bV5BitCount = nBPP;
bmi.bV5Compression = BI_BITFIELDS;
bmi.bV5RedMask = 0xff;
bmi.bV5GreenMask = 0xff00;
bmi.bV5BlueMask = 0xff0000;
bmi.bV5AlphaMask = 0xff000000;

cBmi = ctypes.cast(bmi.address(), BITMAPINFO.ptr);
pixelBuffer = BYTE.ptr();
hbmp = CreateDIBSection(hdcScreen, cBmi, DIB_RGB_COLORS, pixelBuffer.address(), null, 0); 

SelectObject(hdcMemoryDC, hbmp);

BitBlt(hdcMemoryDC, 0,0, nWidth, nHeight, hdcScreen, 0, 0, SRCCOPY);

byteArr = ctypes.cast(pixelBuffer, BYTE.array(arrLen).ptr).contents;

So with the above flags I get a BGRA byteArr which looks like this:

array(5242880)([240, 200, 105, 255, ..... ])

So the B is 240, G is 200, R is 105, and A is 255.

I want to get this into a RGBA form (it's important it's done on the C side for ctypes performance reasons).

So now we can successfully get it into RGBA form HOWEVER the A becomes 0, by using these masks:

bmi.bV5RedMask = 0xff0000;
bmi.bV5GreenMask = 0xff00;
bmi.bV5BlueMask = 0xff;
bmi.bV5AlphaMask = 0xff000000; // we also tried 0x00000000

This now gives us:

array(5242880)([105, 200, 240, 0, ..... ])

So the issue is the A value is going to 0, how can I keep this RGBA format, but keep the A value at 255.

回答1:

BitBlt, like nearly all GDI functions, doesn't preserve the alpha values.

If you're blitting from the screen, then all the alphas are 255--the screen doesn't have holes of transparency. So you can just set the alphas yourself after doing the blit.