I want my app (which works with RGBA8888 images) to be able to paste images from the Windows clipboard. So it should be able to read images off the clipboard that come from any common raster image apps like Gimp, Photoshop, MSPaint, etc.
From reading up on the clipboard functions, it seems I should be able to call GetClipboardData(CF_DIBV5)
to get access to pretty much any bitmap type that’s on the Clipboard since Windows automatically converts between that and CF_BITMAP and CF_DIB. But from reading up on the DIB format, I see that there is an immense number of possible combinations of bit depth, RGB order, optional compression, etc. It seems like what I’m doing would be a common task, but I don’t see any conversion functions in the Windows API (unless I’m poor at searching), and this seems like something that would take a week to write to support all possible formats. So I’m wondering if I’ve overlooked something obvious. Or if there is some kind of assumption I can make to simplify this…like if all the popular image apps happen to copy images to the clipboard in uncompressed/unindexed formats.
UPDATE: Here’s what I have so far:
HGLOBAL clipboard = GetClipboardData(CF_DIBV5);
exists = clipboard != NULL;
int dataLength = GlobalSize(clipboard);
exists = dataLength != 0;
if (exists) {
LPTSTR lockedClipboard = GlobalLock(clipboard);
exists = lockedClipboard != NULL;
if (exists) {
BITMAPV5HEADER *header = (BITMAPV5HEADER*)lockedClipboard;
LONG width = header->bV5Width;
LONG height = header->bV5Height;
BYTE *bits = header + sizeof(header) + header->bV5ClrUsed * sizeof(RGBQUAD);
//Now what? Need function to convert the bits to something uncompressed.
GlobalUnlock(clipboard);
}
}
UPDATE 2:
To clarify, I need literally uncompressed 32 bit image data (RRGGBBAA) which I can manipulate however I like in a cross-platform app. I have no need to use Windows APIs to draw this image to screen.
I am aware of a 3rd party library called stdb_image.h
that can load .bmps, .jpgs, and .pngs into the type of data I need. So if there’s a way I can turn the clipboard data into bitmap or png file data without losing alpha, then I’ll be in good shape.
2
Answers
The basic strategy I've found is to check if there's a raw PNG on the clipboard and use that first if available. That's the easiest. Some apps, such as GIMP, copy images as PNG to the clipboard.
Then check for
CF_DIBV5
. The location of the actual bits depends on whether the "compression" isBI_BITFIELDS
:If the header says compression is
BI_BITFIELDS
, then the data is already as I needed it.If the header says compression is
BI_RGB
and the bit count is 24 or 32, then I can unpack the bytes. 24 bytes means row size might not land on a DWORD boundary, so you have to watch for that.Finally, lower bit counts than 24 likely mean indexed color, which I don't have working yet.
Here is example of usage for
CF_DIBV5
andCF_DIB
. It’s best to useCF_DIB
as backup option. Note, this code won’t work for palette based images (if it is not guaranteed 32bit then see the method further down)You can use
SetDIBitsToDevice
to draw directly onHDC
, or useSetDIBits
GDI functions don’t support alpha transparency (except for a couple of functions like
TransparentBlt
), in general you have to use libraries such as GDI+ for that.If the original image is palette based, you would have to convert to 32bit. Alternatively you could add
BITMAPFILEHEADER
to the data (assuming the source is bitmap) then pass to the other library.This is an example using
CreateDIBitmap
andGetDIBits
to make sure the pixels are in 32bit: