![]() |
bitmap um ein vielfaches von 90 drehen
ich möchte ein bitmap halt um 0,90,180,270 Grad drehen
das gedrehte image soll dirket auf ein canvas gemalt werden. das ganze sollte auch noch möglichst schnell gehen und mit den verschiedenen Pixelformaten klar kommen. nur wie geht das? (das fon efg's Labs versteh ich nicht) |
Hi!
Für 180° (oben nach unten umdrehen) sollte folgender Code gehen: (nicht getestet)
Delphi-Quellcode:
Für 90° und 270° mußt du ein neues (temporäres) Bitmap erstellen, weil sich ja wahrscheinlich die Abmessungen ändern werden.
Procedure Turn180(Bitmap : tBitmap);
Type tLine : Array[0..$FFFF] of Byte; Var LineWidth, y : Integer; Line : ^tLine; Begin LineWidth := Bitmap.Width; Case Bitmap.PixelFormat of pf1Bit : LineWidth := LineWidth SHR 3; pf4Bit : LineWidth := LineWidth SHR 1; pf16Bit : LineWidth := LineWidth SHL 1; pf24Bit : LineWidth := LineWidth * 3; pf32Bit : LineWidth := LineWidth SHL 2; End; GetMem(Line, LineWidth); For y := 0 to ((Bitmap.Height - 1) div 2) do Begin Move(Bitmap.ScanLine[Bitmap.Height - 1 - y]^, Line[0], LineWidth; Move(Bitmap.ScanLine[y]^, Bitmap.ScanLine[Bitmap.Height - 1 - y]^, LineWidth; Move(Line[0], Bitmap.ScanLine[y]^, LineWidth; End; FreeMem(Line, LineWidth); End; |
Für 180° kannst du dir auch mal StretchBlt angucken, damit gehts in einer Zeile. Für 90°/270° mal Mit Scanline rumexperimentieren, ist garnicht so einfach, aber zu schaffen. Mit den unterschiedlichen Pixelformaten ists mit Scanline natürlich auch nicht so ganz einfach, kannst du nicht vor dem bearbeiten auf pf24bit einstellen?
Gruß, Sebastian |
Sorry, der Code spiegelt das Bild nur, es muss noch von links nach rechts umgedreht werden.
Ich hoffe, du bekommst keine Abstürze wegen Scanline! Ist (wie gesagt) nicht getestet. |
aus dem obigen vorgeschlagenen Code hab ich folgendes gemacht:
Delphi-Quellcode:
für verbesserungen hab ich immer ein offenes ohr
Procedure Turn(bitmap,dest:tBitmap;a:integer);
Type tLine = Array[0..0] of Byte; pline = ^tLine; Var Linesize,Linesize2, y, x : Integer; Field,temp : pline; Pixsize : Longint; FieldSize : Longint; Begin if Bitmap.Pixelformat in [pf1Bit,pf4Bit] then Bitmap.PixelFormat:=pf16bit; Dest.PixelFormat:=Bitmap.PixelFormat; Case Bitmap.PixelFormat of pf16Bit : Pixsize:=2; pf24Bit : Pixsize:=3; pf32Bit : Pixsize:=8; End; Linesize:=Bitmap.width * Pixsize; FieldSize:=Linesize*Bitmap.Height; GetMem(Field, fieldSize); For y:=0 to Bitmap.height-1 do Move(Bitmap.ScanLine[y]^, Field[y*Linesize], LineSize); Case a of 0:BEgin Dest.Width:=Bitmap.Width; Dest.Height:=Bitmap.Height; Linesize2:=Pixsize*Dest.width; End; 90:BEgin Dest.Width:=Bitmap.Height; Dest.Height:=Bitmap.Width; Linesize2:=Pixsize*Dest.width; Getmem(temp,Fieldsize); For y:=0 to Bitmap.Height-1 do For x:=0 to Bitmap.width-1 do Begin Move(Field[(y)*Linesize + (x)*Pixsize],temp[(x)*Linesize2 + (bitmap.height -y -1)*Pixsize],Pixsize); End; Freemem(field,Fieldsize); Field:=temp; End; 180:Begin Dest.Width:=Bitmap.Width; Dest.Height:=Bitmap.Height; Linesize2:=Pixsize*Dest.width; Getmem(temp,Fieldsize); For y:=0 to Bitmap.Height-1 do For x:=0 to Bitmap.width-1 do Begin Move(Field[(Bitmap.height -y -1)*Linesize + (Bitmap.width - x -1)*Pixsize],temp[y*Linesize2 + x*Pixsize],Pixsize); End; Freemem(field,Fieldsize); Field:=temp; End; 270:BEgin Dest.Width:=Bitmap.Height; Dest.Height:=Bitmap.Width; Linesize2:=Pixsize*Dest.width; Getmem(temp,Fieldsize); For y:=0 to Bitmap.Height-1 do For x:=0 to Bitmap.width-1 do Begin Move(Field[(y)*Linesize + (x)*Pixsize],temp[(Bitmap.width - x -1)*Linesize2 + (y)*Pixsize],Pixsize); End; Freemem(field,Fieldsize); Field:=temp; End; End; For y:=0 to Dest.height-1 do Move(Field[y*Linesize2],Dest.ScanLine[y]^,Linesize2); Freemem(Field,Fieldsize); End; für 1 und 4 bittige bilder funzt das nicht deswegen wird dann auf 16bit gezwungwn (weil dann 0 < pixsize <1 ) |
Bei 32 Bits würde ich Pixsize nicht auf 8, sondern auf 4 setzen.
Und warum nimmst du Array[0..0] of Byte? Damit erhältst du doch einen Fehler, wenn du die Bereichsprüfung eingeschaltet lässt (mach ich immer so). Move(Field[(y)*Linesize + (x)*Pixsize],temp[(x)*Linesize2 + (bitmap.height -y -1)*Pixsize],Pixsize); scheint mir etwas komisch, Move(Field[((y * Linesize) + x) * Pixsize], temp[((x * Linesize2) + bitmap.height - y - 1) * Pixsize], Pixsize); sieht besser aus. |
Linesize is ja schon die anzahl der bytes und nicht die anzahl der pixel
(linesze:= width * pixelsize) das problem is nur das de Prozedur einfach VIIIIEEEEEELLLLL zu lange dauert |
|
hab ich schon längst und unit7 habe ich für meine zwecke vorerst als optimal lösung aus erkoren
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz