AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Transparentes PNG in TImage drehen...Wie?
Thema durchsuchen
Ansicht
Themen-Optionen

Transparentes PNG in TImage drehen...Wie?

Offene Frage von "Fabian W."
Ein Thema von torud · begonnen am 24. Nov 2006 · letzter Beitrag vom 26. Okt 2008
Antwort Antwort
Seite 2 von 3     12 3      
torud

Registriert seit: 26. Jul 2002
Ort: Sachsen
1.198 Beiträge
 
Delphi XE5 Professional
 
#11

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 09:19
Zitat von MaBuSE:
Delphi-Quellcode:
{Smooth rotate a png object}
procedure SmoothRotate(var aPng: TPNGObject; Angle: Extended);
Damit kannst Du das PNG in dem TImage inkl. der Transparenz bzw Alpha Infos drehen.
@MaBuSE DANKE!!!

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...
Danke
Tom
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.130 Beiträge
 
Delphi 10.3 Rio
 
#12

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 10:27
Zitat von torud:
Und um es vielleicht noch kurz erklären, warum ich PNG in einem TImage verwende.
Genau ist das Problem - was ich so sehe - es sei den, Du hast eine andere PNG Komponente...

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
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#13

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 12:48
Zitat von Mavarik:
Ein TImage kann diese Informationen nicht speichern. Nach dem Laden ist der Alpha-Kanal weg. Oder???
Das ist nicht ganz richtig.

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

Also:
  • TImage hat eine Eigenschaft Picture
  • TPicture hat eine Eigenschaft Graphic
  • Graphic ist vom Typ TGraphic.
  • ABER je nach dem was das TImage beinhaltet steckt da ein Nachkomme von TGraphic drin, der das Bild und alle Informationen bereithält.
In unserem Fall ein TPNGObject.

In der Delphi Onlinehilfe steht:
Graphic (Eigenschaft von TPicture)
Die Eigenschaft Graphic gibt die im TPicture-Objekt enthaltene Grafik an.
property Graphic: TGraphic; Beschreibung
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:
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;
Viel Spaß
MaBuSE
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
torud

Registriert seit: 26. Jul 2002
Ort: Sachsen
1.198 Beiträge
 
Delphi XE5 Professional
 
#14

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 13:12
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:
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;
Ich habe die Routine nur um das Repaint erweitert. Das Assingment prüfe ich noch...Die Position kommt derzeit von einer Scrollbar.
Danke
Tom
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#15

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 13:37
Zitat von torud:
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.
Das liegt warscheinlich daran, dass wenn Du ein Rechteck drehst, das Bild (Rechteck) in das das Rechteck passen soll größer wird. Wenn Du nun die Größe des TImage gleich lässt und Stretch auf True ist, wird das Bild natürlich kleiner dargestellt.

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]
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
torud

Registriert seit: 26. Jul 2002
Ort: Sachsen
1.198 Beiträge
 
Delphi XE5 Professional
 
#16

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 15:11
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?
Angehängte Dateien
Dateityp: zip rotateimage_187.zip (14,9 KB, 43x aufgerufen)
Danke
Tom
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#17

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 15:23
Zitat von torud:
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.
Ich habe mir weder Dein Projekt, noch die Rocate Funktion im Detail angesehen bzw getestet.

Aber ich habe eine Vermutung.

Das Rotate macht wohl ein Anialiasing.
Zitat:
Use this method to rotate RGB and RGB Alpha 'Portable Network Graphics' Images using a smooth antialiased algorithm in order to get much better results.
Wenn Du das Bild nun in 1° Schritten drehst, wird es irgendwann unansehnlich.
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.
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
torud

Registriert seit: 26. Jul 2002
Ort: Sachsen
1.198 Beiträge
 
Delphi XE5 Professional
 
#18

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 15:33
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?
Danke
Tom
  Mit Zitat antworten Zitat
torud

Registriert seit: 26. Jul 2002
Ort: Sachsen
1.198 Beiträge
 
Delphi XE5 Professional
 
#19

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 16:07
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:
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;
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.
Danke
Tom
  Mit Zitat antworten Zitat
torud

Registriert seit: 26. Jul 2002
Ort: Sachsen
1.198 Beiträge
 
Delphi XE5 Professional
 
#20

Re: Transparentes PNG in TImage drehen...Wie?

  Alt 8. Dez 2006, 18:36
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;
Danke
Tom
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:26 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz