How can I create a Base64 encoded string from a GDI + image in C ++?

I recently asked a question, How to create an image in GDI + from Base64 encoding in C ++? that got the answer that led me to the answer.

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. By nature, it is not easy.

The essence of the problem is that the image in GDI + can save its data either to a file or to IStream *. I do not want to save the file, so I need to use the resulting stream. The problem is that my knowledge is breaking.

This first part is what I found out in another 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 )

And now I'm going to perform an operation on the resulting image, in this case, turning it, and now I want the Base64 equivalent string to be ready.

 // 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 where I'm stumped. 

( GetEncoderClsid )

So I end at the end, this is an IStream * object. But here, where both my knowledge and Google break down for me. IStream does not have to be the object itself, it is an interface for other types of streams. I took the road from getting the line -> Image in reverse order, but I don’t know how to determine the size of the stream, which, apparently, is the key for this route.

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

+1
source share
1 answer

Got it

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

The trick, inspired by what I got from in this article , knows a method for determining the size of a stream and forcing it to read it into an array of characters. Then I can pass this array to base64_encode and voilà.

+1
source

Source: https://habr.com/ru/post/1308495/


All Articles