VBA – Get Image Properties, Dimensions, Etc.

I’ve made a few posts in the past regarding image manipulations (resize, rotate, …) but never covered the most basic aspect, which is simply getting general information about an image. Below is a sample which utilizes WIA automation.

Private Type ImgageInfo
    Height                    As Long
    Width                     As Long
    FileExtension             As String
    HorizontalResolution      As Double
    VerticalResolution        As Double
    PixelDepth As Long
End Type
Public Img                    As ImgageInfo


'---------------------------------------------------------------------------------------
' Procedure : WIA_GetImgDimensions
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve various properties (dimensions, extension, resolution) of an image
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Uses Late Binding, so none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFile     : Fully qualified path, filename and extension of the image file to check
'
' Usage:
' ~~~~~~
' Call WIA_GetImgDimensions(C:\Tmp\database.png )
' Debug.Print sFile, "Width: " & Img.Width, "Height: " & Img.Height, "FileExtension: " & _
'                  Img.FileExtension, "HorizontalResolution: " & Img.HorizontalResolution, _
'                  "VerticalResolution: " & Img.VerticalResolution, _
'                  "PixelDepth: " & Img.PixelDepth
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2018-10-23              Initial Release
'---------------------------------------------------------------------------------------
Function WIA_GetImgDimensions(ByVal sFile As String) As Boolean
    'For a complete listing of available WIA ImageFile properties
    '   Ref: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/wiaaut/-wiaaut-imagefile
    On Error GoTo Error_Handler
    Dim oWIA                  As Object

    Set oWIA = CreateObject("WIA.ImageFile")
    oWIA.LoadFile sFile
    Img.Width = oWIA.Width
    Img.Height = oWIA.Height
    Img.FileExtension = oWIA.FileExtension
    Img.HorizontalResolution = oWIA.HorizontalResolution
    Img.VerticalResolution = oWIA.VerticalResolution
    Img.PixelDepth = oWIA.PixelDepth

Error_Handler_Exit:
    On Error Resume Next
    If Not oWIA Is Nothing Then Set oWIA = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: WIA_GetImgDimensions" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function



Private Sub Testme()
    Dim sFile                 As String

    sFile = "C:\Tmp\1.png"
    Call WIA_GetImgDimensions(sFile)
    Debug.Print sFile, "Width: " & Img.Width, "Height: " & Img.Height, _
                "FileExtension: " & Img.FileExtension, _
                "HorizontalResolution: " & Img.HorizontalResolution, _
                "VerticalResolution: " & Img.VerticalResolution, _
                "PixelDepth: " & Img.PixelDepth

    sFile = "C:\Tmp\2.jpg"
    Call WIA_GetImgDimensions(sFile)
    Debug.Print sFile, "Width: " & Img.Width, "Height: " & Img.Height, _
                "FileExtension: " & Img.FileExtension, _
                "HorizontalResolution: " & Img.HorizontalResolution, _
                "VerticalResolution: " & Img.VerticalResolution, _
                "PixelDepth: " & Img.PixelDepth

    sFile = "C:\Tmp\3.gif"
    Call WIA_GetImgDimensions(sFile)
    Debug.Print sFile, "Width: " & Img.Width, "Height: " & Img.Height, _
                "FileExtension: " & Img.FileExtension, _
                "HorizontalResolution: " & Img.HorizontalResolution, _
                "VerticalResolution: " & Img.VerticalResolution, _
                "PixelDepth: " & Img.PixelDepth
End Sub

Similarly, we can get the dimension using the Shell object

Private Type ImgageInfo
    Height                    As Long
    Width                     As Long
    FileExtension             As String
    HorizontalResolution      As Double
    VerticalResolution        As Double
    PixelDepth                As Long
End Type
Public Img                    As ImgageInfo


