User Tools

Site Tools


Loading a GIF or JPEG image

by Richard Russell, September 2008

The main Help documentation describes how to display a GIF or JPEG image on the main output window, but you may wish to perform other operations on an image such as accessing its data or displaying it in a static control. In such cases you are likely to need a handle to the image.

The function below operates in a similar way to SYS “LoadImage” except that it works with JPEG, GIF, BMP, ICO, EMF or WMF images. You can alternatively use the function FNloadimagegdip2 listed at Loading a PNG or TIFF image because that will load GIF and JPEG images too, and gives better results when the image is very large or needs to be scaled.

        DEF FNloadimage(file$, RETURN cx%, RETURN cy%, par%)
        LOCAL iid{}, bmp{}, ix%, iy%, hbm%, hcopy%, pic%, ole%, olpp%, text%
        DIM iid{a%,b%,c%,d%}, text% LOCAL 513
        iid.a% = &7BF80980 : REM. 128-bit iid
        iid.b% = &101ABF32
        iid.c% = &AA00BB8B
        iid.d% = &AB0C3000
        SYS "MultiByteToWideChar", 0, 0, file$, -1, text%, 256
        SYS "LoadLibrary", "OLEAUT32.DLL" TO ole%
        SYS "GetProcAddress", ole%, "OleLoadPicturePath" TO olpp%
        IF olpp%=0 THEN = 0
        SYS olpp%, text%, 0, 0, 0, iid{}, ^pic% : REM. OleLoadPicturePath
        IF pic%=0 THEN = 0
        SYS !(!pic%+12), pic%, ^hbm% : REM. IPicture::get_Handle
        IF hbm%=0 THEN = 0
        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%
        SYS "CopyImage", hbm%, 0, cx%, cy%, 0 TO hcopy%
        SYS "DeleteObject", hbm%
        SYS !(!pic%+8), pic% : REM. IPicture::Release
        = hcopy%

The parameters to the function are the filename (or URL) 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. Note that a filename must contain the drive name (e.g. C:) to distinguish it from an internet URL. 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% = FNloadimage(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 FNloadimage(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 FNloadimage function to display an image in a static control see this article.

To access the data of the image you can use the SYS “GetDIBits” API as follows:

        cx% = 0
        cy% = 0
        himage% = FNloadimage(filename$, cx%, cy%, FALSE)
        DIM bmih{biSize%, biWidth%, biHeight%, biPlanes{l&,h&}, \
        \ biBitCount{l&,h&}, biCompression%, biSizeImage%, \
        \ biXPelsPerMeter%, biYPelsPerMeter%, biClrUsed%, \
        \ biClrImportant%}
        bmih.biSize% = DIM(bmih{})
        bmih.biWidth% = cx%
        bmih.biHeight% = -cy%
        bmih.biPlanes.l& = 1
        bmih.biBitCount.l& = 24
        bmih.biCompression% = 0
        bmih.biSizeImage% = ((cx%*(bmih.biBitCount.l& DIV 8) + 3) AND -4) * cy%
        DIM imagedata% bmih.biSizeImage%-1
        SYS "GetDIBits", @memhdc%, himage%, 0, cy%, imagedata%, bmih{}, 0 TO num%
        SYS "DeleteObject", himage%
        IF num% <> cy% ERROR 100, "GetDIBits failed"

This provides the image data in 'top-down' format as RGB triplets stored at imagedata%; if you require a different data format modify the members of the bmih structure accordingly. Note that each line of image data is always padded (if necessary) to a multiple of four bytes.

If the image data may be too large to be stored on the heap (possibly with HIMEM increased) then you can instead allocate the memory using the Windows API:

        SYS "GlobalAlloc", &40, bmih.biSizeImage% TO imagedata%
        IF imagedata% = 0 ERROR 100, "Insufficient memory"

but in this case don't forget to free the memory later.

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_20gif_20or_20jpeg_20image.txt · Last modified: 2018/04/13 16:45 by richardrussell