Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi bitmap um ein vielfaches von 90 drehen (https://www.delphipraxis.net/2264-bitmap-um-ein-vielfaches-von-90-drehen.html)

nebukadnezzar 15. Jan 2003 11:57


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)

illegal eagle 15. Jan 2003 20:52

Hi!

Für 180° (oben nach unten umdrehen) sollte folgender Code gehen: (nicht getestet)

Delphi-Quellcode:
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 90° und 270° mußt du ein neues (temporäres) Bitmap erstellen, weil sich ja wahrscheinlich die Abmessungen ändern werden.

Sebastian Nintemann 15. Jan 2003 22:10

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

illegal eagle 16. Jan 2003 10:29

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.

nebukadnezzar 16. Jan 2003 16:29

aus dem obigen vorgeschlagenen Code hab ich folgendes gemacht:
Delphi-Quellcode:
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 verbesserungen hab ich immer ein offenes ohr
für 1 und 4 bittige bilder funzt das nicht deswegen wird dann auf 16bit gezwungwn (weil dann 0 < pixsize <1 )

illegal eagle 16. Jan 2003 18:12

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.

nebukadnezzar 16. Jan 2003 19:15

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

illegal eagle 20. Jan 2003 15:08

Wenn's dir zu langsam ist, dann nimm doch den Code vom efg Lab.
Besonders Unit7 sollte man mal ausprobieren.

nebukadnezzar 20. Jan 2003 16:41

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 15:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf