For anyone stumbling on this question after years, I tried Nyerguds' answer above, and while it did work for many programs such as Discord, it did not work out for pasting transparent pictures in Adobe Photoshop 2024 (25.12.3).
However, I did notice Photoshop will successfully paste transparent pictures copied from Google Chrome (but not Firefox).
For this reason, I have tried to investigate this by debugging the clipboard state, and while I don't have Nyerguds' intrinsic knowledge to really understand about what's going on internally in terms of format, here's a version that should work as a starting point for pasting transparent pictures in Photoshop.
You need to add a "Format17"
entry to the DataObject (also known as DIBV5), and the data must use the BITMAPV5HEADER with the bV5AlphaMask value set to to 0xFF000000
for Photoshop to acknowledge it as being a transparent picture.
The code below assumes you are already using Nyerguds' answer.
// byte[] dibData is the first 13 lines of the `public static Byte[] ConvertToDib(Image image)` code from Nyerguds's answer.
private static byte[] ToDibV5(byte[] dibData, int imageWidth, int imageHeight)
{
const uint dataStartPos = 0x7C;
var result = new byte[dataStartPos + dibData.Length];
// Lines with IGNORED means the value of 0 is used.
// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header
// 4 DWORD biSize;
ArrayUtils.WriteIntToByteArray(result, 0x00, 4, true, dataStartPos);
// 4 LONG biWidth;
ArrayUtils.WriteIntToByteArray(result, 0x04, 4, true, (uint)imageWidth);
// 4 LONG biHeight;
ArrayUtils.WriteIntToByteArray(result, 0x08, 4, true, (uint)imageHeight);
// 2 WORD biPlanes;
ArrayUtils.WriteIntToByteArray(result, 0x0C, 2, true, 0x01);
// 2 WORD biBitCount;
ArrayUtils.WriteIntToByteArray(result, 0x0E, 2, true, 0x20);
// IGNORED -- 4 DWORD biCompression;
// IGNORED -- 4 DWORD biSizeImage;
// IGNORED -- 4 LONG biXPelsPerMeter;
// IGNORED -- 4 LONG biYPelsPerMeter;
// IGNORED -- 4 DWORD biClrUsed;
// IGNORED -- 4 DWORD biClrImportant;
// IGNORED -- 4 DWORD bV5Size;
// IGNORED -- 4 LONG bV5Width;
// IGNORED -- 4 LONG bV5Height;
// IGNORED -- 2 WORD bV5Planes;
// IGNORED -- 2 WORD bV5BitCount;
// IGNORED -- 4 DWORD bV5Compression;
// IGNORED -- 4 DWORD bV5SizeImage;
// IGNORED -- 4 LONG bV5XPelsPerMeter;
// IGNORED -- 4 LONG bV5YPelsPerMeter;
// IGNORED -- 4 DWORD bV5ClrUsed;
// IGNORED -- 4 DWORD bV5ClrImportant;
// IGNORED -- 4 DWORD bV5RedMask;
// IGNORED -- 4 DWORD bV5GreenMask;
// IGNORED -- 4 DWORD bV5BlueMask;
// 4 DWORD bV5AlphaMask;
ArrayUtils.WriteIntToByteArray(result, 0x34, 4, true, 0xFF000000); // MUST BE SET for alpha to work in Photoshop.
// IGNORED - 4 DWORD bV5CSType;
// ArrayUtils.WriteIntToByteArray(fullImage, 0x38, 4, true, 0x57696E20); // Google Chrome sets this to LCS_WINDOWS_COLOR_SPACE(0x57696E20)
// CIEXYZTRIPLE bV5Endpoints;
// IGNORED - 4 DWORD bV5GammaRed;
// IGNORED - 4 DWORD bV5GammaGreen;
// IGNORED - 4 DWORD bV5GammaBlue;
// IGNORED - 4 DWORD bV5Intent;
// ArrayUtils.WriteIntToByteArray(fullImage, 0x6C, 4, true, 0x04); // Google Chrome sets this to LCS_GM_IMAGES(0x04)
// IGNORED - 4 DWORD bV5ProfileData;
// IGNORED - 4 DWORD bV5ProfileSize;
// IGNORED - 4 DWORD bV5Reserved;
Array.Copy(dibData, 0, result, dataStartPos, dibData.Length);
return result;
}
// Then, add this in your existing DataObject.
data.SetData("Format17", false, dibv5Data);
// If by any chance you are using SetClipboardData in user32.dll, use `(uint)17` instead of `"Format17"`.