'---------------------------------------------------------------------------------------
' Procedure : Shell_GetImgDimensions
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve the dimensions, extension of an image
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Uses Late Binding, so none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFile     : Fully qualified path, filename and extension of the image file to check
'
' Usage:
' ~~~~~~
' Call Shell_GetImgDimensions(C:\Tmp\database.png )
' Debug.Print sFile, "Width: " & Img.Width, "Height: " & Img.Height
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2018-10-23              Initial Release
' 2         2018-11-04              Made Option Explicit Compliant
'---------------------------------------------------------------------------------------
Function Shell_GetImgDimensions(ByVal sFile As String) As Boolean
    On Error GoTo Error_Handler
    Dim oShell                As Object    'Shell
    Dim oFolder               As Object    'Folder2
    Dim oFile                 As Object    'FolderItem
    Dim sPath                 As String
    Dim sFilename             As String
    Dim sDims                 As String

    sPath = Left(sFile, InStrRev(sFile, "\") - 1)
    sFilename = Right(sFile, Len(sFile) - InStrRev(sFile, "\"))

    Set oShell = CreateObject("Shell.Application")
    Set oFolder = oShell.NameSpace(CStr(sPath))
    Set oFile = oFolder.ParseName(sFilename)

    sDims = oFile.ExtendedProperty("Dimensions")    '-> ?470 x 668?
    sDims = Right(sDims, Len(sDims) - 1)
    sDims = Left(sDims, Len(sDims) - 1)
    Img.Width = CLng(Split(sDims, "x")(0))
    Img.Height = CLng(Split(sDims, "x")(1))

Error_Handler_Exit:
    On Error Resume Next
    If Not oFile Is Nothing Then Set oFile = Nothing
    If Not oFolder Is Nothing Then Set oFolder = Nothing
    If Not oShell Is Nothing Then Set oShell = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: Shell_GetImgDimensions" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function



Private Sub Testme()
    Dim sFile                 As String

    sFile = "C:\Tmp\1.png"
    Call Shell_GetImgDimensions(sFile)
    Debug.Print sFile, "Width: " & Img.Width, "Height: " & Img.Height
    
    sFile = "C:\Tmp\2.jpg"
    Call Shell_GetImgDimensions(sFile)
    Debug.Print sFile, "Width: " & Img.Width, "Height: " & Img.Height
    
    sFile = "C:\Tmp\3.gif"
    Call Shell_GetImgDimensions(sFile)
    Debug.Print sFile, "Width: " & Img.Width, "Height: " & Img.Height
End Sub

18 responses on “VBA – Get Image Properties, Dimensions, Etc.

  1. Tim K

    In my case I commented out the lines to remove extraneous characters.
    sDims = oFile.ExtendedProperty(“Dimensions”) ‘-> ?470 x 668?
    ‘Debug.Print sDims
    ”’ sDims = Right(sDims, Len(sDims))
    ”’ sDims = Left(sDims, Len(sDims))
    Img.Width = CLng(Split(sDims, “x”)(0))
    Img.Height = CLng(Split(sDims, “x”)(1))
    because my operating system wasn’t including any. If I left them in, they results returned trunacated a digit from each dimension

  2. Paul Lehmann

    the line
    Switch(Erl = 0, “”, Erl 0, vbCrLf & “Line No: ” & Erl)
    gives an error, because Switch is not defined.

  3. Don Wiss

    I’m finding this does not work when trying to get the dimensions of a webp file. When trying to load the ImageFile object with the specified file, I get the error:
    The parameter is incorrect.
    I am using Excel 2002.

    1. Daniel Pineault Post author

      That doesn’t surprise me as webp is a newer format (around 2018) from Google and WIA is an older technology (came out with Windows XP – around 2001). I could be wrong, but I believe WIA is limited to working with BMP, GIF, JPEG, PNG and TIFF files.

      I’d look at alternative approaches, perhaps try:

      It all depends on how Google created the format and what they’ve made accessible. I’ve never worked with webp, so I can’t help too much beyond suggesting trying different things.

  4. Don Wiss

    For me, and all other interested readers, to put the effort into learning three ways that may, or may not, produce the results I’m looking for, isn’t very efficient. You have all of those implemented on your machine. A webp file can readily be found on the web to test. It is becoming the standard for major websites.

    1. Daniel Pineault Post author

      I’m not sure I follow 100%. I demonstrates a multitude of ways to approach things so people have options. You then weigh the PROs and CONs and select the right one to fill your needs. Normally, you wouldn’t have 3 libraries to perform the same task, you’d select and implement the one that works for you. At the same time, code is very small in the grand scheme of thing, so if adding 3 text modules to a project enable someone to do everything the wish to, then they can! There truly isn’t a downside to it.

      As for webp, I’ve never seen it before on any website. I’ll do some testing in the coming days as it is always a good idea to be aware of new things, learn a new thing. So thank you for sharing. It will be interesting to compare file sizes, quality, rendering…

  5. Anton Fernando

    What I am trying to access is the Color Representation info like RGB, CMY, HSI ie you can see this in windows explorer right clicking on a photo file and the properties then the details tab. In the image section you have Color representation. I would like to get VBA access to this.

      1. Anton Fernando

        Thank you for your prompt reply. I have used your first example. I can’t find the description for Color representation. Looking at file explorer file properties there is reference to Color representation and yet it not in the list you generated. Things like Photoshop show this value as well. I am a bit lost as how to proceed. I wish I could save a screen shot here to show you.

  6. Bill

    Daniel, I am interested in using the GetImageProperties, but when i try to compile it in Excel editor i am getting the following error:
    Sub or Function not defined: Getting this error on line “GetPropertyValue = Eval(GetPropertyValue)”
    Type mismatch: Getting this error on line “GDIStatus = GdipCreateBitmapFromFile(StrPtr(sFile), lBitmap)”
    i am using Win 11 Pro, Excel 22019. Any help is greatly appricated.

    1. Daniel Pineault Post author

      It’s because Excel doesn’t have an Eval() function. You can either edit the function and change

      GetPropertyValue = Eval(GetPropertyValue)
      To
      GetPropertyValue = Evaluate(GetPropertyValue)

      Or, so as to not mess with the function, add a custom Eval() function to your module like:

      Public Function Eval(sInput As String)
      Eval = Evaluate(sInput)
      End Function

      1. Bill

        Thank you Daniel for the quick reply, i am still getting the type mismatch error on line “GDIStatus = GdipCreateBitmapFromFile(StrPtr(sFile), lBitmap)”

          1. Daniel Pineault Post author

            Well, then that’s the problem. The code here is 32-bit. You’d need to convert it to 64-bit by updating all the APIs and calls. Not something I’ve done, because I don’t use, nor do any of my customer use 64-bit office.

            I wish I could be more helpful, but it’s simply not something I can get into right now.

            If you want post it to a forum and see if people there can’t assist you with the conversion.