2015-05-30 43 views
4

我在写一个非常小的C++程序来帮助我制作动画精灵。我希望它能够将数据从photoshop复制到剪贴板,在我的程序中对其进行处理,然后使用变换覆盖剪贴板。如何从Windows剪贴板中读取位图

虽然问题是我不确定如何从photoshop读取初始剪贴板。

我可以加载GetClipboardData(CF_DIB)的剪贴板,并得到一个有效的句柄,但我不知道如何使用该句柄。我试过使用SFML的Image::LoadFromMemory(handle, GlobalSize(handle)),它能够从内存中加载位图文件,但这似乎不起作用。

我需要真正解析整个格式吗?在这种情况下,我会考虑什么样的格式结构?可能有什么方法可以快速修改数据,使其看起来像位图文件?使用Windows API将其保存到文件可能更容易吗? (然后我可以用SFML加载那个文件来编辑,那样)

这对我来说只是一个快速而脏的工具,可以在photoshop中节省很多烦人的工作,所以效率或鲁棒性并不重要。

+2

格式[含有一个存储器对象BITMAPINFO结构后跟位图位](https://msdn.microsoft.com/en-us/library/windows/desktop/ff729168.aspx) –

回答

5

了解维基百科的位图结构,然后将其写入到一个文件,然后写出来的像素..

我和油漆测试下方的Windows 8.1。我打开与油漆的图像,然后压制Ctrl + C可复制到剪贴板..然后我跑了下面的代码,并将其复制在剪贴板图像到桌面:

#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; 
} 
+0

太棒了!有一个问题,为什么所有这些演员都需要? – Gigi

+1

@Gigi因为C++是强类型的,'fstream'只有“write(char *)”签名。所以你必须投所有其他类型才能写出它们。或者,你可以这样做:'file.write(reinterpret_cast (&bmp),sizeof(bmp))'如果它是紧凑的,而不是所有这些file.write的。 – Brandon

+0

难道你不能像这样使用重载的<< <<运算符吗? http://www.cppforschool.com/assignment/file-handling-sol/writing-number-to-text-file.html – Gigi