如何从C ++中的GDI +图像创建一个Base64编码的字符串? [英] How can I create a Base64-Encoded string from a GDI+ Image in C++?

查看:200
本文介绍了如何从C ++中的GDI +图像创建一个Base64编码的字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近问了一个问题, 如何在C ++中使用Base64编码的字符串在GDI +中创建一个图像? ,它得到一个响应,让我得到答案。

I asked a question recently, How can I create an Image in GDI+ from a Base64-Encoded string in C++?, which got a response that led me to the answer.

现在我需要做相反的事情 - 我有一个图像在GDI +的图像数据我需要变成一个Base64编码的字符串。由于其性质,它不直接。

Now I need to do the opposite - I have an Image in GDI+ whose image data I need to turn into a Base64-Encoded string. Due to its nature, it's not straightforward.

问题的症结是GDI +中的图像可以将其数据保存到文件或IStream *。我不想保存到一个文件,所以我需要使用结果流。问题是,这是我的知识分解。

The crux of the issue is that an Image in GDI+ can save out its data to either a file or an IStream*. I don't want to save to a file, so I need to use the resulting stream. Problem is, this is where my knowledge breaks down.

这个第一部分是我在另一个问题中想到的。

This first part is what I figured out in the other question

// Initialize GDI+.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

// I have this decode function from elsewhere
std::string decodedImage = base64_decode(Base64EncodedImage);

// Allocate the space for the stream
DWORD imageSize = decodedImage.length();
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);
LPVOID pImage = ::GlobalLock(hMem);    
memcpy(pImage, decodedImage.c_str(), imageSize);

// Create the stream
IStream* pStream = NULL;
::CreateStreamOnHGlobal(hMem, FALSE, &pStream);

// Create the image from the stream
Image image(pStream);

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

Base64 code

现在我要对结果图像执行一个操作,在这种情况下旋转它,现在我完成后需要Base64等效的字符串。

And now I'm going to perform an operation on the resulting image, in this case rotating it, and now I want the Base64-equivalent string when I'm done.

// Perform operation (rotate)
image.RotateFlip(Gdiplus::Rotate180FlipNone);

IStream* oStream = NULL;

CLSID tiffClsid;
GetEncoderClsid(L"image/tiff", &tiffClsid);  // Function defined elsewhere
image.Save(oStream, &tiffClsid);

// And here's where I'm stumped. 

GetEncoderClsid

所以我结束的是一个IStream *对象。但这里是我的知识和谷歌为我分崩离析。 IStream不应该是一个对象本身,它是一个接口的其他类型的流。我下去的路从反向的string-> Image,但我不知道如何确定流的大小,这似乎是该路由的关键。

So what I wind up with at the end is an IStream* object. But here's where both my knowledge and Google break down for me. IStream shouldn't be an object itself, it's an interface for other types of streams. I'd go down the road from getting string->Image in reverse, but I don't know how to determine the size of the stream, which appears to be key to that route.

如何从一个IStream *到一个字符串(我将然后Base64-Encode)?

How can I go from an IStream* to a string (which I will then Base64-Encode)? Or is there a much better way to go from a GDI+ Image to a string?

推荐答案

有了它

std::string RotateImage(const std::string &Base64EncodedImage)
{
    // Initialize GDI+.
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    std::string decodedImage = base64_decode(Base64EncodedImage);

    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);

    image.RotateFlip(Gdiplus::Rotate180FlipNone);

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

    IStream* oStream = NULL;
    CreateStreamOnHGlobal(NULL, TRUE, (LPSTREAM*)&oStream);

    CLSID tiffClsid;
    GetEncoderClsid(L"image/tiff", &tiffClsid);
    image.Save(oStream, &tiffClsid);

    ULARGE_INTEGER ulnSize;
    LARGE_INTEGER lnOffset;
    lnOffset.QuadPart = 0;
    oStream->Seek(lnOffset, STREAM_SEEK_END, &ulnSize);
    oStream->Seek(lnOffset, STREAM_SEEK_SET, NULL);

    char *pBuff = new char[(unsigned int)ulnSize.QuadPart];
    ULONG ulBytesRead;
    oStream->Read(pBuff, (ULONG)ulnSize.QuadPart, &ulBytesRead);

    std::string rotated_string = base64_encode((const unsigned char*)pBuff, ulnSize.QuadPart);

    return rotated_string;
}

这个诀窍的灵感来自于本文,是知道找出流的大小的方法,并让它读取它转换为字符数组。然后我可以将该数组提供给 base64_encode 函数和voilà。

The trick, as inspired by what I got from this article, is knowing the method to finding out the size of the stream, and having it read it into a character array. Then I can feed that array to the base64_encode function and voilà.

这篇关于如何从C ++中的GDI +图像创建一个Base64编码的字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