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

7
我有一个应用程序,目前是用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),我已经有了将字符串解码为另一个字符串的代码。 然而,我遇到的问题是如何将信息传递给GDI+中的Image对象。
此时,我认为我需要:
a)一种将Base64解码后的字符串转换为IStream以提供给Image对象的FromStream函数的方法
b)一种将Base64编码的字符串转换为IStream以提供给Image对象的FromStream函数的方法(因此,与我当前使用的代码不同)
c)我没有考虑到的完全不同的方式。
我的C ++技能非常生疏,而且我也被托管的.NET平台宠坏了,所以如果我攻击这一切的方法都是错的,我愿意听取建议。

更新:除了我下面发布的解决方案外,我还找到了一种相反的方法,如果有人需要的话。


为什么不在Reflector中打开它,看看.NET是如何实现它的呢? - Billy ONeal
不详细查看的话,Boost.Serialization中的数据流迭代器可能对*(base64 -> binary)*有所帮助... http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/dataflow.html - Georg Fritzsche
好的,如果你遇到问题还要继续使用谷歌搜索答案,然后看到排名第一或第二的结果是你刚刚在 SO 上发出的问题,那么这种情况确实有点奇怪。 - Tom Kidd
2个回答

10

好的,使用我提供的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);

我相信它可以得到极大的改进,但它能够工作。


5

这应该是一个两步过程。首先,将base64解码为纯二进制(如果您从文件加载了TIFF,则会得到的位)。对此,第一个谷歌结果看起来非常不错。

其次,您需要将这些位转换为位图对象。当我不得不从资源表中加载图像时,我遵循了这个例子


好的,基本上这就是答案。每当我谷歌一些东西时,总会遇到这些页面,但由于我正在处理字符串或字节数组,我不知道如何合并这两个概念(第二篇文章正在寻找来自表格的资源)。我刚刚弄清楚了如何做,并将在周一发布代码/答案。 - Tom Kidd
看我的回答 - 这就是我做的,但我想我会让别人回答并获得声望 :) - Tom Kidd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接