AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

PNG in TImage falsch dargestellt

Ein Thema von tumo · begonnen am 14. Apr 2020 · letzter Beitrag vom 29. Apr 2020
Antwort Antwort
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#1

AW: PNG in TImage falsch dargestellt

  Alt 17. Apr 2020, 18:19
Da wird das Problem dann sein, dass .Draw() vermutlich die Transparenzen des Originalbildes wirklich zum Zeichnen benutzt, und ein Blend aus BMP und PNG erstellt. Das wäre für .Draw() auch richtig - aber nicht für .Assign()! Dank Alpha unterscheidet sich Zeichnen erheblich von Kopieren, und das ist in der Tat ein dicker Fehler in der gezeigten Methode. Allerdings auch schon in der alten Version... bei der ich fast vermute, dass .Draw() eigentlich falsch mit Transparenz umgegangen ist, sodass das richtige Verhalten für .Assign() entstand, und gleichzeitig für meine Probleme verantwortlich war.

Klingt für mich jetzt erstmal schlüssig.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Rolf Frei

Registriert seit: 19. Jun 2006
655 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: PNG in TImage falsch dargestellt

  Alt 17. Apr 2020, 19:24
Das Problem ist, dass nun, wenn man ein transparentes PNG auf eine Bitmap assigned eben der Hintergrund schwarz wird. Das war in einer älteren Version der PNGImage nicht so und da hat das mit der Trnasparenz und dem Alphachannel einwandfrei funktioniert. Da war der Hintergrund weiss, nähmlich so wie ein leeres Bitmap eben ist. Durch das fixe setzen der Farbe und einem FillRect wird die "leere" Bitmap mit schwarz "übermmalt" und der Transparente Teil wird schwarz. Meiner Meinung nach ist das falsch oder müsste zumindest mit einem Property gesteuert werden können, welche Farbe man da will.

Durch diese fixe Setzen auf die Farbe 0 (schwarz) ist der AssingTo praktisch unbrauchbar geworden. Ich musste mir dafür eine eigene Routine schreiben, die diese 2 Zeilen nicht enthält, damit mein D7 Programm nach der Migration auf 10.3 noch richtig mit den PNG's umgehen kann. Mir ist echt ein Rätsel wer das da mit fixem schwarzen Hintergund überhaupt so nutzen kann?!
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#3

AW: PNG in TImage falsch dargestellt

  Alt 17. Apr 2020, 20:43
Es gibt bei transparenten Bitmaps eigentlich keinen richtigen oder falschen Hintergrund - zumindest, solange es noch nicht auf das finale Bild gezeichnet wurde, auf dem es angezeigt werden soll. Weiß ist genauso falsch wie Schwarz (und technisch gesehen ist transparent-schwarz (=0) richtiger für "leer" als nicht-transparent-weiß (=$FFFFFFFF)). Was man eigentlich in dieser Situation haben will ist, dass sowohl Farbe als auch Alpha unverändert übernommen werden. "Assigned" eben, im Gegensatz zu "Drawn" wo die Farbwerte anhand der Transparenz miteinander verrechnet werden. Es ist schlicht nicht okay in einer Assign-Methode intern Draw(To) zu verwenden. Stattdessen müssten die Pixel 1:1 kopiert werden.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
Ort: Kirchlinteln (LK Verden)
1.116 Beiträge
 
Delphi 2009 Professional
 
#4

AW: PNG in TImage falsch dargestellt

  Alt 17. Apr 2020, 21:26
