Search code examples
c++windowsgdi+gdi

How to use GDI+ library to decode a jpeg in memory?


GDI+ provides a Image class, and you can use this class to read a image file with one format and then save this file to another format. But if I want to just decode a jpeg file (already loaded into memory), how can I do it?


Solution

  • You can use SHCreateMemStream and Gdiplus::Image::FromStream

    #include <Window.h>
    #include <Gdiplus.h>
    #include <Shlwapi.h>
    #include <atlbase.h>
    ...
    CComPtr<IStream> stream;
    stream.Attach(SHCreateMemStream(buf, bufsize));
    Gdiplus::Image *image = Gdiplus::Image::FromStream(stream);
    

    Where buf contains jpeg data (or any other compatible image format) and bufsize is the length of that data.

    SHCreateMemStream needs "Shlwapi.lib" library.

    Example:

    void foo(HDC hdc)
    {
        //Read jpeg from input file in to buf:
        HANDLE hfile = CreateFile(L"test.jpg", 
            GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (!hfile) return;
    
        DWORD bufsize = GetFileSize(hfile, NULL);
        BYTE *buf = new BYTE[bufsize];
    
        DWORD temp;
        ReadFile(hfile, buf, bufsize, &temp, 0);
    
        //convert buf to IStream    
        CComPtr<IStream> stream;
        stream.Attach(SHCreateMemStream(buf, bufsize));
    
        //Read from IStream    
        Gdiplus::Bitmap *image = Gdiplus::Bitmap::FromStream(stream);
        if (image)
        {
            Gdiplus::Graphics g(hdc);
            g.DrawImage(image, 0, 0);
            delete image;
        }
    
        delete[]buf;
        CloseHandle(hfile);
    }
    

    Edit: easier method as mentioned in comments:

    IStream* stream = SHCreateMemStream(buf, bufsize);
    Gdiplus::Image *image = Gdiplus::Image::FromStream(stream);
    ...
    stream->Release();