I am writing an extremely small C++ program to help me animate sprites. I'd like it to take data I copy to the clipboard from photoshop, manipulate it in my program, then overwrite the clipboard with the transform.
The problem though is that I'm not sure how to read the initial clipboard from photoshop.
I can load the clipboard with GetClipboardData(CF_DIB)
, and get a valid handle, but I've no idea how to use that handle. I've tried using SFML's Image::LoadFromMemory(handle, GlobalSize(handle))
which is able to load bitmap files from memory, but that doesn't seem to work.
Will I need to actually parse the entire format? What format structure would I be looking at in that case? Would there perhaps be any way I could quickly mangle the data so it might look like a bitmap file? Could it be easier/possible to simply save it to file using the windows API? (I could then load that file with SFML to edit, that way)
It's just a quick and dirty tool for myself to save a lot of grunt work in photoshop, so efficiency or robustness aren't important at all.
Learn the bitmap structure from Wikipedia and then write it out to a file and then write out the pixels..
I've tested the below with Paint on Windows 8.1. I opened an image with paint and then pressed Ctrl + C to copy to the clipboard.. then I ran the following code and it copied the clipboard image to the desktop:
#include <iostream>
#include <fstream>
#include <windows.h>
typedef struct
{
std::uint32_t biSize;
std::int32_t biWidth;
std::int32_t biHeight;
std::uint16_t biPlanes;
std::uint16_t biBitCount;
std::uint32_t biCompression;
std::uint32_t biSizeImage;
std::int32_t biXPelsPerMeter;
std::int32_t biYPelsPerMeter;
std::uint32_t biClrUsed;
std::uint32_t biClrImportant;
} DIB;
typedef struct
{
std::uint16_t type;
std::uint32_t bfSize;
std::uint32_t reserved;
std::uint32_t offset;
} HEADER;
typedef struct
{
HEADER header;
DIB dib;
} BMP;
int main()
{
std::cout<<"Format Bitmap: "<<IsClipboardFormatAvailable(CF_BITMAP)<<"\n";
std::cout<<"Format DIB: "<<IsClipboardFormatAvailable(CF_DIB)<<"\n";
std::cout<<"Format DIBv5: "<<IsClipboardFormatAvailable(CF_DIBV5)<<"\n";
if (IsClipboardFormatAvailable(CF_BITMAP) || IsClipboardFormatAvailable(CF_DIB) || IsClipboardFormatAvailable(CF_DIBV5))
{
if (OpenClipboard(NULL))
{
HANDLE hClipboard = GetClipboardData(CF_DIB);
if (!hClipboard)
{
hClipboard = GetClipboardData(CF_DIBV5);
}
if (hClipboard != NULL && hClipboard != INVALID_HANDLE_VALUE)
{
void* dib = GlobalLock(hClipboard);
if (dib)
{
DIB *info = reinterpret_cast<DIB*>(dib);
BMP bmp = {0};
bmp.header.type = 0x4D42;
bmp.header.offset = 54;
bmp.header.bfSize = info->biSizeImage + bmp.header.offset;
bmp.dib = *info;
std::cout<<"Type: "<<std::hex<<bmp.header.type<<std::dec<<"\n";
std::cout<<"bfSize: "<<bmp.header.bfSize<<"\n";
std::cout<<"Reserved: "<<bmp.header.reserved<<"\n";
std::cout<<"Offset: "<<bmp.header.offset<<"\n";
std::cout<<"biSize: "<<bmp.dib.biSize<<"\n";
std::cout<<"Width: "<<bmp.dib.biWidth<<"\n";
std::cout<<"Height: "<<bmp.dib.biHeight<<"\n";
std::cout<<"Planes: "<<bmp.dib.biPlanes<<"\n";
std::cout<<"Bits: "<<bmp.dib.biBitCount<<"\n";
std::cout<<"Compression: "<<bmp.dib.biCompression<<"\n";
std::cout<<"Size: "<<bmp.dib.biSizeImage<<"\n";
std::cout<<"X-res: "<<bmp.dib.biXPelsPerMeter<<"\n";
std::cout<<"Y-res: "<<bmp.dib.biYPelsPerMeter<<"\n";
std::cout<<"ClrUsed: "<<bmp.dib.biClrUsed<<"\n";
std::cout<<"ClrImportant: "<<bmp.dib.biClrImportant<<"\n";
std::ofstream file("C:/Users/Brandon/Desktop/Test.bmp", std::ios::out | std::ios::binary);
if (file)
{
file.write(reinterpret_cast<char*>(&bmp.header.type), sizeof(bmp.header.type));
file.write(reinterpret_cast<char*>(&bmp.header.bfSize), sizeof(bmp.header.bfSize));
file.write(reinterpret_cast<char*>(&bmp.header.reserved), sizeof(bmp.header.reserved));
file.write(reinterpret_cast<char*>(&bmp.header.offset), sizeof(bmp.header.offset));
file.write(reinterpret_cast<char*>(&bmp.dib.biSize), sizeof(bmp.dib.biSize));
file.write(reinterpret_cast<char*>(&bmp.dib.biWidth), sizeof(bmp.dib.biWidth));
file.write(reinterpret_cast<char*>(&bmp.dib.biHeight), sizeof(bmp.dib.biHeight));
file.write(reinterpret_cast<char*>(&bmp.dib.biPlanes), sizeof(bmp.dib.biPlanes));
file.write(reinterpret_cast<char*>(&bmp.dib.biBitCount), sizeof(bmp.dib.biBitCount));
file.write(reinterpret_cast<char*>(&bmp.dib.biCompression), sizeof(bmp.dib.biCompression));
file.write(reinterpret_cast<char*>(&bmp.dib.biSizeImage), sizeof(bmp.dib.biSizeImage));
file.write(reinterpret_cast<char*>(&bmp.dib.biXPelsPerMeter), sizeof(bmp.dib.biXPelsPerMeter));
file.write(reinterpret_cast<char*>(&bmp.dib.biYPelsPerMeter), sizeof(bmp.dib.biYPelsPerMeter));
file.write(reinterpret_cast<char*>(&bmp.dib.biClrUsed), sizeof(bmp.dib.biClrUsed));
file.write(reinterpret_cast<char*>(&bmp.dib.biClrImportant), sizeof(bmp.dib.biClrImportant));
file.write(reinterpret_cast<char*>(info + 1), bmp.dib.biSizeImage);
}
GlobalUnlock(dib);
}
}
CloseClipboard();
}
}
return 0;
}