Ich muss meine Aussage von vorhin korrigieren: Mir fällt nämlich auf, dass der von mir beschriebene Bug nur mit TImageList.AddMaked(BMP, clNone) und InsertMasked auftritt (ReplaceMasked unterstützt allgemein keine Alphakanäle), nicht jedoch mit TImage, während mein Bugfix (Kopieren der Scanline-Bytes) in TImageList fehlerfrei funktioniert aber in TImage unter bestimmten Umständen zu einem extrem lustigen Fehler führt (siehe *):
-Einfach nur Original-Assignmit Korrektur von Rolfmit manuellem Kopieren der Scanline-Bytesmit manuellem Kopieren der Scanline-Bytes und Korrektur von Rolf
TImage.Picture.Graphic := BMPfehlerfrei mit fehlerfreiem Alphakanalzu Weiß geglättet komplett ohne Alphakanalsiehe *Alphakanal wird komplett ignoriert, also alle Pixel in gespeicherter Farbe vollständig deckend
TImageList.AddMasked(BMP, egal)zu Schwarz geglättet mit fehlerfreiem Alphakanalzu Weiß geglättet komplett ohne Alphakanalfehlerfrei mit fehlerfreiem AlphakanalAlphakanal wird komplett ignoriert, also alle Pixel in gespeicherter Farbe vollständig deckend
* ohne RDP: Die TBitmap zeichnet sich selbst wie folgt auf den Hintergrund, auf dem das TImage liegt: Pixel mit Deckkraft > 0 haben korrekten Alphakanal. Bei Pixeln mit Deckkraft = 0 wird für jeden Kanal einzeln (d.h. ohne Überlauf) der Kanal zum jeweiligen Kanal des Hintergrunds addiert. Das sieht lustig aus, tritt aber normalerweise nicht auf, da die meiste Software es nicht erlaubt, Farben außer Schwarz in transparenten Pixeln zu speichern, und Schwarz fehlerfrei dargestellt würde (Hintergrund + clBlack = Hintergrund).
* in einer RDP-Sitzung: Bild zeichnet nicht vollständig deckende Pixel zwar mit korrektem Alphakanal, aber als ob die Farbe des in der PNG gespeicherten Pixels komplett schwarz wäre. Vollständig deckende Pixel sind fehlerfrei. GDI macht über RDP wirklich was es will.

Mich wundert vor allem, dass TCanvas.Draw überhaupt den Alphakanal des Zielbitmaps schreibt. In TPNGImage.Draw wird in dem Fall TPNGImage.DrawPartialTrans aufgerufen, das wahrscheinlich eine Spezialbehandlung für Bitmaps bietet, die ich aber nicht verstehen/finden kann.
Und mich wundert, dass frischt assignte Bitmaps in TImage fehlerfrei dargetellt werden, in TImageList aber nicht. Die Daten müssen also irgendwo fehlerfrei vorhanden sein.
Auch seltsam: Der zweite Parameter von AddMasked wird in allen oben getesteten Fällen ignoriert.

Ich hab mal mein Beispielprojekt angehängt. imagelist.png enthält drei 16x16-Bilder nebeneinander:
  1. weißer Kreis, linke Hälfte ist nur 50% deckend
  2. schwarzer Kreis, linke Hälfte ist nur 50% deckend
  3. die 16 Standardfarben in der unteren Hälfte sind in der oberen Hälfte mit 0 Deckkraft gespeichert
Das enthaltene Kompilat ist aus D2009 (sieht bei D10.3 genau so aus, ebenso unter Windows 10) und stellt den Zustand aus der vorletzten Spalte (mit manuellem Kopieren der Scanline-Bytes). Davon habe ich auch zwei Bilder angehängt (jeweils ohne RDP).
(Ich weiß, dass der Code Memoryleaks hat.)
Angehängte Grafiken
Dateityp: png beispiel2.png (2,8 KB, 17x aufgerufen)
Dateityp: png beispiel.png (25,7 KB, 16x aufgerufen)
Angehängte Dateien
Dateityp: 7z TransTest.7z (239,2 KB, 4x aufgerufen)
Janni
2005 PE, 2009 PA, XE2 PA

