在 C++ (win32) 中将位图转换为内存中的 PNG

问题描述 投票:0回答:8

我可以仅使用 Platform SDK 将位图转换为内存中的 PNG(即不写入文件)吗? (即没有 libpng 等)。

我还希望能够为该图像定义透明颜色(不是 Alpha 通道)。

GdiPlus 解决方案似乎仅限于宽度可被 4 整除的图像。在调用 Save() 期间,任何其他操作都会失败。有谁知道这个限制的原因以及我如何/是否可以解决它?

更新

我实现了 GDI+ 解决方案,但正如我所说,它仅限于四边形宽度的图像。我正在寻求在不改变图像尺寸的情况下解决这个宽度问题,或者寻找可行的替代非 GDI+ 解决方案。

c++ winapi png
8个回答
21
投票

LodePNG (GitHub) 是一个无库 PNG 编码器/解码器。


14
投票

我使用 libpng 读取和写入 PNG,它似乎可以处理我扔给它的所有内容(我在单元测试中使用了它,比如 257x255 图像,它们不会造成任何麻烦)。 我相信 API 足够灵活,不会与文件 I/O 绑定(或者至少您可以覆盖其默认行为,例如参见

png_set_write_fn
中的 定制部分)

在实践中,我总是通过更干净的 boost::gil PNG IO 扩展 使用它,但不幸的是,这需要

char*
文件名,如果你深入研究它的实现中的
png_writer
file_mgr
类看起来与
FILE*
非常相关(尽管如果你使用的是 Linux,使用 fmemopen 和内存缓冲区的版本可能很容易就可以完成)。


12
投票

在此站点上,代码显示了如何将位图转换为 PNG 并将其写入文件:http://dotnet-snippets.de/dns/gdi-speichern-eines-png-SID814.aspx。 Bitmap 的

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 中运行。我从来没有用它做过什么,只是用谷歌搜索了一下。不过,看起来你可以使用它。


8
投票

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。


6
投票

我使用 GDI+ 将位图作为 PNG 保存到文件中。 您可能应该查看有关 GDI+ 的 MSDN 信息here,特别是这个函数GdipSaveImageToStream

本教程这里可能也会提供一些帮助。


5
投票

GDI(老派,非加)有一个

GetDIBits
方法,可以要求使用 PNG 压缩输出位(
BITMAPINFOHEADER::biCompression
==
BI_PNG
)。我想知道这是否可以用来创建 PNG 文件?使用
GetDIBits
编写标准位图文件已经足够复杂了 - 所以我怀疑这会更加困难。


3
投票

如果您只想使用 Windows API,WIC 是实现此目的的方法,它支持位图和 PNG。


2
投票

使用库可能比自己重新发明轮子更好。

查看freeImage

© www.soinside.com 2019 - 2024. All rights reserved.