Jump to content

Getting value of a string Exif property of an image


 Share

Recommended Posts

The following code is one of my many attempts to get the value of a string property from an image. It doesn't work. I know that IMAGEDESCRIPTION has a string value.

In one of my many attempts, I did get the string OLYMPUS .., which I know is correct from IrfanView, but I can't get it again.

How should I get this string?

 

#include <GDIPlus.au3>
Opt('MustDeclareVars',1)

; Property Item structure
Global Const $tagGDIPPROPERTYITEM = _
    "uint id;" & _          ; ID of this property
    "uint length;" & _      ; Length of the property value, in bytes
    "ushort type;" & _      ; Type of the value, as one of TAG_TYPE_XXX constants
    "ptr value;"            ; property value

Global Const $GDIP_PROPERTYTAGIMAGEDESCRIPTION = 0x010E

; #VARIABLES# ===================================================================================================================
Global $ghGDIPMatrix = 0
Global $GDIP_STATUS = 0
Global $GDIP_ERROR = 0

Local $Dsk_ghImage

    _GDIPlus_Startup()
    $Dsk_ghImage = _GDIPlus_ImageLoadFromFile('H:\b\PA160005 - Copy.JPG')

    Local $propListVec = _GDIPlus_ImageGetPropertyIdList($Dsk_ghImage)
    Local $qProps = $propListVec[0]
    For $i = 1 To $qProps
        $propListVec[$i] = Hex($propListVec[$i])
        While StringLeft($propListVec[$i],1)='0'
            $propListVec[$i] = StringMid($propListVec[$i],2)
        WEnd
        ConsoleWrite($propListVec[$i]&@CRLF)
    Next

    Local $tProp = _GDIPlus_ImageGetPropertyItem($Dsk_ghImage,$GDIP_PROPERTYTAGIMAGEDESCRIPTION)

    Local $len = $tProp.length
    Local $s = 'char str['&$len&']'
    Local $ptr = $tProp.value
    Local $tStr = DllStructCreate($s,$ptr)
MsgBox(0,'@error',@error)
    Local $strval = DllStructGetData($tStr,'str')
MsgBox(0,'','@error '&@error&'   strval '&$strval)


; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_ImageGetPropertyIdList
; Description ...: Gets a list of the property identifiers used in the metadata of an Image object
; Syntax.........: _GDIPlus_ImageGetPropertyIdList($hImage)
; Parameters ....: $hImage - Pointer to an Image object
; Return values .: Success      - Array of property identifiers:
;                  |[0] - Number of property identifiers
;                  |[1] - Property identifier 1
;                  |[2] - Property identifier 2
;                  |[n] - Property identifier n
;                  Failure      - -1 and either:
;                  |@error and @extended are set if DllCall failed
;                  |$GDIP_STATUS contains a non zero value specifying the error code
;                  |$GDIP_ERROR:
;                  |    1 - The _GDIPlus_ImageGetPropertyCount function failed, $GDIP_STATUS contains the error code
;                  |    2 - The image does not contain any property items
;                  |    3 - The _GDIPlus_ImageGetPropertyIdList function failed, $GDIP_STATUS contains the error code
; Author.........: Authenticity
; Remarks .......: The property item identifiers are declared in GDIPConstants.au3, those that start with $GDIP_PROPERTYTAGN*
; Related .......: _GDIPlus_ImageGetAllPropertyItems, _GDIPlus_ImageGetPropertyCount, _GDIPlus_ImageGetPropertyItem
; Link ..........; @@MsdnLink@@ GdipGetPropertyIdList
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_ImageGetPropertyIdList($hImage)
    Local $iI, $iCount, $tProperties, $pProperties, $aProperties[1], $aResult

    $iCount = _GDIPlus_ImageGetPropertyCount($hImage)
    If @error Then Return SetError(@error, @extended, -1)

    If $GDIP_STATUS Then
        $GDIP_ERROR = 1
        Return -1
    ElseIf $iCount = 0 Then
        $GDIP_ERROR = 2
        Return -1
    EndIf

    $tProperties = DllStructCreate("uint[" & $iCount & "]")
    $pProperties = DllStructGetPtr($tProperties)
    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertyIdList", "hwnd", $hImage, "int", $iCount, "ptr", $pProperties)
    If @error Then Return SetError(@error, @extended, -1)

    $GDIP_STATUS = $aResult[0]
    If $GDIP_STATUS Then
        $GDIP_ERROR = 3
        Return -1
    EndIf

    ReDim $aProperties[$iCount + 1]
    $aProperties[0] = $iCount

    For $iI = 1 To $iCount
        $aProperties[$iI] = DllStructGetData($tProperties, 1, $iI)
    Next
    Return $aProperties
EndFunc   ;==>_GDIPlus_ImageGetPropertyIdList

; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_ImageGetPropertyItem
; Description ...: Gets a specified property item (piece of metadata) from an Image object
; Syntax.........: _GDIPlus_ImageGetPropertyItem($hImage, $iPropID)
; Parameters ....: $hImage  - Pointer to an Image object
;                  $iPropID - Identifier of the property item to be retrieved
; Return values .: Success      - $tagGDIPPROPERTYITEM structure containing the property size, type and value pointer
;                  Failure      - -1 and either:
;                  |@error and @extended are set if DllCall failed
;                  |$GDIP_STATUS contains a non zero value specifying the error code
;                  |$GDIP_ERROR:
;                  |    1 - The _GDIPlus_ImageGetPropertyItemSize function failed, $GDIP_STATUS contains the error code
;                  |    2 - The specified property identifier does not exist in the image
;                  |    3 - The _GDIPlus_ImageGetPropertyItem function failed, $GDIP_STATUS contains the error code
; Author.........: Authenticity
; Remarks .......: None
; Related .......: _GDIPlus_ImageGetPropertyIdList, _GDIPlus_ImageGetPropertyItemSize, $tagGDIPPROPERTYITEM
; Link ..........; @@MsdnLink@@ GdipGetPropertyItem
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_ImageGetPropertyItem($hImage, $iPropID)
    Local $iBuffer, $tBuffer, $pBuffer, $tPropertyItem, $aResult

    $iBuffer = _GDIPlus_ImageGetPropertyItemSize($hImage, $iPropID)
    If @error Then Return SetError(@error, @extended, -1)

    If $GDIP_STATUS Then
        $GDIP_ERROR = 1
        Return -1
    ElseIf $iBuffer = 0 Then
        $GDIP_ERROR = 2
        Return -1
    EndIf

    $tBuffer = DllStructCreate("byte[" & $iBuffer & "]")
    $pBuffer = DllStructGetPtr($tBuffer)
    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertyItem", "hwnd", $hImage, "uint", $iPropID, "uint", $iBuffer, "ptr", $pBuffer)
    If @error Then Return SetError(@error, @extended, -1)

    $GDIP_STATUS = $aResult[0]
    If $GDIP_STATUS Then
        $GDIP_ERROR = 3
        Return -1
    EndIf

    $tPropertyItem = DllStructCreate($tagGDIPPROPERTYITEM, $pBuffer)
    Return $tPropertyItem
EndFunc   ;==>_GDIPlus_ImageGetPropertyItem

; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_ImageGetPropertyCount
; Description ...: Gets the number of properties (pieces of metadata) stored in an Image object
; Syntax.........: _GDIPlus_ImageGetPropertyCount($hImage)
; Parameters ....: $hImage - Pointer to an Image object
; Return values .: Success      - Number of property items store in the Image object
;                  Failure      - -1 and either:
;                  |@error and @extended are set if DllCall failed
;                  |$GDIP_STATUS contains a non zero value specifying the error code
; Author.........: Authenticity
; Remarks .......: None
; Related .......: _GDIPlus_ImageGetAllPropertyItems, _GDIPlus_ImageGetPropertyIdList
; Link ..........; @@MsdnLink@@ GdipGetPropertyCount
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_ImageGetPropertyCount($hImage)
    Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertyCount", "hwnd", $hImage, "uint*", 0)

    If @error Then Return SetError(@error, @extended, -1)

    $GDIP_STATUS = $aResult[0]
    If $GDIP_STATUS Then Return -1
    Return $aResult[2]
EndFunc   ;==>_GDIPlus_ImageGetPropertyCount


; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_ImageGetPropertyItemSize
; Description ...: Gets the size, in bytes, of a specified property item of an Image object
; Syntax.........: _GDIPlus_ImageGetPropertyItemSize($hImage, $iPropID)
; Parameters ....: $hImage  - Pointer to an Image object
;                  $iPropID - Identifier of the property item to be retrieved
; Return values .: Success      - $tagGDIPPROPERTYITEM structure containing the property size, type and value pointer
;                  Failure      - -1 and either:
;                  |@error and @extended are set if DllCall failed
;                  |$GDIP_STATUS contains a non zero value specifying the error code
; Author.........: Authenticity
; Remarks .......: None
; Related .......: _GDIPlus_ImageGetPropertyIdList, _GDIPlus_ImageGetPropertyItem
; Link ..........; @@MsdnLink@@ GdipGetPropertyItemSize
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_ImageGetPropertyItemSize($hImage, $iPropID)
    Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertyItemSize", "hwnd", $hImage, "uint", $iPropID, "uint*", 0)

    If @error Then Return SetError(@error, @extended, -1)

    $GDIP_STATUS = $aResult[0]
    If $GDIP_STATUS Then Return -1
    Return $aResult[3]
EndFunc   ;==>_GDIPlus_ImageGetPropertyItemSize

 

Edited by c.haslam
Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Link to comment
Share on other sites

I think that I have found a solution to my own problem.

Reading much on the forum, I discovered something: never return a structure from a function! _GDIPlus_ImageGetPropertyItem() does this.

So my new version of this function returns a 1-dimensional array. For now, it returns property ID, type and value: I replaced Return $tPropertyItem with:

Local $retVec[3]
    $retVec[0] = $tPropertyItem.id
    $retVec[1] = $tPropertyItem.type
    Switch $tPropertyItem.type
        Case 2
            Local $tvalue = DllStructCreate('char str['&$tPropertyItem.length&']',$tPropertyItem.value)
            $retVec[2] = $tvalue.str
    EndSwitch
    Return $retVec

It may not need to return type.

Thank you to Valik for saying never to return a structure from a function. So far I have tested it on 2 string properties.

Edited by c.haslam
Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...