如何从 C++ 中的 Base64 编码字符串在 GDI+ 中创建图像?

Posted

技术标签:

【中文标题】如何从 C++ 中的 Base64 编码字符串在 GDI+ 中创建图像?【英文标题】:How can I create an Image in GDI+ from a Base64-Encoded string in C++? 【发布时间】:2010-04-30 18:42:52 【问题描述】:

我有一个应用程序,目前是用 C# 编写的,它可以采用 Base64 编码的字符串并将其转换为图像(在本例中为 TIFF 图像),反之亦然。在 C# 中,这实际上非常简单。

    private byte[] ImageToByteArray(Image img)
    
        MemoryStream ms = new MemoryStream();
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
        return ms.ToArray();
    

    private Image byteArrayToImage(byte[] byteArrayIn)
    
        MemoryStream ms = new MemoryStream(byteArrayIn);
        BinaryWriter bw = new BinaryWriter(ms);
        bw.Write(byteArrayIn);
        Image returnImage = Image.FromStream(ms, true, false);
        return returnImage;
    

    // Convert Image into string
    byte[] imagebytes = ImageToByteArray(anImage);
    string Base64EncodedStringImage = Convert.ToBase64String(imagebytes);

    // Convert string into Image
    byte[] imagebytes = Convert.FromBase64String(Base64EncodedStringImage);
    Image anImage = byteArrayToImage(imagebytes);

(而且,现在我正在研究它,可以进一步简化)

我现在有业务需要在 C++ 中执行此操作。我正在使用 GDI+ 来绘制图形(目前仅适用于 Windows),并且我已经拥有 decode C++ 中的字符串(到另一个字符串)的代码。然而,我遇到的问题是将信息放入 GDI+ 中的 Image 对象中。

在这一点上,我认为我需要任何一个

a) 一种将 Base64 解码字符串转换为 IStream 以提供给 Image 对象的 FromStream 函数的方法

b) 一种将 Base64 编码的字符串转换为 IStream 以提供给 Image 对象的 FromStream 函数的方法(因此,与我当前使用的代码不同)

c) 一些完全不同的方式我在这里没有想到。

我的 C++ 技能非常生疏了,而且我也被托管的 .NET 平台宠坏了,所以如果我攻击这一切都是错误的,我愿意接受建议。

更新:除了我在下面发布的解决方案之外,我还想出了如何go the other way 如果有人需要它。

【问题讨论】:

为什么不在 Reflector 中打开它,看看 .NET 是如何做到的? 如果不详细查看它们,来自 Boost.Serialization 的数据流迭代器可能对 (base64 -> binary) 有帮助 ...boost.org/doc/libs/1_42_0/libs/serialization/doc/dataflow.html 好吧,继续使用 Google 搜索您的问题的答案并看到 #1 或 #2 结果是您刚刚提出的问题,这有点奇怪。 【参考方案1】:

好的,使用我链接的 Base64 解码器和 Ben Straub 链接的示例中的信息,我得到了它的工作

using namespace Gdiplus; // Using GDI+

Graphics graphics(hdc); // Get this however you get this

std::string encodedImage = "<Your Base64 Encoded String goes here>";

std::string decodedImage = base64_decode(encodedImage); // using the base64 
                                                        // library I linked

DWORD imageSize = decodedImage.length();
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);
LPVOID pImage = ::GlobalLock(hMem);
memcpy(pImage, decodedImage.c_str(), imageSize);

IStream* pStream = NULL;
::CreateStreamOnHGlobal(hMem, FALSE, &pStream);

Image image(pStream);

graphics.DrawImage(&image, destRect);

pStream->Release();
GlobalUnlock(hMem);
GlobalFree(hMem);

我确信它可以大大改进,但它确实有效。

【讨论】:

【参考方案2】:

这应该是一个两步的过程。首先,将 base64 解码为纯二进制(如果您从文件中加载 TIFF,您将拥有的位)。这个first Google result 看起来不错。

其次,您需要将这些位转换为位图对象。当我不得不从资源表中加载图像时,我关注了this example。

【讨论】:

好的,这基本上就是答案。当我在谷歌搜索时,我一直在这些页面上运行,但由于我正在处理字符串或字节数组,我不知道如何合并这两个概念(第二篇文章正在从表中寻找资源)。我刚刚想通了,我会在星期一发布代码/答案。 在下面查看我的答案 - 我就是这样做的,但我想我会给别人代表回答它:)

以上是关于如何从 C++ 中的 Base64 编码字符串在 GDI+ 中创建图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 base64 编码的字符串构造 java.security.PublicKey 对象?

如何使用 PHP 从 base64 编码的数据/字符串创建图像并将其保存到网站文件夹

从 Base64 编码的字符串中检索 MIME 类型

如何在 JavaScript 中使用字节数组将字符串转换为 base64 编码?

如何在 ios 中将 Base64 编码的 NSString 转换为字节数组(Java)?

如何从 base64 编码字符串创建 Java Key 对象,以便使用 JJWT 进行 PS256 解析