Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Einmal im Leben ein "richtiges" PNG-Bild erstellen (https://www.delphipraxis.net/191126-einmal-im-leben-ein-richtiges-png-bild-erstellen.html)

geesmith 11. Dez 2016 20:44

Einmal im Leben ein "richtiges" PNG-Bild erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi zusammen

Über PNG und dergleichen lässt sich ja so richtig viel finden. Auch hier im Forum wurde schon viel darüber geschrieben. Eines konnte ich jedoch nie klären und aus aktuellem Projektanlass beschäftigt es mich nun wieder. Ich bin kein Grafikexperte, daher seid etwas nachsichtig :).

Es geht darum, ein PNG-File mit Transparenz zu speichern. Das funktioniert ganz gut (bmp.TransparentColor, bmp.TransparentMode, bmp.Transparent). Ich habe in meinem Delphi-Beispiel ein Bild mit TransparentColor = clWhite gespeichert. Laden und mit Draw in ein bestehendes Bild zeichnen kann ich mein Transparentes PNG ebenso.

Aber wenn ich mein PNG-File mit Photoshop über ein anderes Bild legen will, dann habe ich Probleme. Ich zeige im angehängten Screenshot in Photoshop den Vergleich zu einem "richtigen" PNG-File. Das "Richtige" (die Bombe) wird mit dem Transparenz-Muster und in der Ebenenübersicht als "Ebene" angezeigt. Mein gespeichertes PNG-File wird mit der Farbe Weiss im Hintergrund und in der Ebenenübersicht als "Hintergrund" angezeigt. Also irgendwas ist da anders.

Was als Folge davon auch mühsam ist, dass wenn ich so ein "falsches" PNG in Delphi lade und mit Draw irgendwo hinzeiche, ich die jeweilige "Transparenzfarbe" dem Image fix angeben muss. Bei dem "richtigen PNG kann ich das Ding einfach laden und reinzeichnen und fertig.

Daher meine Frage.. wie kriege ich so ein "richties" PNG-File in Delphi hin?

Meine Darstellung und Beschreibung habe ich bewusst etwas naiv erscheinen lassen. :wink:

Vielen Dank für eure Hilfe
Gee

Neutral General 11. Dez 2016 21:08

AW: Einmal im Leben ein "richtiges" PNG-Bild erstellen
 
Du musst ein PNGImage benutzen. Das hat glaube ich irgendwas wie Transparenz-Scanline oder sowas.
Damit kann man die Transparenz richtig setzen.

Namenloser 11. Dez 2016 21:41

AW: Einmal im Leben ein "richtiges" PNG-Bild erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Habe mal meine Unit angehängt, die ich lange Zeit verwendet habe, um PNGs zu laden und zu speichern (benötigt Graphics32). Die ursprüngliche Version des Quelltextes hatte ich mal irgendwo gefunden (weiß leider nicht mehr wo) und dann über die Jahre etwas erweitert und ein paar Bugs gefixt und Freepascal-Support hinzugefügt. Disclaimer: Ich habe immer alles nur soweit implementiert wie ich es selber brauchte. Deshalb keine Garantie auf Korrektheit oder Vollständigkeit.

Es scheint inzwischen aber auch neuere Versionen (Forks?) der ursprünglichen Unit zu geben, die anscheinend mehr können als meine, z.B. hier. Ich hoffe mal, die funktionieren auch korrekt. Ich weiß nur noch, dass die ursprüngliche Version bei manchen Dateien irgendein Problem mit dem Alphakanal hatte, was sich darin äußerte, dass die Ränder immer etwas "ausgefranst" waren, was sich beim mehrfachen Lesen und Speichern glaube ich auch noch verschlimmerte. Das habe ich dann irgendwann mal gefixt. Ich hoffe ich habe die richtige Version erwischt, die den Fix auch enthält.

geesmith 13. Dez 2016 09:23

AW: Einmal im Leben ein "richtiges" PNG-Bild erstellen
 
Danke für euren Input.

Ich habe beide Anregungen verfolgt und versucht ein Beispiel zu generieren.

Leider ohne Erfolg. Das mit der Transparenz-Scanline hat mich nicht weitergebracht. Hast du ein Beispiel?

Da ich mit Berlin-Standard arbeite, hat mich das GR32-Beispiel schlussendlich nicht weiter gebracht. Zwar gab es hier vielversprechende Ansätze wie "Header.ColorType" etc, aber das erzeugt Fehlermeldungen. PixelPtr gibt es bei TBitmap auch nicht. Ich konnte hier leider kein lauffähiges Beispiel mit Standard-Delphi Komponenten erzeugen.

