- Offizieller Beitrag
Diese Funktion kann eine GDI+ Bitmap als JPG abspeichern.
Das allein ist ja nichts Besonderes, aber meine Funktion bietet an, die Bitmap vorher zu skalieren und zu drehen bzw. zu spiegeln und kann dann trotzdem noch die EXIF-Daten der Ursprungsbitmap übernehmen.
Beim skalieren einer GDI+ Bitmap (mit _GDIPlus_ImageScale) wird nämlich eine neue Bitmap erstellt und wenn man diese abspeichert, gehen die EXIF-Daten verloren. Will man diese beibehalten, muss man die Daten von der "alten" Bitmap rüberkopieren.
Und genau dieses kopieren der EXIF-Daten hat mich den ganzen gestrigen Tag beschäftigt. Ich wollte das unbedingt nur mit AutoIt schaffen (ohne externe Programme verwenden zu müssen).
Heute habe ich dann den Durchbruch geschafft und die Funktion fertig gestellt:
Spoiler anzeigen
#include <GDIPlus.au3>
Global $sImagefile = @ScriptDir & '\test.jpg'
Global $sNewFile = @ScriptDir & '\test_new.jpg'
_GDIPlus_Startup()
Global $hImage = _GDIPlus_BitmapCreateFromFile($sImagefile)
; Bild als JPG speichern mit Uebername der EXIF-Daten, 90% Qualitaet, Breite und Hoehe jeweils 25% und keine Drehung
_GDIPlus_ImageSaveAsJPG($hImage, $sNewFile, True, 90, 0.25, 0.25, 0)
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_Shutdown()
If FileExists($sNewFile) Then ShellExecute($sNewFile)
Exit
#cs
$iRotate = Type of rotation and flip:
0 - No rotation and no flipping (A 180-degree rotation, a horizontal flip and then a vertical flip)
1 - A 90-degree rotation without flipping (A 270-degree rotation, a horizontal flip and then a vertical flip)
2 - A 180-degree rotation without flipping (No rotation, a horizontal flip followed by a vertical flip)
3 - A 270-degree rotation without flipping (A 90-degree rotation, a horizontal flip and then a vertical flip)
4 - No rotation and a horizontal flip (A 180-degree rotation followed by a vertical flip)
5 - A 90-degree rotation followed by a horizontal flip (A 270-degree rotation followed by a vertical flip)
6 - A 180-degree rotation followed by a horizontal flip (No rotation and a vertical flip)
7 - A 270-degree rotation followed by a horizontal flip (A 90-degree rotation followed by a vertical flip)
#ce
Func _GDIPlus_ImageSaveAsJPG($hImage, $sSaveFile, $bEXIF = True, $iQuality = 90, $fScaleW = 1.0, $fScaleH = 1.0, $iRotate = 0)
Local $hScaledBitmap, $sCLSID, $tData, $tParams, $bRet, $iError = 0
$hScaledBitmap = _GDIPlus_ImageScale($hImage, $fScaleW, $fScaleH) ; das Bild skalieren (neue Bitmap wird erstellt)
If $iRotate Then _GDIPlus_ImageRotateFlip($hScaledBitmap, $iRotate) ; die neue Bitmap drehen bzw. spiegeln (wenn gewuenscht)
If $bEXIF Then ; die EXIF-Daten in die neue Bitmap kopieren (wenn gewuenscht)
_GDIPlus_ImageCopyPropertyItems($hImage, $hScaledBitmap)
If @error Then Return SetError(@error, @extended, False)
EndIf
$sCLSID = _GDIPlus_EncodersGetCLSID('JPG')
$tParams = _GDIPlus_ParamInit(1)
$tData = DllStructCreate('int Quality') ; Struktur fuer die JPG-Qualitaet erstellen
DllStructSetData($tData, 'Quality', $iQuality) ; JPG-Qualitaet entsprechend setzen (von 0 = schlechteste bis 100 = beste)
_GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, 'Quality'))
$bRet = _GDIPlus_ImageSaveToFileEx($hScaledBitmap, $sSaveFile, $sCLSID, $tParams)
If @error Then $iError = 4
_GDIPlus_BitmapDispose($hScaledBitmap)
$tData = 0
Return SetError($iError, 0, $bRet)
EndFunc ;==>_GDIPlus_ImageSaveAsJPG
Func _GDIPlus_ImageCopyPropertyItems(ByRef $hSourceImage, ByRef $hDestImage)
Local Const $tagGDIPPROPERTYITEM = 'uint id;uint length;ushort type;ptr value;'
Local $aRes, $iSize, $iCount, $tBuffer, $pBuffer, $tGDIPPROPERTYITEM
$aRes = DllCall($__g_hGDIPDll, 'uint', 'GdipGetPropertySize', 'hwnd', $hSourceImage, 'uint*', 0, 'uint*', 0)
If @error Then Return SetError(1, @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', $hSourceImage, 'uint', $iSize, 'uint', $iCount, 'ptr', $pBuffer)
If @error Then Return SetError(2, @extended, False)
For $i = 0 To $iCount - 1
$tGDIPPROPERTYITEM = DllStructCreate($tagGDIPPROPERTYITEM, $pBuffer)
$aRes = DllCall($__g_hGDIPDll, 'uint', 'GdipSetPropertyItem', 'hwnd', $hDestImage, 'ptr', $pBuffer)
If @error Then Return SetError(3, @extended, False)
$pBuffer += DllStructGetSize($tGDIPPROPERTYITEM)
$tGDIPPROPERTYITEM = 0
Next
$tBuffer = 0
Return True
EndFunc ;==>_GDIPlus_ImageCopyPropertyItems
Alles anzeigen
Vielleicht könnt ihr so eine Funktion ja auch gebrauchen...
P.S.: Als Anhang findet ihr ein Test-JPG (mit EXIF-Daten).