How might one copy a 32bit (per pixel) RGBA image to Windows' Clipboard? I've arrived to this function after a lot of trial, but no luck in having my image data "paste" at all. It does not appear in the Clipboard's history either.
Slightly editing it to use CF_DIB and the BITMAPINFOHEADER header has yielded a "copy" entry in that history and an image of the correct size when pasted, though sticking a png on the back of a CF_DIB has caused programs to glitch out in incredibly interesting and non-benign ways.
My goal is to copy an image with an alpha channel to the Clipboard, and to have the colors not be multiplied against this alpha during the hand-off. What am I be doing wrong..?
bool copyBitmapIntoClipboard(Window & window, const Bitmap & in) {
// this section is my code for creating a png file
StreamWrite stream = StreamWrite::asBufferCreate();
in.savePng(stream);
uint64 bufSize = 0;
char * buf = stream._takeBuffer(bufSize, false);
// "buf" <-- contains the PNG payload
// "bufSize" <-- is the size of this payload
// beyond this point, it's just standard windows' stuff that doesn't rely on my code
BITMAPV5HEADER header;
header.bV5Size = sizeof(BITMAPV5HEADER);
header.bV5Width = in.getX(); // <-- size of the bitmap in pixels, width and height
header.bV5Height = in.getY();
header.bV5Planes = 1;
header.bV5BitCount = 0;
header.bV5Compression = BI_PNG;
header.bV5SizeImage = bufSize;
header.bV5XPelsPerMeter = 0;
header.bV5YPelsPerMeter = 0;
header.bV5ClrUsed = 0;
header.bV5ClrImportant = 0;
header.bV5RedMask = 0xFF000000;
header.bV5GreenMask = 0x00FF0000;
header.bV5BlueMask = 0x0000FF00;
header.bV5AlphaMask = 0x000000FF;
header.bV5CSType = LCS_sRGB;
header.bV5Endpoints; // ignored
header.bV5GammaRed = 0;
header.bV5GammaGreen = 0;
header.bV5GammaBlue = 0;
header.bV5Intent = 0;
header.bV5ProfileData = 0;
header.bV5ProfileSize = 0;
header.bV5Reserved = 0;
HGLOBAL gift = GlobalAlloc(GMEM_MOVEABLE, sizeof(BITMAPV5HEADER) + bufSize);
if (gift == NULL)
return false;
HWND win = window.getWindowHandle();
if (!OpenClipboard(win)) {
GlobalFree(gift);
return false;
}
EmptyClipboard();
void * giftLocked = GlobalLock(gift);
if (giftLocked) {
memcpy(giftLocked, &header, sizeof(BITMAPV5HEADER));
memcpy((char*)giftLocked + sizeof(BITMAPV5HEADER), buf, bufSize);
}
GlobalUnlock(gift);
SetClipboardData(CF_DIBV5, gift);
CloseClipboard();
return true;
}