Fazit... ich kann weiterhin nur PNG-Dateien erzeugen welche sich gleich wie im meinem Screenshot oben verhalten. Was vielleicht noch spannend ist, dass Gimp in meinem erzeugten PNGFile die Transparenzfläche anzeigen kann. Nur Photoshop zeigt das anders an. Also die PNG ist irgendwie doch anders als eine PNG-Datei wie ich sie von irgendwoher downloaden kann.

Das ist nach wie vor meine einzige lauffähige Möglichkeit ein PNG zu erstellen. Hat noch jemand ein anderes Beispiel?
Code:
procedure TForm1.Button1Click(Sender: TObject);
var png:TPngObject;
  bmp:TBitmap;
begin
  bmp := TBitmap.Create;
  png := TPngObject.Create;

  bmp.SetSize(100,100);

  With bmp.Canvas do
  begin
    Pen.Width := 5;
    Pen.Color := clRed;
    Rectangle(10,10,30,30);
    TextOut(5,5,'Test1');
  end;

  bmp.TransparentColor := clWhite;
  bmp.TransparentMode := tmFixed;
  bmp.Transparent := True;

  png.Assign(bmp);
  png.SaveToFile('C:\temp\'+outputfilename+'.png');

  png.Free;
  bmp.Free;
end;

Neutral General 13. Dez 2016 09:39

AW: Einmal im Leben ein "richtiges" PNG-Bild erstellen
 
Du hast es ja nicht mal versucht.
Nicht einfach nur das Bitmap assignen.
Du musst die Transparenz über das PNG Objekt selbst einstellen.

PS: Man sollte TPNGImage und nicht TPNGObject benutzen:

TPNGImage.TransparencyMode
TPNGImage.AlphaScanline

geesmith 13. Dez 2016 13:17

AW: Einmal im Leben ein "richtiges" PNG-Bild erstellen
 
Danke Michael für deinen kleinen Denkanstoss. Ich hatte es schon probiert, habe aber aufgeben müssen da ich noch auf dem falschen Denkweg lag. Mittlerweile krieg ich es mit dem folgenden Code hin. Das scheint wirklich zu funktionieren ...und du hattest recht "vergiss assign()" :).

Mittlerweile schnall ich den Code. Noch eine Frage... Warum sollte man TPNGImage und nicht TPNGObject benutzen?

Code:
var
  bmp:TBitmap;
  png:TPngImage;
  Line: PByteArray;
  y,x:Integer;
  PixColor, TransColor: TColor;
begin
  TransColor := clWhite;
  // Bitmap zeichnen
  bmp := TBitmap.Create;
  bmp.SetSize(100,100);
  With bmp.Canvas do
  begin
    Brush.Color := TransColor;
    FillRect(rect(0,0,bmp.Width,bmp.Height));
    Pen.Width := 5;
    Pen.Color := clRed;
    Rectangle(20,30,80,90);
    Pen.Width := 10;
    Pen.Color := clRed;
    Rectangle(50,40,70,70);
    TextOut(5,5,DateTimeToStr(now));
  end;
  bmp.TransparentColor := TransColor;
  bmp.TransparentMode := tmFixed;
  bmp.Transparent     := True;
  // Erstellen des PNG-Image
  png := TPngImage.CreateBlank(COLOR_RGBALPHA, 8, bmp.Width, bmp.Height);
  try
    for y := 0 to bmp.Height - 1 do
    begin
      Line := png.AlphaScanline[y];
      for x := 0 to bmp.Width - 1 do
      begin
        PixColor := bmp.Canvas.Pixels[x,y];
        png.Pixels[x,y] := PixColor;
        if PixColor = TransColor then
          Line^[x] := 0
        else
          Line^[x] := 255;
      end;
    end;
    png.SaveToFile('c:\temp\pngtrans6.png');
  finally
    png.Free;
  end;
  bmp.Free;
end;

Neutral General 13. Dez 2016 13:57

AW: Einmal im Leben ein "richtiges" PNG-Bild erstellen
 
Schön dass dus hinbekommen hast :)

TPNGImage ist einfach nur der neue Name.
TPNGObject ist laut Embarcadero die veraltete Version.

Letztendlich wird es (erst mal) wohl keinen Unterschied machen.
Aber mit "TPNGImage" bist du "zukunftssicher".
Da TPNGObject veraltet ist kann es sein, dass es in einer kommenden Version nicht mehr existiert.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:27 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