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

时间:2010-05-13 22:01:53

标签: c++ string image gdi+ base64

我最近问了一个问题 How can I create an Image in GDI+ from a Base64-Encoded string in C++? ,得到了一个回复,让我得到答案。

现在我需要做相反的事情 - 我在GDI +中有一个Image,我的图像数据需要变成Base64-Encoded字符串。由于它的性质,它并不简单。

问题的关键在于GDI +中的图像可以将其数据保存到文件或IStream *中。我不想保存到文件,所以我需要使用生成的流。问题是,这是我的知识崩溃的地方。

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

// 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等效的字符串。

// 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开始,但我不知道如何确定流的大小,这似乎是该路由的关键。

如何从IStream *转到字符串(我将使用Base64-Encode)?或者有更好的方法从GDI +图像转换为字符串?

1 个答案:

答案 0 :(得分:0)

搞定了

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

这个技巧受到我从this article得到的启发,就是知道找出流大小的方法,并将其读入字符数组。然后我可以将该数组提供给base64_encode函数和voilà。