我是否可以仅使用Platform SDK将位图转换为内存中的PNG(即无需写入文件)? (即没有libpng等)。
我还希望能够为此图像定义透明色(不是Alpha通道)。
GdiPlus解决方案似乎仅限于宽度可被4整理的图像。在调用Save()期间,其他任何操作都失败了。有谁知道这个限制的原因以及我是否可以解决这个问题?
更新:赏金
我正在开始赏金(我真的希望这个工作)。我实现了GDI +解决方案,但正如我所说,它仅限于四边形图像。赏金将发送给任何可以解决此宽度问题的人(不改变图像尺寸),或者可以提供可行的替代非GDI +解决方案。
答案 0 :(得分:17)
答案 1 :(得分:15)
我使用libpng读取和写入PNG,它似乎处理了我抛出的东西(我在单元测试中用它来处理像257x255图像这样的东西并没有造成麻烦)。我相信API足够灵活,不会与文件I / O绑定(或者至少可以覆盖其默认行为,例如,请参阅customization部分中的png_set_write_fn
)
在实践中,我总是通过更干净的boost::gil PNG IO extension使用它,但不幸的是,它会带有char*
个文件名,如果你深入了解png_writer
和{{1它的实现中的类似乎与file_mgr
非常相关(尽管如果你在Linux上,使用fmemopen和内存缓冲区的版本很可能很容易编译)。
答案 2 :(得分:11)
在此网站上,代码显示了如何将位图转换为PNG,将其写入文件:http://dotnet-snippets.de/dns/gdi-speichern-eines-png-SID814.aspx。位图的Save
方法也支持写入IStream
(http://msdn.microsoft.com/en-us/library/ms535406%28VS.85%29.aspx),而不是写入文件。您可以使用CreateStreamOnHGlobal
API函数创建由内存备份的Stream。 (http://msdn.microsoft.com/en-us/library/aa378980%28VS.85%29.aspx)。使用过的库GDI +从WindowsXP包含在Windows中,在Windows98中可以在Windows中运行。我从未用它做过什么,只是用Google搜索。看起来你可以使用它。
答案 3 :(得分:7)
CImage类(ATL / MFC)支持保存为PNG格式。与GDI +解决方案一样,它也支持保存到流。这是我用来将它保存到CByteArray的一些代码:
CByteArray baPicture;
IStream *pStream = NULL;
if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) == S_OK)
{
if (image.Save(pStream, Gdiplus::ImageFormatPNG) == S_OK)
{
ULARGE_INTEGER ulnSize;
LARGE_INTEGER lnOffset;
lnOffset.QuadPart = 0;
if (pStream->Seek(lnOffset, STREAM_SEEK_END, &ulnSize) == S_OK)
{
if (pStream->Seek(lnOffset, STREAM_SEEK_SET, NULL) == S_OK)
{
baPicture.SetSize(ulnSize.QuadPart);
ULONG ulBytesRead;
pStream->Read(baPicture.GetData(), ulnSize.QuadPart, &ulBytesRead);
}
}
}
}
pStream->Release();
我不知道你是否想要使用ATL或MFC。
答案 4 :(得分:5)
我使用GDI +将位图作为PNG保存到文件中。您应该查看有关GDI + here的MSDN信息,特别是此函数GdipSaveImageToStream。
本教程here也可能会提供一些帮助。
答案 5 :(得分:3)
GDI(旧学校,非加)有GetDIBits
方法可以要求使用PNG压缩输出位(BITMAPINFOHEADER::biCompression
== BI_PNG
)。我想知道这是否可用于创建PNG文件?使用GetDIBits
编写标准位图文件非常复杂 - 所以我怀疑这会更加困难。
答案 6 :(得分:3)
如果您只想使用Windows API,WIC是实现此目的的方法,它同时支持位图和PNG。
答案 7 :(得分:2)
使用库而不是自己重新发明轮子可能会更好。