Geändert von Redeemer (17. Apr 2020 um 21:28 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.629 Beiträge
 
Delphi 12 Athens
 
#5

AW: PNG in TImage falsch dargestellt

  Alt 20. Apr 2020, 23:40
(Ich weiß, dass der Code Memoryleaks hat.)
Hast du vergessen zu speichern? Der Code ist faktisch nicht existent:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von scrat1979
scrat1979

Registriert seit: 12. Jan 2007
Ort: Sulzbach a.d. Murr
1.029 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: PNG in TImage falsch dargestellt

  Alt 21. Apr 2020, 15:06
Ich klinke mich mal kurz ein da ich gerade auch einen Code erstellt habe um aus einen Stream (genauer gesagt ein im Stream gespeichertes PNG) in einem TImage anzuzeigen. Das (transparente) PNG wird über LoadFromStream in ein TPNGImage geladen und anschließend in einem TImage angezeigt. Sofern ich nicht völlig blind bin klappt die Darstellung der Transparenzen problemlos... Delphi 10.3.3
Michael Kübler
  Mit Zitat antworten Zitat
Rolf Frei

Registriert seit: 19. Jun 2006
655 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: PNG in TImage falsch dargestellt

  Alt 22. Apr 2020, 11:57
Ich klinke mich mal kurz ein da ich gerade auch einen Code erstellt habe um aus einen Stream (genauer gesagt ein im Stream gespeichertes PNG) in einem TImage anzuzeigen. Das (transparente) PNG wird über LoadFromStream in ein TPNGImage geladen und anschließend in einem TImage angezeigt. Sofern ich nicht völlig blind bin klappt die Darstellung der Transparenzen problemlos... Delphi 10.3.3
Mein beschriebenes Problem ist etwas tiefgründiger, wie ich festgestellt habe. Wenn du das PNG einfach nur darstellst, passt das. Sobald du nun aber eine Bitmap daraus machst, also mit Assign, und es speicherst wird der Hintergrund nun schwarz und der Alphachannelbereich wird falsch und sieht fürchterlcih aus. Das ist mit der älteren PNGImages aus D7 nicht der Fall. Da ist der Hintergrund nach dem Speichern weiss und auch der Alphachannel wird richtig gespeichert. Die RIO PNGImages Klasse macht das falsch und durch das Schwarz setzten des Hintergrunds wird beim speichern das Bitmap "kaputt" gemacht. Das heisst, die altbekannte Transparenz beim Bitmap wird gesetzt (Farbe Schwarz) und der Alphachannelbereich der Grafik wird nicht transparent. Mit der alten Version wird keine Transparenz gespeichert und daher sieht das da auch richtig aus. Ich erwarte hier auch garnicht, dass das Bitmap eine Trnasparenz bekommt, da TBitmap das Bild nicht mit dem Alphachannel speichert. Die neue Version versucht das Bitmap transparent zu machen, das geht aber nur solange kein Alphachannel im Spiel ist, ansonsten sieht das Bitmap fürchterlich aus.

Siehe die anghängten Bilder und das beigefügte Demoprojekt.
- transAlpha.png Originaldatei
- transAlphaRio.bmp Speicherung der Bitmap nach dem Assign mit der aktuellen VCL.Imaging.PNGImages.pas
- transAlphaD7.bmp Speicherung der Bitmap nach dem Assign mit der alten D7 PNGImges.pas

Wer die D7 Version der PNGImages nicht hat, kann einfach die beiden von mir oben erwöhnten Zeilen in der aktuellen Version löschen und schon ist alles wieder wie es sein soll.
Angehängte Dateien
Dateityp: zip PNG-BMP-Images.zip (851,3 KB, 2x aufgerufen)

Geändert von Rolf Frei (22. Apr 2020 um 12:17 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von scrat1979
scrat1979

Registriert seit: 12. Jan 2007
Ort: Sulzbach a.d. Murr
1.029 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: PNG in TImage falsch dargestellt

  Alt 22. Apr 2020, 12:12
Okay, alles klar. Ich gehe auch den Umweg über ein TBitmap, da letztendlich eine Darstellung in einer TImageList erfolgen soll (genauer gesagt Replace, das erfordert eben ein TBitmap). Funktioniert tadellos. Allerdings - wie du schon richtig erkannt hast - geht es um die reine Darstellung.
Michael Kübler
  Mit Zitat antworten Zitat
tumo

Registriert seit: 28. Apr 2014
46 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: PNG in TImage falsch dargestellt

  Alt 21. Apr 2020, 15:14
Nach weiterem überlegen, probieren und googlen habe ich "herausgefunden", dass der Anzeigefehler nur auftritt, wenn die PNG im ColorMode 3 (Paletten-Modus) geladen wird. @Redeemer hatte also den richtigen Riecher (oder womöglich schon eine Lösung?). Warum genau dadurch Ränder schwarz angezeigt werden, wo die Pixeldaten eig. richtig sind, bleibt mir aber ein Rätsel. Mit der Graphics32 Library habe ich jetzt ein wenig rumprobiert. Sie geht, aber recht umständlich in manchen Belangen. Die essentielle Funktion für mich (PNGs laden) geht nur mit einer extra Unit, die man noch dazu installieren muss :/. Sollte es also eine Lösung für die VCL TImages geben, wäre ich sehr erfreut, diese zu erfahren.

@scrat1979
Wie gesagt, es ist nur bei manchen PNGs. Um genau zu sein bei PNGs im ColorMode 3 (Paletten-Modus)
  Mit Zitat antworten Zitat
Benutzerbild von scrat1979
scrat1979

Registriert seit: 12. Jan 2007
Ort: Sulzbach a.d. Murr
1.029 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: PNG in TImage falsch dargestellt

  Alt 21. Apr 2020, 18:52
@Tumo: Alles klar, könnte die Erklärung sein, dass es bei mir - Gott sei dank - funktioniert. Wollte es auch nur der Vollständigkeit halber erwähnen.

Viel Erfolg dir weiterhin
Michael Kübler
  Mit Zitat antworten Zitat
Antwort Antwort


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 05:57 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