﻿; Date: 20.01.2018
#Region ;************ Includes ************
#include-once
#include <GDIPlus.au3>
#EndRegion ;************ Includes ************

If $__g_hGDIPDll = 0 Then
	_GDIPlus_Startup()
	OnAutoItExitRegister('__IGPI_Exit')
EndIf

Func __IGPI_Exit()
	_GDIPlus_Shutdown()
EndFunc

; Diese Funktion liest 24 ausgewaehlte (siehe $aDescription in __GDIPlus_ImageGetItemValue)
; Exifdaten aus der uebergebenen GDI+ Bitmap aus und gibt diese als String in
; englisch ($iLanguage = 0) oder deutsch ($iLanguage = 1) zurueck
Func _GDIPlus_ImageGetPropertyItems(ByRef $hImage, $iLanguage)
	Local Const $tagGDIPPROPERTYITEM = 'uint id;uint length;ushort type;ptr value;'
	Local $aDim, $aFormat, $aRes, $iSize, $iCount, $tBuffer, $pBuffer, $tGDIPPROPERTYITEM, $sOut
	$aDim = _GDIPlus_ImageGetDimension($hImage)
	If @error Then Return SetError(1, @error, False)
	$aFormat = _GDIPlus_ImageGetPixelFormat($hImage)
	$sOut = StringFormat('%s|%d x %d px  (%s)\r', ($iLanguage ? 'Bildgröße' : 'Picture Dimension'), $aDim[0], $aDim[1], $aFormat[1])
	$aRes = DllCall($__g_hGDIPDll, 'uint', 'GdipGetPropertySize', 'hwnd', $hImage, 'uint*', 0, 'uint*', 0)
	If @error Then Return SetError(2, @extended, False)
	$iSize = $aRes[2] ; $aRes[2] = Total size in bytes
	$iCount = $aRes[3] ; $aRes[3] = Number of property items
	$tBuffer = DllStructCreate('byte[' & $iSize & ']')
	$pBuffer = DllStructGetPtr($tBuffer)
	$aRes = DllCall($__g_hGDIPDll, 'uint', 'GdipGetAllPropertyItems', 'hwnd', $hImage, 'uint', $iSize, 'uint', $iCount, 'ptr', $pBuffer)
	If @error Then Return SetError(3, @extended, False)
	For $i = 0 To $iCount - 1
		$tGDIPPROPERTYITEM = DllStructCreate($tagGDIPPROPERTYITEM, $pBuffer)
		$sOut &= __GDIPlus_ImageGetItemValue($tGDIPPROPERTYITEM, $iLanguage)
		$pBuffer += DllStructGetSize($tGDIPPROPERTYITEM)
		$tGDIPPROPERTYITEM = 0
	Next
	$tBuffer = 0
	Return StringTrimRight($sOut, 1)
EndFunc   ;==>_GDIPlus_ImageGetPropertyItems

