5

I've this piece of code working on Windows 7 64-bit: it allows me to transform a representation of an Image contained into a std::string (Base64EncodedImage) to a GdiPlus::Bitmap:

HRESULT hr; 
using namespace Gdiplus;
std::string decodedImage = Base64EncodedImage;
DWORD imageSize = decodedImage.length();

HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);
if (!hMem)
    ErrorExit(TEXT("GlobalAlloc")); //http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx

LPVOID pImage = ::GlobalLock(hMem);
if (!pImage)
    ErrorExit(TEXT("GlobalLock"));

CopyMemory(pImage, decodedImage.c_str(), imageSize);
IStream* pStream = NULL;

BitmapData* bitmapData = new BitmapData;
if (::CreateStreamOnHGlobal(hMem, FALSE, &pStream) != S_OK)
    ErrorExit(TEXT("CreateStreamOnHGlobal"));
else
{
    bitmap = Bitmap::FromStream(pStream);   //FAILS on WIN32
    if (!bitmap)
        ErrorExit(TEXT("FromStream"));

    RECT clientRect;
    GetClientRect(hwnd, &clientRect);

    bitmapClone = bitmap->Clone(0, 0, clientRect.right, clientRect.bottom, PixelFormatDontCare);
    delete bitmap;
    bitmap = NULL;    
}

But it fails on Windows 7 32-bit, specifically on this line:

bitmap = Bitmap::FromStream(pStream);

It always returns NULL, but I can't get how is this working on x64 but not in x86. If someone can enlighten me, I'll be grateful.

Thanks!

  • Not an expert, but shouldn't you `GlobalUnlock` the memory before passing it to `CreateStreamonHGlobal`? [MSDN](http://msdn.microsoft.com/en-us/library/windows/desktop/aa378980\(v=vs.85\).aspx) says "Avoid calling the object’s methods while you have the memory handle locked with GlobalLock. This can cause method calls to fail unpredictably.". – user786653 Feb 06 '12 at 18:12
  • As far as I know, I should Lock/CreateStreamOnHGlobal/Unlock; I will try doing what you said. – Maximiliano Santa Cruz Feb 06 '12 at 18:34
  • possible duplicate http://stackoverflow.com/questions/2746855/how-can-i-create-an-image-in-gdi-from-a-base64-encoded-string-in-c – Sergey Vyacheslavovich Brunov Feb 06 '12 at 18:44
  • Yes but the problem is not how to create the image (solved... sort of), but, how does it work on 64bit but not in 32 bit. – Maximiliano Santa Cruz Feb 06 '12 at 19:15

1 Answers1

12

The code you've provided works well for me.

But when I've commented the GDI+ initialization, the Bitmap::FromStream(pStream) method always returns NULL pointer.

Do you have the GDI+ initialization?

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

By the way, the GDI+ uninitialization:

GdiplusShutdown(gdiplusToken);
  • Yes, it has been initialized. The code remains the same for win32 and win64. Adding more context to the question, this has been made using Firebreath (http://www.firebreath.org); and using MS Visual C++ on a 64bit machine targeting 32bit build. – Maximiliano Santa Cruz Feb 06 '12 at 19:14
  • Could you please check the last error (call `GetLastError()` after `Bitmap::FromStream`)? – Sergey Vyacheslavovich Brunov Feb 06 '12 at 20:03
  • [Just for your information](http://www.codeproject.com/Messages/787169/Re-Bitmap-FromStream-returns-NULL-solution.aspx). Also, which status the `GdiplusStartup` function returns in your case? – Sergey Vyacheslavovich Brunov Feb 06 '12 at 20:11
  • 1
    It works now, in my initialization code I had the SuppressBackgroundThread = true; removing that line made the trick! – Maximiliano Santa Cruz Feb 06 '12 at 20:12
  • 2
    Awesome answer, could've search for a possible bug for days if not for this simple answer ! GDI was initialized after this, so I was always receiving null, don't think would be able to find this little bugger on my own :) – Silencer Oct 23 '15 at 07:54