2015-05-30 112 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