Hier noch die Verwendung von
GDI+. Nur einfaches Beispiel, ohne Ressourcenschutz oder Ähnliches. Leider bietet die Save-Procedure nicht die Option des Überschreibens, daher ein bisschen Nachbau.
GDI+ ist sehr schnell. Zu beachten ist, dass hier die Blockgröße
16 Pixel beträgt, Höhe/Breite also ein Vielfaches von 16 sein müssen.
Frustrierend ist, dass
GDI+ als 32-Bit-
DLL natürlich wieder mal nicht in 64-Bit-Anwendungen benutzt werden kann.
Delphi-Quellcode:
uses ... GDIPAPI, GDIPOBJ,GDIPUTIL;
procedure DreheMitGDIPlus1;
Var i:integer;
DatListe:TStringDynArray;
GPImage: TGPImage;
EncoderCLSID: TGUID;
Ergebnis : Status;
TempDatname:string;
const
Verz = 'C:\Test\';
begin
DatListe := TDirectory.GetFiles(Verz,'*.jpg');
GetEncoderClsid('image/jpeg', EncoderCLSID);
For i := 0 to High(DatListe) do begin
GPImage := TGPImage.Create(DatListe[i]);
GPImage.RotateFlip(Rotate90FlipNone);
TempDatname := TPath.ChangeExtension(DatListe[i],'$$$');
Ergebnis := GPImage.Save(TempDatname,EncoderCLSID);
GPImage.Free;
If Ergebnis = Ok then begin
If DeleteFile(DatListe[i])
then RenameFile(TempDatname,DatListe[i])
else DeleteFile(TempDatname);
end;
end;
end;
Die nachfolgende Version ist die "volle". An ihr ist besonders interessant, dass sie nicht nur selbständig ermittelt, ob das JPG überhaupt gedreht werden muss, sondern auch den Zugriff auf weitere
GDI-Funktionen bietet. Auch kann außer dem PropertyTagOrientation noch eine Vielzahl von weiteren EXIF-Markern ausgelesen werden.
Delphi-Quellcode:
uses ... GDIPAPI, GDIPOBJ,GDIPUTIL;
procedure DreheMitGDIPlus2;
Var i:integer;
DatListe:TStringDynArray;
GPImage: TGPImage;
PPropItem: PPropertyItem;
BufferSize: Cardinal;
Orientation: Byte;
RotateBy: EncoderValue;
EncoderCLSID: TGUID;
EncoderParams: TEncoderParameters;
EncoderTransformValue:integer;
Ergebnis : Status;
TempDatname:string;
const
Verz = 'C:\Test\';
begin
DatListe := TDirectory.GetFiles(Verz,'*.jpg');
GetEncoderClsid('image/jpeg', EncoderCLSID);
FillChar(EncoderParams, SizeOf(EncoderParams), 0);
EncoderParams.Count := 1;
EncoderParams.Parameter[0].Guid := EncoderTransformation;
EncoderParams.Parameter[0].Type_ := EncoderParameterValueTypeLong;
EncoderParams.Parameter[0].NumberOfValues := 1;
For i := 0 to High(DatListe) do begin
GPImage := TGPImage.Create(DatListe[i]);
BufferSize := GPImage.GetPropertyItemSize(PropertyTagOrientation);
If BufferSize > 0 then begin
GetMem(PPropItem, BufferSize);
Try
GPImage.GetPropertyItem(PropertyTagOrientation, BufferSize, PPropItem);
Orientation := PByte(PPropItem.value)^;
case Orientation of
3: RotateBy := EncoderValueTransformRotate180;
6: RotateBy := EncoderValueTransformRotate90;
8: RotateBy := EncoderValueTransformRotate270;
else Continue;
end;
If (Orientation in [3,6,9]) then begin
EncoderTransformValue := Ord(RotateBy);
EncoderParams.Parameter[0].Value := @EncoderTransformValue;
TempDatname := TPath.ChangeExtension(DatListe[i],'$$$');
Ergebnis := GPImage.Save(WideString(TempDatname),EncoderCLSID,@EncoderParams);
GPImage.Free;
If Ergebnis = Ok then begin
If DeleteFile(DatListe[i])
then RenameFile(TempDatname,DatListe[i])
else DeleteFile(TempDatname);
end;
end;
Finally
FreeMem(PPropItem);
end;
end;
end;
end;