Older Version Newer Version

Alyce Alyce Jan 3, 2014

==Getting Image File Information with GDI32==

While it is possible to [[GraphicDimensions|open and read any image file as a sequential file to find the image width and height]], it may be easier to use the GDI32 {{GetObjectA}}.  {{GetObjectA}} retrieves information for all bitmaps in memory.  [[GDIPlusLoadAnyImage|Load the image first with GDIPlus]] with a call to {{GdipCreateBitmapFromFile}}.  Once the image is loaded, call {{GetObjectA}} to retrieve information.  This code is based in part upon Alyce Watson's [[GDI|API Graphics Series]].  The code also uses Dan Teel's demo [[GDIPlusLoadAnyImage|Load Any Image with GDIPlus]].

Two structs are needed.  The first is for the {{GetObjectA}} code.  The struct holds the bitmap information.
[[code]]
    Struct ImageInfo, _
        imgType as Long, _
        imgWidth as Long, _
        imgHeight as Long, _
        imgWidthBytes as Long, _
        imgPlanes as Word, _
        imgBitsPixel as Word, _
        imgBits as Long
[[code]]
The second struct is for the {{GdipCreateBitmapFromFile}} code.
[[code]]
    Struct doubleWord, a as uLong
[[code]]

Once the image is loaded and {{GetObjectA}} is called, the ImageInfo struct will contain the bitmap.  Copy the width and height information from the struct to numeric variables.
[[code]]
        imgWidth = ImageInfo.imgWidth.struct
        imgHeight = ImageInfo.imgHeight.struct
[[code]]
The advantages to loading an image with {{GdipCreateBitmapFromFile}} and then calling {{GetObjectA}} to find the width and height of the image are
>> 1.  No parsing of the image extension is needed to identify the image format
>> 2.  No complicated math formulas are needed to extract the width and height of the format
>> 3.  No error is given when trying to access a file path longer than 128 characters

When the image is no longer needed, delete the image from memory with {{DeleteObject}}.
[[code]]
    Call DeleteObject hImage

Sub DeleteObject hImage
    CallDLL #gdi32, "DeleteObject", _
        hImage as uLong, _
        result as Long
End Sub
[[code]]

===Demo to Load an Image with GdipCreateBitmapFromFile and Find Dimensions with GetObjectA===
[[code format="vbnet"]]

' Extension variable for Filedialog
' Valid image formats are bmp, gif, ico, jpg, png, and tiff
    iExt$ = "*.bmp;*.gif;*.ico;*.jpg;*.png;*.tiff"

' Variables to hold the width and height of the image
    imageWidth = 0
    imageHeight = 0

' Struct necessary for loading an image with GDIPlus
    Struct doubleWord, a as uLong

' Struct necessary for returning image file information
    Struct ImageInfo, _
        imgType as Long, _
        imgWidth as Long, _
        imgHeight as Long, _
        imgWidthBytes as Long, _
        imgPlanes as Word, _
        imgBitsPixel as Word, _
        imgBits as Long

' Design a GUI to host the image
    WindowWidth = 800
    WindowHeight = 600
    UpperLeftX = Int((DisplayWidth - WindowWidth) / 2)
    UpperLeftY = Int((DisplayHeight - WindowHeight) / 2)

' Design a graphicbox to display the image
    Stylebits #main.g, 0, _WS_BORDER, 0, 0
    Graphicbox #main.g, 0, 0, 792, 580

    Open "Getting the Image Width and Height with GetObjectA" for Window_nf as #main
    #main "Trapclose [closeApp]"
    #main "Font Verdana 10 Bold"
    hMain = hWnd(#main)
    hG = hWnd(#main.g)
    #main.g "Down"
' Load an image file
    Filedialog "Image to Load", iExt$, imagePathFile$
' Load the image using GDIPlus, hImage is the returned handle to the bitmap in memory
    hImage = LoadImgFromFile(imagePathFile$)
' Get the bitmap information using GetObjectA
    imageDimen$ = ImageDimensions$(hImage)
    imageW = Val(Word$(imageDimen$, 1, Chr$(0)))
    imageH = Val(Word$(imageDimen$, 2, Chr$(0)))
' Load the bitmap in memory
    Loadbmp "pic", hImage
' Draw the image using native LB command Drawbmp
    #main.g "Drawbmp pic 10 10; Flush"
' Resize the graphicbox to the size of the image
    #main.g "Locate 0 0 ";imageW + 20;" ";imageH + 20
    #main "Refresh"
' Give the width and height of the image
    msg$ = "Image Dimensions";Chr$(10);Chr$(13); _
        "Width: ";imageW;" pixels";Chr$(10);Chr$(13); _
        "Height: ";imageH;" pixels";Chr$(10);Chr$(13)
    Notice msg$
Wait

[closeApp]
' Unload the native LB bitmap
    Unloadbmp "pic"
' Release memory from GDIPlus loaded image
    Call DeleteObject hImage
    Close #main
End

Function ImageDimensions$(hImage)
    lStruct = Len(ImageInfo.struct)
    CallDLL #gdi32, "GetObjectA", _
        hImage as uLong, _
        lStruct as Long, _
        ImageInfo as struct, _
        result as Long
        imgWidth = ImageInfo.imgWidth.struct
        imgHeight = ImageInfo.imgHeight.struct
        ImageDimensions$ = Str$(imgWidth);Chr$(0);Str$(imgHeight)
End Function

Function wChar$(string$)
    For i = 1 to Len(string$)
        wChar$ = wChar$ + Mid$(string$, i, 1) + chr$(0)
    Next i
    wChar$ = wChar$ + Chr$(0) + Chr$(0)
End Function

Function LoadImgFromFile(picFile$)
    Open "gdiplus.dll" for dll as #gdip
    gdistart$=Chr$(1)
    For i = 1 to 15
        gdistart$ = gdistart$ + Chr$(0)
    Next i
    Calldll #gdip,"GdiplusStartup", _
        doubleWord as struct, _
        gdistart$ as Ptr, _
        status as uLong
    token=doubleWord.a.struct
    If status <> 0 Then
        LoadImgFromFile = 0
    Else
        wFileLoc$=wChar$(picFile$)
        Calldll #gdip,"GdipCreateBitmapFromFile", _
            wFileLoc$ as Ptr, _
            doubleWord as struct, _
            status as uLong
        hPic = doubleWord.a.struct
        If status <>0 then
            LoadImgFromFile=0
        Else
            CallDLL #gdip,"GdipCreateHBITMAPFromBitmap", _
            hPic as uLong, _
            doubleWord as struct, _
            0 as uLong, _
            status as uLong
            hImage=doubleWord.a.struct
            If status <> 0 Then
                LoadImgFromFile = 0
            Else
                LoadImgFromFile = hImage
            End if
            CallDLL #gdip,"GdipDisposeImage", _
                hPic as uLong, _
                result as uLong
        End If
        CallDLL #gdip,"GdiplusShutdown", _
            token as uLong, _
            result as uLong
    End If
    Close #gdip
End Function

Sub DeleteObject hImage
    CallDLL #gdi32, "DeleteObject", _
        hImage as uLong, _
        result as Long
End Sub
[[code]]


----