User Tools

Site Tools


loading_20a_20png_20or_20tiff_20image

Loading a PNG or TIFF image

by Richard Russell, October 2008, revised November 2010 and January 2012

The article Loading a GIF or JPEG image lists a replacement for the LoadImage API which works for JPEG, GIF, ICO, EMF and WMF images as well as for BMP images. However two common still-image formats not supported by that function are PNG and TIFF.

The two functions listed below each load PNG and TIFF images in addition to the others (since there's a large variety of different TIFF formats it may load only the more common variants). They require GDI+ to be installed on the target PC.

Method 1


This version is the simpler of the two, but can't cope with very large images and, when scaling is required, the quality is not as good as it might be:

        DEF FNloadimagegdip(file$, RETURN cx%, RETURN cy%, par%)
        LOCAL tSI{}, bmp{}, ix%, iy%, hbm%, bmp%, hcopy%, gdip%, text%, res%, lGDIP%
        DIM text% LOCAL 513
 
        SYS "MultiByteToWideChar", 0, 0, file$, -1, text%, 256
 
        SYS "LoadLibrary", "GDIPLUS.DLL" TO gdip%
        IF gdip% = 0 ERROR 100, "Couldn't load GDIPLUS.DLL"
        SYS "GetProcAddress", gdip%, "GdiplusStartup" TO `GdiplusStartup`
        SYS "GetProcAddress", gdip%, "GdipCreateBitmapFromFile" TO `GdipCreateBitmapFromFile`
        SYS "GetProcAddress", gdip%, "GdipCreateHBITMAPFromBitmap" TO `GdipCreateHBITMAPFromBitmap`
        SYS "GetProcAddress", gdip%, "GdipDisposeImage" TO `GdipDisposeImage`
        SYS "GetProcAddress", gdip%, "GdiplusShutdown" TO `GdiplusShutdown`
 
        DIM tSI{GdiplusVersion%, DebugEventCallback%, \
        \       SuppressBackgroundThread%, SuppressExternalCodecs%}
        tSI.GdiplusVersion% = 1
 
        SYS `GdiplusStartup`, ^lGDIP%, tSI{}, 0
        SYS `GdipCreateBitmapFromFile`, text%, ^bmp% TO res%
        IF res% THEN
          SYS `GdiplusShutdown`, lGDIP%
          SYS "FreeLibrary", gdip%
          =0
        ENDIF
        SYS `GdipCreateHBITMAPFromBitmap`, bmp%, ^hbm% TO res%
        IF res% THEN
          SYS `GdipDisposeImage`, bmp%
          SYS `GdiplusShutdown`, lGDIP%
          SYS "FreeLibrary", gdip%
          =0
        ENDIF
 
        DIM bmp{bmType%,bmWidth%,bmHeight%,bmWidthBytes%,bmPlanes{l&,h&}, \
        \       bmBitsPixel{l&,h&}, bmBits%}
        SYS "GetObject", hbm%, DIM(bmp{}), bmp{}
 
        ix% = bmp.bmWidth%
        iy% = bmp.bmHeight%
 
        IF cx%=0 cx% = ix%
        IF cy%=0 cy% = iy%
 
        IF par% THEN
          IF cx%/cy%>ix%/iy% cx% = cy%*ix%/iy% ELSE cy% = cx%*iy%/ix%
        ENDIF
 
        SYS "CopyImage", hbm%, 0, cx%, cy%, 0 TO hcopy%
        SYS "DeleteObject", hbm%
        SYS `GdipDisposeImage`, bmp%
        SYS `GdiplusShutdown`, lGDIP%
        SYS "FreeLibrary", gdip%
 
        = hcopy%

Method 2


This version is a little more complicated, but can cope with very large images (potentially greater than 10000 x 10000 pixels) and scales the image, when required, with a higher quality:

        DEF FNloadimagegdip2(file$, RETURN cx%, RETURN cy%, par%)
        LOCAL tSI{}, bmi{}, text%, gdip%, image%, ix%, iy%, lGDIP%
        LOCAL hdc%, hdib%, old%, gfx%, bits%
        DIM text% LOCAL 513
 
        SYS "MultiByteToWideChar", 0, 0, file$, -1, text%, 256
 
        SYS "LoadLibrary", "GDIPLUS.DLL" TO gdip%
        IF gdip% = 0 ERROR 100, "Couldn't load GDIPLUS.DLL"
        SYS "GetProcAddress", gdip%, "GdiplusStartup" TO `GdiplusStartup`
        SYS "GetProcAddress", gdip%, "GdipLoadImageFromFile" TO `GdipLoadImageFromFile`
        SYS "GetProcAddress", gdip%, "GdipDrawImageRectRectI" TO `GdipDrawImageRectRectI`
        SYS "GetProcAddress", gdip%, "GdipGetImageHeight" TO `GdipGetImageHeight`
        SYS "GetProcAddress", gdip%, "GdipGetImageWidth" TO `GdipGetImageWidth`
        SYS "GetProcAddress", gdip%, "GdipCreateFromHDC" TO `GdipCreateFromHDC`
        SYS "GetProcAddress", gdip%, "GdipSetSmoothingMode" TO `GdipSetSmoothingMode`
        SYS "GetProcAddress", gdip%, "GdipDeleteGraphics" TO `GdipDeleteGraphics`
        SYS "GetProcAddress", gdip%, "GdipDisposeImage" TO `GdipDisposeImage`
        SYS "GetProcAddress", gdip%, "GdiplusShutdown" TO `GdiplusShutdown`
 
        DIM tSI{GdiplusVersion%, DebugEventCallback%, \
        \       SuppressBackgroundThread%, SuppressExternalCodecs%}
        DIM bmi{biSize%, biWidth%, biHeight%, biPlanes{l&,h&}, biBitCount{l&,h&}, \
        \       biCompression%, biSizeImage%, biXPelsPerMeter%, biYPelsPerMeter%, \
        \       biClrUsed%, biClrImportant%}
        tSI.GdiplusVersion% = 1
 
        SYS `GdiplusStartup`, ^lGDIP%, tSI{}, 0
        SYS `GdipLoadImageFromFile`, text%, ^image%
        IF image% = 0 THEN
          SYS `GdiplusShutdown`, lGDIP%
          SYS "FreeLibrary", gdip%
          =0
        ENDIF
 
        SYS `GdipGetImageWidth`, image%, ^ix%
        SYS `GdipGetImageHeight`, image%, ^iy%
        IF cx% = 0 THEN cx% = ix%
        IF cy% = 0 THEN cy% = iy%
        IF par% THEN
          IF cx%/cy%>ix%/iy% cx% = cy%*ix%/iy% ELSE cy% = cx%*iy%/ix%
        ENDIF
 
        bmi.biSize% = DIM(bmi{})
        bmi.biWidth% = cx%
        bmi.biHeight% = -cy%
        bmi.biPlanes.l& = 1
        bmi.biBitCount.l& = 24
 
        SYS "CreateCompatibleDC", 0 TO hdc%
        IF hdc% = 0 ERROR 92, "CreateCompatibleDC failed"
        SYS "CreateDIBSection", hdc%, bmi{}, 0, ^bits%, 0, 0 TO hdib%
        IF hdib%=0 ERROR 91, "CreateDIBSection failed"
        SYS "SelectObject", hdc%, hdib% TO old%
        SYS "PatBlt", hdc%, 0, 0, cx%, cy%, &FF0062 : REM WHITENESS
 
        SYS `GdipCreateFromHDC`, hdc%, ^gfx%
        IF gfx%=0 ERROR 90, "GdipCreateFromHDC failed"
        SYS `GdipSetSmoothingMode`, gfx%, 2
        SYS `GdipDrawImageRectRectI`,gfx%,image%,0,0,cx%,cy%,0,0,ix%,iy%,2,0,0,0
 
        SYS "SelectObject", hdc%, old%
        SYS "DeleteDC", hdc%
        SYS `GdipDeleteGraphics`, gfx%
        SYS `GdipDisposeImage`, image%
        SYS `GdiplusShutdown`, lGDIP%
        SYS "FreeLibrary", gdip%
        = hdib%

How to use


The parameters to the functions are the filename of the image, the required width and height (in pixels) and a flag to indicate whether you want the aspect ratio to be preserved or not. The returned value is a handle to the image, or zero if the image cannot be found or opened.

If the required width and/or height values are supplied as zero then the actual width and/or height of the original image are used. Thus if a non-zero value is supplied for the width and zero is supplied for the height, the image will be scaled horizontally (if required) but not vertically; however if the preserve aspect ratio flag is set to TRUE, the then image will be scaled vertically to preserve the correct shape.

The actual dimensions of the (possibly scaled) image are returned in the second and third parameters, therefore they must be supplied as variables rather than as constants. Thus if you don't want to scale the image call the function as follows

        cx% = 0
        cy% = 0
        himage% = FNloadimagegdip2(filename$, cx%, cy%, FALSE)

Alternatively if you are not interested in knowing the actual dimensions you can modify the function definition by removing the RETURN qualifiers:

        DEF FNloadimagegdip2(file$, cx%, cy%, par%)

With this modification you can supply constant values (e.g. 0) as parameters.

When you have completely finished with the image you should delete the handle as follows:

        SYS "DeleteObject", himage%

To use the FNloadimagegdip function to display an image in a static control see this article.

To access the data of the image it is better to use Method 2 (in which the bitmap is stored in a DIB Section). The local variable bits% points to the bitmap data, so that could either be changed to a global or returned from the function as another RETURN parameter. The data is in 'top-down' format as RGB triplets, although a different format could be used by modifying the contents of the bmi{} structure.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
loading_20a_20png_20or_20tiff_20image.txt · Last modified: 2024/01/05 00:22 by 127.0.0.1