![]() |
Re: Transparentes PNG in TImage drehen...Wie?
Zitat:
Sorry, wenn ich mich vielleicht etwas blöd anstelle, aber wie übergebe ich denn der Routine SmoothRotate das pnpObjekt aus dem TImage? Ansonsten bin ich mir sehr sicher, dass das genau das Richtige ist... Und um es vielleicht noch kurz erklären, warum ich PNG in einem TImage verwende. Ich erstelle Pläne auf einem Form. Auf diesen Plänen sind diverse TImages, die der User frei hinzufügen und bewegen kann (TImages mit geladenen PNG´s). Nun will/muss ich aber für bestimmte Bilder einfach anbieten, dass man die Bilder vor dem Hinzufügen über einen Dialog noch drehen kann. Wenn das funktioniert, will ich dann auch noch nachträglich, die einem Plan hinzugefügten Bilder drehen lassen... |
Re: Transparentes PNG in TImage drehen...Wie?
Zitat:
Ein TImage kann diese Informationen nicht speichern. Nach dem Laden ist der Alpha-Kanal weg. Oder??? bzw. Das Image in Deinem Beispiel kann eine PNG Datei nicht laden... Daher gehe ich davon aus, dass Du eine andere Komponente hast... Frank :coder: |
Re: Transparentes PNG in TImage drehen...Wie?
Zitat:
TImage kann über die Filter (z.B. pngdelphi) auch mit PNG Dateien umgehen. Da das TImage ja auch wissen muß wie es gezeichnet wird müssen die Infos ja irgendwo da drin sein :mrgreen: Also:
In der Delphi Onlinehilfe steht: Graphic (Eigenschaft von TPicture) Die Eigenschaft Graphic gibt die im TPicture-Objekt enthaltene Grafik an.
Delphi-Quellcode:
Beschreibung
property Graphic: TGraphic;
Mit Graphic legen Sie den Grafiktyp fest, die das TPicture-Objekt enthält. Ein TPicture-Objekt kann Grafiken des Typs Bitmap, Symbol, Metadatei oder benutzerdefinierte Grafikklassen enthalten. Folgender Code sollte Dein Problem lösen: (gibt aber Fehler, wenn Im TImage kein Bild geladen ist, das sollte mit Assigned() noch abgefangen werden.)
Delphi-Quellcode:
Viel Spaß
procedure TForm1.BitBtn1Click(Sender: TObject);
var x: TPNGObject; begin // Ist da überhaupt ein PNG drin? if Image1.Picture.Graphic is TPngObject then begin // TPngObject(Image1.Picture.Graphic) ist ein konstanter Ausdruck // und kann nicht als Var Parameter übergeben werden, deshalb // Der Umweg über x ;-) x := Image1.Picture.Graphic as TPngObject; SmoothRotate(x, 20); end; end; MaBuSE |
Re: Transparentes PNG in TImage drehen...Wie?
Danke für die Hinweise und die Codes. Das hat mir wirklich SEHR weitergeholfen. Ich bin nun an dem Punkt, wo ich sagen kann, dass es grundsätzlich funktioniert, ABER, der Bildinhalt wird jedes mal verkleinert. Irgednwo ist da noch ein kleiner Fehler drin.
Delphi-Quellcode:
Ich habe die Routine nur um das Repaint erweitert. Das Assingment prüfe ich noch...Die Position kommt derzeit von einer Scrollbar.
procedure Tobjects.ScrollBar1Change(Sender: TObject);
var x: TPNGObject; begin // Ist da überhaupt ein PNG drin? if img_obj_prev.Picture.Graphic is TPngObject then begin // TPngObject(Image1.Picture.Graphic) ist ein konstanter Ausdruck // und kann nicht als Var Parameter übergeben werden, deshalb // Der Umweg über x ;-) x := img_obj_prev.Picture.Graphic as TPngObject; SmoothRotate(x, ScrollBar1.Position); img_obj_prev.Repaint; end; end; |
Re: Transparentes PNG in TImage drehen...Wie?
Zitat:
Ich hoffe Du verstehst was ich meine. ;-) [edit] Beispiel: Bild mit 20 x 10 Pixel wird um 90° gedreht es hat dann 10 x 20 Pixel. Wenn die Höhe des TImage jetzt immer noch 10 Pixel hat, wird das Bild um Faktor 2 verkleinert. Es ist nur noch halb so groß. [/edit] |
Re: Transparentes PNG in TImage drehen...Wie?
Liste der Anhänge anzeigen (Anzahl: 1)
Ok, ich habe mal wieder das Beispielprojekt angepasst und es dreht sich nur, was sich drehen soll, ABER die Qualität ist leider inakzeptabel und auch die Geschwindigkeit der Berechnung wird von mal zu mal langsamer. Desweiteren habe ich ja im Projekt als Beispiel zum Drehen eine Scrollbar genommen, womit ich dem User anbieten will, dass er das Bild von 1° auf 360° drehen kann. Das stimmt leider auch nicht ganz, denn mir scheint, als würde der Drehwinkel jedes mal grösser werden.
Mach ich da nun wieder was falsch? :roll: |
Re: Transparentes PNG in TImage drehen...Wie?
Zitat:
Aber ich habe eine Vermutung. Das Rotate macht wohl ein Anialiasing. Zitat:
Mein Vorschlag. Leg vor dem Drehen eine "Kopie" des PNG Bildes an. Drehe dann ein temp. Bild der Kopie und weise es danach der TImage Komponente zu. Ich mach mal ein Beisp. ;-) |
Re: Transparentes PNG in TImage drehen...Wie?
guter vorschlag! darauf hätte ich eigentlich auch selbst kommen müssen. wie kann ich es noch händeln, dass der rechner nicht so lange zu rechnen braucht, wenn ein user auf der scrollbar einen der beiden buttons permanent gedrückt hält? mit einer boolschen variable IsRunning, und wenn die noch true ist, einfach die aktion NICHT ausführen. macht das sinn?
|
Re: Transparentes PNG in TImage drehen...Wie?
Vergesst alles ab Guten Morgen. Es funzt nun - Jippi. Ich habe es erstmal "polnisch" gelöst, indem ich einfach nur ein unsichtbares TImage auf das Formular gelegt habe und den Code nur dahingehend geändert habe.
Delphi-Quellcode:
Und was soll ich sagen? Es ist wirklich ganz ok! Ich glaube, dass ich damit nun was anfangen kann...Danke an alle, die mitgeholfen haben.
procedure TForm1.ScrollBar1Change(Sender: TObject);
var x,y: TPNGObject; begin // Ist da überhaupt ein PNG drin? if img_src.Picture.Graphic is TPngObject then begin // TPngObject(Image1.Picture.Graphic) ist ein konstanter Ausdruck // und kann nicht als Var Parameter übergeben werden, deshalb // Der Umweg über x ;-) img_dest.Picture.Graphic.Assign(img_src.Picture.Graphic); x := img_dest.Picture.Graphic as TPngObject; SmoothRotate(x, ScrollBar1.Position); img_dest.Repaint; end; end; |
Re: Transparentes PNG in TImage drehen...Wie?
Ok, eine kleine Frage habe ich dann trotzdem noch, weil mich das Grössenproblem des Images doch noch beschäftigt. Ich eröffne dazu auch gern einen neuen Thread, aber ich bin froh, dass ich hier schon Hilfe gefunden habe und indirekt hängt es ja mit den mir zur Verfügung gestellten Sourcen zusammen.
So wie ich das Drehen des Bildes verstehe, wird das Bild in den gegebenen Bildgrössen gedreht. Somit können die Bildinhalte auch mal kleiner und auch grösser werden. Mir wäre es aber lieber, wenn das Bild nur gedreht werden würde und die Ausmasse des Bildes sich ändern würden. Damit wäre das zu drehende Bildobjekt für den User immer in der gleichen Grösse. In Photoshop ist das auch möglich... Wie könnte ich dass mit der vorhandenen Routine umsetzen? Mir ist schon klar, was ich verlange, aber ich dachte mir, dass es vielleicht reichen könnte, wenn man die in der Routine implementierte Funktion zur Grössenberechnung abklemmt oder umschreibt....Leider sind meine mathematischen Kenntnisse diesbezüglich eher mager... :(
Delphi-Quellcode:
procedure SmoothRotate(var aPng: TPNGObject; Angle: Extended);
{Supporting functions} function TrimInt(i, Min, Max: Integer): Integer; begin if i>Max then Result:=Max else if i<Min then Result:=Min else Result:=i; end; function IntToByte(i:Integer):Byte; begin if i>255 then Result:=255 else if i<0 then Result:=0 else Result:=i; end; function Min(A, B: Double): Double; begin if A < B then Result := A else Result := B; end; function Max(A, B: Double): Double; begin if A > B then Result := A else Result := B; end; function Ceil(A: Double): Integer; begin Result := Integer(Trunc(A)); if Frac(A) > 0 then Inc(Result); end; {Calculates the png new size} function newsize: tsize; var fRadians: Extended; fCosine, fSine: Double; fPoint1x, fPoint1y, fPoint2x, fPoint2y, fPoint3x, fPoint3y: Double; fMinx, fMiny, fMaxx, fMaxy: Double; begin {Convert degrees to radians} fRadians := (2 * PI * Angle) / 360; fCosine := abs(cos(fRadians)); fSine := abs(sin(fRadians)); fPoint1x := (-apng.Height * fSine); fPoint1y := (apng.Height * fCosine); fPoint2x := (apng.Width * fCosine - apng.Height * fSine); fPoint2y := (apng.Height * fCosine + apng.Width * fSine); fPoint3x := (apng.Width * fCosine); fPoint3y := (apng.Width * fSine); fMinx := min(0,min(fPoint1x,min(fPoint2x,fPoint3x))); fMiny := min(0,min(fPoint1y,min(fPoint2y,fPoint3y))); fMaxx := max(fPoint1x,max(fPoint2x,fPoint3x)); fMaxy := max(fPoint1y,max(fPoint2y,fPoint3y)); Result.cx := ceil(fMaxx-fMinx); Result.cy := ceil(fMaxy-fMiny); end; type TFColor = record b,g,r:Byte end; var Top, Bottom, Left, Right, eww,nsw, fx,fy, wx,wy: Extended; cAngle, sAngle: Double; xDiff, yDiff, ifx,ify, px,py, ix,iy, x,y, cx, cy: Integer; nw,ne, sw,se: TFColor; anw,ane, asw,ase: Byte; P1,P2,P3:Pbytearray; A1,A2,A3: pbytearray; dst: TPNGObject; IsAlpha: Boolean; new_colortype: Integer; begin {Only allows RGB and RGBALPHA images} if not (apng.Header.ColorType in [COLOR_RGBALPHA, COLOR_RGB]) then raise Exception.Create('Only COLOR_RGBALPHA and COLOR_RGB formats' + ' are supported'); IsAlpha := apng.Header.ColorType in [COLOR_RGBALPHA]; if IsAlpha then new_colortype := COLOR_RGBALPHA else new_colortype := COLOR_RGB; {Creates a copy} dst := tpngobject.Create; with newsize do dst.createblank(new_colortype, 8, cx, cy); cx := dst.width div 2; cy := dst.height div 2; {Gather some variables} Angle:=angle; Angle:=-Angle*Pi/180; sAngle:=Sin(Angle); cAngle:=Cos(Angle); xDiff:=(Dst.Width-apng.Width)div 2; yDiff:=(Dst.Height-apng.Height)div 2; {Iterates over each line} for y:=0 to Dst.Height-1 do begin P3:=Dst.scanline[y]; if IsAlpha then A3 := Dst.AlphaScanline[y]; py:=2*(y-cy)+1; {Iterates over each column} for x:=0 to Dst.Width-1 do begin px:=2*(x-cx)+1; fx:=(((px*cAngle-py*sAngle)-1)/ 2+cx)-xDiff; fy:=(((px*sAngle+py*cAngle)-1)/ 2+cy)-yDiff; ifx:=Round(fx); ify:=Round(fy); {Only continues if it does not exceed image boundaries} if(ifx>-1)and(ifx<apng.Width)and(ify>-1)and(ify<apng.Height)then begin {Obtains data to paint the new pixel} eww:=fx-ifx; nsw:=fy-ify; iy:=TrimInt(ify+1,0,apng.Height-1); ix:=TrimInt(ifx+1,0,apng.Width-1); P1:=apng.scanline[ify]; P2:=apng.scanline[iy]; if IsAlpha then A1 := apng.alphascanline[ify]; if IsAlpha then A2 := apng.alphascanline[iy]; nw.r:=P1[ifx*3]; nw.g:=P1[ifx*3+1]; nw.b:=P1[ifx*3+2]; if IsAlpha then anw:=A1[ifx]; ne.r:=P1[ix*3]; ne.g:=P1[ix*3+1]; ne.b:=P1[ix*3+2]; if IsAlpha then ane:=A1[ix]; sw.r:=P2[ifx*3]; sw.g:=P2[ifx*3+1]; sw.b:=P2[ifx*3+2]; if IsAlpha then asw:=A2[ifx]; se.r:=P2[ix*3]; se.g:=P2[ix*3+1]; se.b:=P2[ix*3+2]; if IsAlpha then ase:=A2[ix]; {Defines the new pixel} Top:=nw.b+eww*(ne.b-nw.b); Bottom:=sw.b+eww*(se.b-sw.b); P3[x*3+2]:=IntToByte(Round(Top+nsw*(Bottom-Top))); Top:=nw.g+eww*(ne.g-nw.g); Bottom:=sw.g+eww*(se.g-sw.g); P3[x*3+1]:=IntToByte(Round(Top+nsw*(Bottom-Top))); Top:=nw.r+eww*(ne.r-nw.r); Bottom:=sw.r+eww*(se.r-sw.r); P3[x*3]:=IntToByte(Round(Top+nsw*(Bottom-Top))); {Only for alpha} if IsAlpha then begin Top:=anw+eww*(ane-anw); Bottom:=asw+eww*(ase-asw); A3[x]:=IntToByte(Round(Top+nsw*(Bottom-Top))); end; end; end; end; apng.assign(dst); dst.free; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:26 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