Func __GDIPlus_ImageGetItemValue(ByRef $tITEM, $iLanguage = 0)
	Local Const $aDescription[24][2] = [ _
			['GPS Latitude Ref.', 'GPS Breitengrad Ref.'], _
			['GPS Latitude', 'GPS Breitengrad'], _
			['GPS Longitude Ref.', 'GPS Längengrad Ref.'], _
			['GPS Longitude', 'GPS Längengrad'], _
			['GPS Altitude Ref.', 'GPS Höhe Ref.'], _
			['GPS Altitude', 'GPS Höhe'], _
			['GPS ImageDirection', 'GPS Bildausrichtung'], _
			['Picture Description', 'Bildbeschreibung'], _
			['Camera Manufacturer', 'Kamerahersteller'], _
			['Camera Model', 'Kameramodell'], _
			['Software', 'Software'], _
			['Artist', 'Photograph'], _
			['Copyright', 'Copyright'], _
			['Exposure Time', 'Belichtungszeit'], _
			['FNumber', 'Blende'], _
			['ISO Speed Ratings', 'ISO-Wert'], _
			['Exif-Version', 'Exif-Version'], _
			['Date Time Original', 'Aufnahmedatum'], _
			['Date Time Digitized', 'Speicherdatum'], _
			['Exposure Bias Value', 'Belichtungskorrektur'], _
			['Flash', 'Blitz'], _
			['Focal Length', 'Brennweite'], _
			['Exif Image Width', 'Exif Bildbreite'], _
			['Exif Image Height', 'Exif Bildhöhe']]
	Local Const $aFlash[2][2] = [['No', 'Nein'], ['Yes', 'Ja']], $sDel1 = '|', $sDel2 = @CR
	Local Const $aAltRef[2][2] = [['Above sea level', 'Oberhalb des Meeresspiegels'], ['Below sea level', 'Unterhalb des Meeresspiegels']]
	Local Enum $GPSLatRef, $GPSLat, $GPSLonRef, $GPSLon, $GPSAltRef, $GPSAlt, $GPSImgDir, $Description, $Make, $Model, $Software, $Artist, $Copyright, $ExpTime, $FNumber, $ISO, $ExifVer, $DTOrig, $DTDig, $ExpBias, $Flash, $FocLen, $Width, $Height
	Local $iID = DllStructGetData($tITEM, 'id'), $sOut = ''
	Switch $iID
		Case 0x0001 ; GPS LatitudeRef (N/S)
			$sOut = $aDescription[$GPSLatRef][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x0002 ; GPS Latitude
			$sOut = $aDescription[$GPSLat][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x0003 ; GPS LongitudeRef (E/W)
			$sOut = $aDescription[$GPSLonRef][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x0004 ; GPS Longitude
			$sOut = $aDescription[$GPSLon][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x0005 ; GPS AltitudeRef (above/below sea level)
			$sOut = $aDescription[$GPSAltRef][$iLanguage] & $sDel1 & $aAltRef[__GDIPlus_ImageGetValue($tITEM, $iID)][$iLanguage] & $sDel2
		Case 0x0006 ; GPS Altitude
			$sOut = $aDescription[$GPSAlt][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x0011 ; GPS ImageDirection
			$sOut = $aDescription[$GPSImgDir][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x010E ; Bildbeschreibung
			$sOut = $aDescription[$Description][$iLanguage] & $sDel1 & BinaryToString(__GDIPlus_ImageGetValue($tITEM, $iID), 4) & $sDel2
		Case 0x010f ; Kamerahersteller
			$sOut = $aDescription[$Make][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x0110 ; Kameramodell
			$sOut = $aDescription[$Model][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x0131 ; Software
			$sOut = $aDescription[$Software][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x013B ; Photograph
			$sOut = $aDescription[$Artist][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x8298 ; Copyright
			$sOut = $aDescription[$Copyright][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x829A ; Belichtungszeit
			$sOut = $aDescription[$ExpTime][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & ' s' & $sDel2
		Case 0x829D ; Blende
			$sOut = $aDescription[$FNumber][$iLanguage] & $sDel1 & StringFormat('F %.2f', __GDIPlus_ImageGetValue($tITEM, $iID)) & $sDel2
		Case 0x8827 ; ISO-Wert
			$sOut = $aDescription[$ISO][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x9000 ; ExifVersion
			$sOut = $aDescription[$ExifVer][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x9003 ; Datum/Zeit der Aufnahme
			$sOut = $aDescription[$DTOrig][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x9004 ; Datum/Zeit der Speicherung
			$sOut = $aDescription[$DTDig][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & $sDel2
		Case 0x9204 ; Belichtungskorrektur
			$sOut = $aDescription[$ExpBias][$iLanguage] & $sDel1 & StringFormat('%.2f', __GDIPlus_ImageGetValue($tITEM, $iID)) & $sDel2
		Case 0x9209 ; Blitz
			$sOut = $aDescription[$Flash][$iLanguage] & $sDel1 & $aFlash[__GDIPlus_ImageGetValue($tITEM, $iID)][$iLanguage] & $sDel2
		Case 0x920A ; Brennweite
			$sOut = $aDescription[$FocLen][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & ' mm' & $sDel2
		Case 0xA002 ; Bildbreite
			$sOut = $aDescription[$Width][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & ' px' & $sDel2
		Case 0xA003 ; Bildhoehe
			$sOut = $aDescription[$Height][$iLanguage] & $sDel1 & __GDIPlus_ImageGetValue($tITEM, $iID) & ' px' & $sDel2
	EndSwitch
	Return $sOut
EndFunc   ;==>__GDIPlus_ImageGetItemValue

Func __GDIPlus_ImageGetValue(ByRef $tITEM, $iID)
	Local Const $GDIP_PROPERTYTAGTYPEBYTE = 1
	Local Const $GDIP_PROPERTYTAGTYPEASCII = 2
	Local Const $GDIP_PROPERTYTAGTYPESHORT = 3
	Local Const $GDIP_PROPERTYTAGTYPELONG = 4
	Local Const $GDIP_PROPERTYTAGTYPERATIONAL = 5
	Local Const $GDIP_PROPERTYTAGTYPEUNDEFINED = 7
	Local Const $GDIP_PROPERTYTAGTYPESLONG = 9
	Local Const $GDIP_PROPERTYTAGTYPESRATIONAL = 10
	Local $iSize, $iType, $pValue, $tBuffer, $sOut, $iDeg, $iMin, $iDec
	$iSize = DllStructGetData($tITEM, 'length')
	$iType = DllStructGetData($tITEM, 'type')
	$pValue = DllStructGetData($tITEM, 'value')
	Switch $iType ; der Puffer fuer die Items kann unterschiedliche Strukturen aufweisen
		Case $GDIP_PROPERTYTAGTYPEBYTE ; array of bytes
			$tBuffer = DllStructCreate('byte[' & $iSize & ']', $pValue)
			$sOut = DllStructGetData($tBuffer, 'val1')
		Case $GDIP_PROPERTYTAGTYPEASCII ; null-terminated ASCII string
			$tBuffer = DllStructCreate('byte[' & $iSize & ']', $pValue)
			$sOut = BinaryToString(DllStructGetData($tBuffer, 1))
			$sOut = StringReplace($sOut, Chr(0), '')
		Case $GDIP_PROPERTYTAGTYPESHORT ; array of unsigned short (16-bit)
			$tBuffer = DllStructCreate('ushort', $pValue)
			If $iID = 0x9209 Then ; Blitz
				$sOut = BitAND(DllStructGetData($tBuffer, 1), 1) == 1 ; nur False/True
			Else
				$sOut = DllStructGetData($tBuffer, 1)
			EndIf
		Case $GDIP_PROPERTYTAGTYPELONG ; array of unsigned long (32-bit)
			$tBuffer = DllStructCreate('ulong', $pValue)
			$sOut = DllStructGetData($tBuffer, 1)
		Case $GDIP_PROPERTYTAGTYPERATIONAL ; array of pairs of unsigned long
			$tBuffer = DllStructCreate('ulong val1;ulong val2;ulong val3;', $pValue)
			Switch $iID
				Case 0x0002, 0x0004 ; GPS Latitude und Longitude
					$iDeg = DllStructGetData($tBuffer, 'val1') / DllStructGetData($tBuffer, 'val2')
					$iMin = DllStructGetData($tBuffer, 'val3') / 10000
					$iDec = $iMin / 60 + $iDeg
					$sOut = StringFormat('%i  %.4f  (%f)', $iDeg, $iMin, $iDec)
				Case 0x0006 ; GPS Altitude
					$sOut = StringFormat('%.2f m', DllStructGetData($tBuffer, 'val1') / 100)
				Case 0x0011 ; GPS ImageDirection
					$sOut = StringFormat('%.2f', DllStructGetData($tBuffer, 'val1') / 100)
				Case 0x829A ; Belichtungszeit
					$sOut = DllStructGetData($tBuffer, 'val1') & '/' & DllStructGetData($tBuffer, 'val2')
				Case 0x829D, 0x920A ; Blende und Brennweite
					$sOut = DllStructGetData($tBuffer, 'val1') / DllStructGetData($tBuffer, 'val2')
			EndSwitch
		Case $GDIP_PROPERTYTAGTYPEUNDEFINED ; 4 Byte ASCII string
			$tBuffer = DllStructCreate('byte[4]', $pValue)
			$sOut = BinaryToString(DllStructGetData($tBuffer, 1))
		Case $GDIP_PROPERTYTAGTYPESRATIONAL ; array of pairs of signed long
			$tBuffer = DllStructCreate('long val1;long val2;', $pValue)
			$sOut = DllStructGetData($tBuffer, 'val1') / DllStructGetData($tBuffer, 'val2')
	EndSwitch
	$tBuffer = 0
	Return $sOut
EndFunc   ;==>__GDIPlus_ImageGetValue
