Dieses Thema gibt es schon des öfteren hier und auch entsprechende ("langsamere") Lösungen. Allerdings soll das ganze in einem zeitkritischen Prozess ablaufen, weshalb ich nach vielfachen Tests bei
diesem Code gelandet bin, der für mich schnell genug ist.
Ich möchte das ganze zu einer Funktion zusammenfassen. Aber irgendwie stelle ich mich bei der 180°-Drehung zu blöd an. Ich erhalte bei der Ausführung immer nur Datenmüll. Ich probiere jetzt schon eine Ewigkeit rum und finde meinen Fehler nicht:
Delphi-Quellcode:
// Rotiert das angegebene Bitmap in 90°-Schritten ------------------------------
Type
TRotateDir = (rdLeft = 0, rdRight, rdUpturn);
Procedure RotateBitmap(
Const Bitmap: TBitmap;
Const RotateDir: TRotateDir = rdLeft);
Type
TRGBArray =
Array [0..0]
Of TRGBTriple;
pRGBArray = ^TRGBArray;
THelpRGB =
Packed Record
rgb : TRGBTriple;
alpha : Byte;
End;
Var
oldPF : TPixelFormat;
header : TBitmapInfo;
dc : hDC;
P :^THelpRGB;
H, W : Integer;
I, J : Integer;
RowOut : pRGBArray;
Begin
oldPF:=Bitmap.PixelFormat;
With TMemoryStream.Create
Do
Try
SetSize(Bitmap.Height * Bitmap.Width * 4);
Bitmap.PixelFormat:=pf24bit;
With header.bmiHeader
Do
Begin
biSize:= SizeOf(TBITMAPINFOHEADER);
biWidth:= Bitmap.Width;
biHeight:= Bitmap.Height;
biPlanes:= 1;
biBitCount:= 32;
biCompression:= 0;
biSizeimage:= Size;
biXPelsPerMeter:=1;
biYPelsPerMeter:=1;
biClrUsed:= 0;
biClrImportant:= 0;
End;
dc:=GetDC(0);
P:=Memory;
GetDIBits(
dc, Bitmap.Handle, 0, Bitmap.Height, P, header, dib_RGB_Colors);
ReleaseDC(0,
dc);
H:=Bitmap.Height; W:=Bitmap.Width;
// Werte merken
If (RotateDir <> rdUpturn)
Then // Falls kein 180° gewünscht
Begin
Bitmap.Width:= H; Bitmap.Height:=W;
// um 90° drehen
End;
Case RotateDir
of
rdLeft :
For J:=0
To Pred(W)
Do
Begin
rowOut:=Bitmap.ScanLine[Pred(W) - J];
P:=Memory;
// reset pointer
Inc(P, J);
For I:=Pred(H)
Downto 0
Do
Begin
rowout[I]:=p^.rgb;
Inc(P, W);
End;
End;
rdRight :
For J:=0
To Pred(W)
Do
Begin
rowOut:=Bitmap.ScanLine[J];
P:=Memory;
// reset pointer
Inc(P, J);
For I:=0
To Pred(H)
Do
Begin
rowout[I]:=p^.rgb;
Inc(P, W);
End;
End;
rdUpturn :
For J:=0
To Pred(H)
Do // <- funktioniert leider nicht :-(
Begin
rowOut:=Bitmap.ScanLine[Pred(H) - J];
P:=Memory;
// reset pointer
Inc(P, J);
For I:=Pred(W)
Downto 0
Do
Begin
rowOut[I]:=p^.rgb;
Inc(P, H);
End;
End;
End;
Finally
Free;
End;
Bitmap.PixelFormat:=oldPF;
End;
Ich bin mir (fast) sicher, dass es nur eine Kleinigkeit ist. Nachdem ich aber jetzt schon 3h an der Sache tüfftle, sehe ich so langsam den Wald vor lauter Bäumen nicht mehr.
Wo liegt mein Fehler?