【发布时间】:2019-12-09 11:54:24
【问题描述】:
我尝试使用问题here 的答案之一中的代码,当我在“paint”中打开位图文件后运行它时,选择其中的一部分并复制它,程序将复制的图像保存为需要,但是当我按 PrntScrn (并且屏幕截图出现在剪贴板中并在程序中标识为位图文件)时,程序将其保存为位图文件,但是当我尝试打开它时,我收到一条消息,指出不支持图像格式. 我想这是因为我保存图像的方式。 我的问题是两种类型的图像之间有什么区别,其中一种可以正常工作而另一种不能?
这是我的代码:
#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("Test2.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);
std::cout << "finished" << std::endl;
}
GlobalUnlock(dib);
}
}
CloseClipboard();
}
}
return 0;
}
【问题讨论】:
-
不同之处在于,一个程序比另一个程序保存的图像具有更少的协议违规(或不那么致命)。 BMP 文件格式比您想象的要复杂得多。你可以帮自己一个忙,而不是试图重新发明轮子。 Windows 附带一个位图编解码器作为WIC 的一部分。使用它,你会得到一个结构正确的文件。
标签: c++ windows winapi clipboard