![]() |
Re: Grenzen von PlgBlt
Hab mal schnell was geschrieben:
Delphi-Quellcode:
Edit: Hoffe es ist einfach genug. :wink:
procedure Rotiere(ABitmap: TBitmap; ADirection: Integer);
{---} const PIXELCOUNT = 8; {---} function Rol(const AByte, APositions: Byte): Byte register; asm mov cl, dl rol al, cl end; {---} function Ror(const AByte, APositions: Byte): Byte register; asm mov cl, dl ror al, cl end; {---} function CalcByteCount(AWidth: Integer): Integer; begin Result := AWidth div PIXELCOUNT; if (AWidth mod PIXELCOUNT) > 0 then Inc(Result); end; {---} var y, x1, x2, yMax, i, xCount, yCount: Integer; p1, p2, buffer: ^Byte; v, m: Byte; begin {im Uhrzeigersinn drehen} if (ADirection = 90) or (ADirection = 180) or (ADirection = 270) then begin ABitmap.Pixelformat := pf1Bit; xCount := CalcByteCount(ABitmap.Width); yCount := CalcByteCount(ABitmap.Height); GetMem(buffer, xCount * yCount * PIXELCOUNT); try FillChar(buffer^, xCount * yCount * PIXELCOUNT, #0); yMax := ABitmap.Height - 1; if ADirection = 90 then begin m := 1 shl (PIXELCOUNT - 1); for y := yMax downto 0 do begin p1 := ABitmap.Scanline[y]; p2 := buffer; Inc(p2, (yMax - y) div PIXELCOUNT); for x1 := 0 to xCount - 1 do begin v := p1^; for x2 := 0 to PIXELCOUNT - 1 do begin v := Rol(v, 1); if Odd(v) then p2^ := p2^ or m; Inc(p2, yCount); end; Inc(p1, 1); end; m := Ror(m, 1); end; ABitmap.SetSize(ABitmap.Height, ABitmap.Width); p2 := buffer; end else if ADirection = 270 then begin m := 1 shl (PIXELCOUNT - 1); for y := 0 to yMax do begin p1 := ABitmap.Scanline[y]; Inc(P1, xCount - 1); p2 := buffer; Inc(p2, (y div PIXELCOUNT)); for x1 := 0 to xCount - 1 do begin v := p1^; for x2 := 0 to PIXELCOUNT - 1 do begin if Odd(v) then p2^ := p2^ or m; v := Ror(v, 1); Inc(p2, yCount); end; Dec(p1, 1); end; m := Ror(m, 1); end; ABitmap.SetSize(ABitmap.Height, ABitmap.Width); p2 := buffer; {Leerzeilen überspringen} Inc(p2, yCount * ((xCount * PixelCount) - ABitmap.Height)); end else if ADirection = 180 then begin p2 := buffer; i := (ABitmap.Width mod PIXELCOUNT); for y := yMax downto 0 do begin p1 := ABitmap.Scanline[y]; Inc(P1, xCount - 1); if i = 0 then v := 0 else begin v := p1^; Dec(p1); v := Rol(v, i); end; for x1 := 0 to xCount - 1 do begin m := 0; for x2 := 0 to i - 1 do begin m := Rol(m, 1); if Odd(v) then m := m or 1; v := Ror(v, 1); end; if (i > 0) and (x1 = (xCount - 1)) then v := 0 else begin v := p1^; Dec(P1); end; for x2 := i to PIXELCOUNT - 1 do begin m := Rol(m, 1); if Odd(v) then m := m or 1; v := Ror(v, 1); end; p2^ := m; Inc(p2); end; end; p2 := buffer; end else Exit; {Bitmap aus dem Buffer füllen} xCount := CalcByteCount(ABitmap.Width); for y := 0 to ABitmap.Height - 1 do begin p1 := ABitmap.Scanline[y]; Move(p2^, p1^, xCount); Inc(p2, xCount); end; finally FreeMem(Buffer); end; end; end; |
Re: Grenzen von PlgBlt
Zitat:
Ich habe nur gedacht, dass die Funktionen von GDI+ übersichtlich sind. Das sind sie wohl auch. Kürzer und einfacher als FlipBild.RotateFlip(Rotate90FlipNone); ist ja kaum vorstellbar. Aber wenn ich erhebliche Klimmzüge starten muss, um mein TBitmap in alle möglichen anderen Typen und wieder zurück zu verwandeln, dann ist es für mich nicht nutzbar. Ich wäre gern bei GDI+ geblieben bzw. erstmal dorthin gekommen, weil ich das Bild vor/nach dem Drehen noch strecken bzw. stauchen muss. Und dafür scheint es ja auch Einiges bereit zu halten ... Vielen herzlichen Dank sagt Alex |
Re: Grenzen von PlgBlt
Zitat:
Für mich war es etwas einfacher da es unter VB viele anleitungen und samples gibt von denen man lernen kann. In Delphi gibt es da fast so gut wie nichts. Was du am ende benutzt mußt du selbst wissen. Es soll ja funktionieren. ;) gruss Emil |
Re: Grenzen von PlgBlt
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Aber ich bin doch tatsächlich ein gutes Stück weiter. Mein Vorteil ist, dass ich die Bilder "nur" verarbeiten und dann speichern muss. Das Darstellen usw. ist für mich unwichtig. Und so ist es mir zwischenzeitlich gelungen, mein TBimap einem TGPBitmap zuzuweisen und nach anfägnlichen Schwierigkeiten auch zu speichern. Ich habe den Code als Archiv angehängt für Interessierte. Dazu habe ich eine Frage: 1. Mit der Funktion
Delphi-Quellcode:
sage ich - nach meinem Verständnis -, dass GDIPBitmap den Speicherbereich von Image1.Picture.Bitmap benutzen soll. Da aber Image1 den Speicher nicht freigibt, müssten die Operationen, die ich mache auch Image1 betreffen und evtl. sogar angezeigt werden. Wo liegt mein Missverständnis?
GDIPBitmap:=TGPBitmap.Create(Image1.Picture.Bitmap.Handle,
Image1.Picture.Bitmap.Palette); Gruß und Danke für die Vorschlage, Hilfen und Ermunterungen Alex |
Re: Grenzen von PlgBlt
Zitat:
Habs auch mit deiner großen Bitmap probiert. Was genau klappt den nicht, bzw. wie sieht das Ergebnis aus? |
AW: Re: Grenzen von PlgBlt
Hallo,
mit der Zeit werde auch ich schlauer und habe somit gelernt, wie man DLL-Funktionen einbinden kann :lol:. Ich habe jetzt in den Implementations-Teil meiner "Dreh-Unit" folgendes geschrieben:
Delphi-Quellcode:
Die Deklaration von RotateFlipType habe ich jetzt mal außen vor gelassen. Die Deklaration von GPStatus ist nicht auf meinem Mist gewachsen, sonder ich habe sie einfach aus der Unit GDIPAPI.pas von
Const
Status = (Ok, GenericError, InvalidParameter, OutOfMemory, ObjectBusy, InsufficientBuffer, NotImplemented, Win32Error, WrongState, Aborted, FileNotFound, ValueOverflow, AccessDenied, UnknownImageFormat, FontFamilyNotFound, FontStyleNotFound, NotTrueTypeFont, UnsupportedGdiplusVersion, GdiplusNotInitialized, PropertyNotFound, PropertyNotSupported); TStatus = Status; GpStatus = TStatus; Function GdipImageRotateFlip(Image: Pointer; rfType: ROTATEFLIPTYPE): GPSTATUS; Stdcall; External 'gdiplus.dll'; ![]() Und so sollte das dann von mir aufgerufen werden:
Delphi-Quellcode:
TImage.Picture.Bitmap.Handle ist doch vom Typ HBITMAP. Ist das eine anderes HBITMAP als es GDI+ benutzt?
Procedure TMainForm.BtnRotateClick(Sender: TObject);
Var Stat : GPStatus; tmp : HBitmap; Begin tmp:=Image1.Picture.Bitmap.Handle; Stat:=GdipImageRotateFlip(@tmp, Rotate90FlipNone); ShowMessage(StatusText[Stat]); End; Denn ich bekomme immer die Statusmeldung "ObjectBusy" zurück. Erwartet hatte ich eigentlich "GdiplusNotInitialized", weil ich genau das nicht getan habe; Initialisieren. Könnte mir bei der Gelegenheit bitte mal jemand ein Beispiel posten, wie ich mit den Funktionen "GdipCreateBitmapFromHBITMAP" bzw. "GdipCreateHBITMAPFromBitmap" ein TBitmap aus Delphi in ein GDI+-konformes HBITMAP umwandeln kann und umgekehrt? Mehr als das und "GdipImageRotateFlip" brauche ich vermutlich wirklich nicht, so dass mein Code übersichtlich und mein Programm schön klein bliebe! Bitte, bitte, Alex |
AW: Re: Grenzen von PlgBlt
Der "falsche" Fehlercode kommt wohl daher, dass ich GDI+ nicht initialisiert hatte. Jetzt klappt es mit dem Erzeugen durch
Delphi-Quellcode:
. Der Status passt und der Pointer auf das Image ist nicht mehr
GdipCreateBitmapFromHBITMAP()
Delphi-Quellcode:
.
nil
Allerdings erhalt ich nun beim Aufruf von
Delphi-Quellcode:
als Status-Rückmeldung
GdipImageRotateFlip
Delphi-Quellcode:
wobei folgendes definiert ist:
InvalidParameter
Delphi-Quellcode:
Auch das stammt nicht von mir, sondern ist ein Ausschnitt aus der von mir bereits zitierten Unit.
Type
RotateFlipType= (RotateNoneFlipNone = 0, Rotate90FlipNone = 1, Rotate180FlipNone = 2, Rotate270FlipNone = 3, RotateNoneFlipX = 4, Rotate90FlipX = 5, Rotate180FlipX = 6, Rotate270FlipX = 7, RotateNoneFlipY = Rotate180FlipX, Rotate90FlipY = Rotate270FlipX, Rotate180FlipY = RotateNoneFlipX, Rotate270FlipY = Rotate90FlipX, RotateNoneFlipXY = Rotate180FlipNone, Rotate90FlipXY = Rotate270FlipNone, Rotate180FlipXY = RotateNoneFlipNone, Rotate270FlipXY = Rotate90FlipNone); Status = (Ok, GenericError, InvalidParameter, OutOfMemory, ObjectBusy, InsufficientBuffer, NotImplemented, Win32Error, WrongState, Aborted, FileNotFound, ValueOverflow, AccessDenied, UnknownImageFormat, FontFamilyNotFound, FontStyleNotFound, NotTrueTypeFont, UnsupportedGdiplusVersion, GdiplusNotInitialized, PropertyNotFound, PropertyNotSupported); TStatus = Status; GpStatus = TStatus; Was mache ich denn nun wieder falsch? Mein Ziel ist es nachwievor, einfach nur ein TBitmap herzunehmen, in ein GDI+Bild umzuwandeln, dieses zu drehen und dann wieder in ein TBitmap zurückzuwandeln. |
AW: Re: Grenzen von PlgBlt
Ich antworte nun mal selbst:
ich habe es mit den Funktionen hinbekommen. Offenbar gelten die Grenzen von
Delphi-Quellcode:
bedauerlicher Weise auch für
PlgBlt()
Delphi-Quellcode:
. Die Ursache für die Speicherzugriffsverletzungen und sonstigen Fehlermeldungen war schlicht die, dass mein Test-Bild zu groß ist. Benutze ich ein kleineres Bild, dann klappt das ganze prima.
GdipImageRotateFlip()
Es gibt bloß ein Speicherleck, dass ich mit FastMM nicht eingrenzen kann. Bei jedem Drehen, braucht das Programm mehr Speicher und FastMM zeigt beim Beenden rein garnichts an. Ich habe sogar schon Speicherlecks provoziert, die gezeigt werden. Aber der andere Verbrauch ist unergründlich. Da ich also die API von Windows wohl vergessen kann, muss ich mir jetzt überlegen, wie ich ![]() Gruß, Alex |
AW: Grenzen von PlgBlt
Ich nutze GID+ sehr ausgiebig, allerdings mit Streams und Painroutinen, falls Du schnelle und einfache Canvasroutinen brauchen solltest, kann du ja hie mal bohren und erweitern:
Delphi-Quellcode:
unit ExCanvasTools;
// 20100915 by Thomas Wassermann interface uses Windows, SysUtils, Classes, Graphics; Function Grad2Rad(w:Double):Double; Procedure PaintGraphic(ACanvas:TCanvas;x,y:Integer;AGraphic:TGraphic;Faktor,Winkel:Double;PosIsCenter:Boolean=false); Procedure PaintText(ACanvas:TCanvas;Const s:String;x,y:Integer;Faktor,Winkel:Double;PosIsCenter:Boolean=false); Procedure ResetCanvas(ACanvas:TCanvas); procedure SetCanvasZoomAndRotation(ACanvas: TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double); implementation Function Grad2Rad(w:Double):Double; begin Result := w / 360 * PI *2; end; Procedure PaintText(ACanvas:TCanvas;Const s:String;x,y:Integer;Faktor,Winkel:Double;PosIsCenter:Boolean=false); var px,py:Integer; begin SetCanvasZoomAndRotation(ACanvas , Faktor, Winkel, x,y); if PosIsCenter then begin px := Round( ACanvas.TextWidth(s) / 2 ); py := Round( ACanvas.TextHeight(s) / 2 ); end else begin px := 0; py := 0; end; ACanvas.TextOut(-px ,-py ,s); ResetCanvas(ACanvas); end; Procedure PaintGraphic(ACanvas:TCanvas;x,y:Integer;AGraphic:TGraphic;Faktor,Winkel:Double;PosIsCenter:Boolean=false); var px,py:Integer; begin if PosIsCenter then begin px := Round( AGraphic.Width / 2 ); py := Round( AGraphic.Height / 2 ); end else begin px := 0; py := 0; end; SetCanvasZoomAndRotation(ACanvas , Faktor, Winkel, x , y ); ACanvas.Draw(-px ,-py ,AGraphic); ResetCanvas(ACanvas); end; Procedure ResetCanvas(ACanvas:TCanvas); begin SetCanvasZoomAndRotation(ACanvas , 1, 0, 0,0); end; Procedure SetCanvasZoomAndRotation(ACanvas:TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double); var form : tagXFORM; Winkel:Double; begin Winkel := Grad2Rad(Angle); SetGraphicsMode(ACanvas.Handle, GM_ADVANCED); SetMapMode(ACanvas.Handle,MM_ANISOTROPIC); form.eM11 := Zoom * cos( Winkel); form.eM12 := Zoom *Sin( Winkel) ; form.eM21 := Zoom * (-sin( Winkel)); form.eM22 := Zoom * cos( Winkel) ; form.eDx := CenterpointX; form.eDy := CenterpointY; SetWorldTransform(ACanvas.Handle,form); end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:49 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