NO

Author Topic: GDI+ - image format supported  (Read 9196 times)

henrin

  • Guest
GDI+ - image format supported
« on: February 08, 2015, 10:38:25 PM »
I was looking for a simple way to do simple things, that is to display an image when processing a WM_PAINT message.
Immediateley I found it was not simple. The best (or the less bad) solution I found is GDI+ and the contribution of John Findlay helped a lot.

I implemented an image load function directly fom a file or from a resource file (setion RCDATA) and made it as simple as possible (sgi.c is 151 lines and sgi.h is 13 lines - no zip needed).

I tested successfully JPG and PNG files.

For BMP, EMF and TIF, it works only after loading from a resource file, I really wonder why.
Some idea, do anybody have?

sgi.h
Code: [Select]
typedef void* GP_GPIMAGE ;
                                                            /*-------- RETURN VALUES -------*/

int SGIinit(void) ;                                         /* 0 if OK, <0 if error         */
void SGIexit(void) ;

GP_GPIMAGE SGIimageLoad(char *filename) ;                   /* image handle, <0 if error    */
void SGIimageUnload(GP_GPIMAGE image) ;

int SGIimageWidth(GP_GPIMAGE image) ;                       /* image's width, <0 if error   */
int SGIimageHeight(GP_GPIMAGE image) ;                      /* image's height, <0 if error  */

int SGIimageDraw(HDC hdc, RECT *rect, GP_GPIMAGE image) ;   /* 0 if OK, <0 if error         */

sgi.c
Code: [Select]
/*===================================================================================== sgi.c ==*/

    /* Minimum implementation of GdiPlus that allows the loading and rendering of images        */
    /* cf. Microsoft GDI+ Flat API; J.Findlay http://www.johnfindlay.plus.com/pellesc/GdiPlus   */

    /*    PNG and JPEG images can be loaded directly from a file or from a resource (RCDATA)    */
    /*    BMP and EMF images can be loaded only from a resource (RCDATA)                        */

#include <windows.h>
#include <math.h>
#include "sgi.h"


/*========================================================================== INIT & EXIT GDI+ ==*/

typedef struct
{
    UINT32 GdiplusVersion ;
    void* DebugEventCallback ;
    BOOL SuppressBackgroundThread ;
    BOOL SuppressExternalCodecs ;
} GDIPLUSSTARTUPINPUT ;

typedef int _stdcall (*NotificationHookProc)(ULONG_PTR *token);
typedef VOID _stdcall   (*NotificationUnhookProc)(ULONG_PTR token);

typedef struct
{
    NotificationHookProc NotificationHook ;
    NotificationUnhookProc NotificationUnhook ;
} GDIPLUSSTARTUPOUTPUT ;

int _stdcall GdiplusStartup(ULONG_PTR*, const GDIPLUSSTARTUPINPUT*, GDIPLUSSTARTUPOUTPUT*) ;
VOID _stdcall GdiplusShutdown(ULONG_PTR) ;

static ULONG_PTR gdiplusToken ;

/*----------------------------------------------------------------------------------------------*/
int SGIinit(void)
{
    GDIPLUSSTARTUPINPUT gdiplusStartupInput = { 1, NULL, FALSE, FALSE } ;      /* no option!    */

    int st = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    return - st ;                                   /* resturn value is < 0 in case of error    */
}

/*----------------------------------------------------------------------------------------------*/
void SGIexit(void)
{
    GdiplusShutdown(gdiplusToken) ;
}

/*============================================================================== PAINT IMAGES ==*/

    /* Minimum implementation of GdiPlus that allows the loading and rendering of image files   */
    /* cf. Microsoft GDI+ Flat API; J.Findlay http://www.johnfindlay.plus.com/pellesc/GdiPlus   */

    /*    PNG and JPEG images can be loaded directly from a file or from a resource (RCDATA)    */
    /*    BMP, EMF and TIFF images can be loaded only from a resource (RCDATA)                  */

#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")

#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")

#pragma comment(lib, "gdiplus.lib")

/*----------------------------------------------------------------------------- GDI+ flat API --*/

typedef void* GP_GPGRAPHICS ;

int _stdcall GdipLoadImageFromStreamICM(IStream* stream, GP_GPIMAGE *image);
int _stdcall GdipLoadImageFromFileICM(const wchar_t*, GP_GPIMAGE *image) ;
int _stdcall GdipCreateFromHDC(HDC, GP_GPGRAPHICS**) ;
int _stdcall GdipDrawImageRectI(GP_GPGRAPHICS, GP_GPIMAGE, INT, INT, INT, INT) ;
int _stdcall GdipGetImageWidth(GP_GPIMAGE, UINT*) ;
int _stdcall GdipGetImageHeight(GP_GPIMAGE, UINT*) ;
int _stdcall GdipDisposeImage(GP_GPIMAGE) ;
int _stdcall GdipDeleteGraphics(GP_GPGRAPHICS*) ;

/*----------------------------------------------------------------------- Load & unload image --*/
GP_GPIMAGE SGIimageLoad(char *fName)
/*
    fName is either the name of an image file (ie. "beach.png") or a resource name (ie. "#8009").
*/
{
    GP_GPIMAGE image = NULL ;
    int l = strlen(fName) ;

    if (fName[0] == '#')                                /* case resource ID                     */
    {
        HMODULE hModule = GetModuleHandle(NULL) ;
        HRSRC resrc = FindResource(hModule, fName, RT_RCDATA) ;
        int size = SizeofResource(hModule, resrc) ;
        LPVOID fByte = LockResource(LoadResource(hModule, resrc)) ;
        LPSTREAM lpstr = SHCreateMemStream(fByte, size) ;
        GdipLoadImageFromStreamICM(lpstr, &image) ;
    }
    else
    {
        wchar_t wname[2 * l + 4] ;                        /* convert fName to wide characters'  */
        if (mbstowcs(wname, fName, l) < 1)
            return NULL ;
        GdipLoadImageFromFileICM(wname, &image) ;
    }
    return image ;
}

void SGIimageUnload(GP_GPIMAGE image)
{
    GdipDisposeImage(image) ;
}

/*-------------------------------------------------------------------------------- Image Size --*/
int SGIimageWidth(GP_GPIMAGE image)
{
    UINT width = 0 ;
    int e = GdipGetImageWidth(image, &width) ;
    if (e) return - e ;                            /* If the function fails, it result is <0    */
    return width ;
}

int SGIimageHeight(GP_GPIMAGE image)
{
    UINT height = 0 ;
    int e = GdipGetImageHeight(image, &height) ;
    if (e) return - e ;
    return height ;
}

/*-------------------------------------------------------------------------------- Draw image --*/
int SGIimageDraw(HDC hdc, RECT *rect, GP_GPIMAGE image)
/*
    This function is typically called in the windows's message loop (case WM_PAINT).
    The image is aligned top - left in the rectangle.
*/
{
    int iw = SGIimageWidth(image) ;                                /* image size                */
    int ih = SGIimageHeight(image) ;
    if ((double) iw * ih == 0.0) return  - 99 ;                    /* one dimension is null     */
   
    GP_GPGRAPHICS *graphx ;
    int e = GdipCreateFromHDC(hdc, &graphx) ;
    if (e)
        return - 98 ;

    e = GdipDrawImageRectI(graphx, image, rect->left, rect->top, iw, ih) ;
    GdipDeleteGraphics(graphx) ;
    return - e ;
}

henrin

  • Guest
Closed: GDI+ - image format supported
« Reply #1 on: February 17, 2015, 03:22:02 PM »
While expanding to animated GIF, the problem disappear.
All formats that should work are really displayed!
Unless a subtil reason, this thread can be considered as closed.