Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   PNG in TImage falsch dargestellt (https://www.delphipraxis.net/204002-png-timage-falsch-dargestellt.html)

tumo 14. Apr 2020 13:38

Delphi-Version: 10.3 Rio

PNG in TImage falsch dargestellt
 
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo,

ich habe ein kleines Programm, was mir Texturen auflistet und diese nach Bedarf anzeigt. Die Texturen sind als PNG gespeichert und werden (dank PNGImage) auch problemlos von Delphi geladen. Die Texturen sind fast immer 32x32 px groß und damit ich diese auf einem FHD Bildschirm auch ordentlich beurteilen kann, dachte ich, ich stelle sie ein wenig größer dar. TImage war von dieser Idee leider weniger begeistert, da es manche der Texturen mit schwarzem Outline darstellt. Dabei trat der Fehler bisher nur bei Bildern mit (genutztem) Alpha-Channel auf, jedoch auch nicht bei jedem Bild mit Alpha-Werten. Damit ist die Beurteilung der Texturen logischerweise unmöglich, da nicht korrekt dargestellt. Wenn ich mir die Pixeldaten vom TImage (!) ausgeben lasse, ist alles korrekt, also muss ein Fehler bei der gestreckten Darstellung passieren.

Zum Verständnis: Das TImage hat
Delphi-Quellcode:
Proportional := true
und
Delphi-Quellcode:
Stretch := true
. Das TImage soll das Bild auf eine Größe von 144x144 px, ultimativ aber auf jede beliebige Größe skalieren können. Der Fehler tritt nicht auf, wenn das TImage auf 64x64 px (x2) skaliert, bei 128x128 px (x4) wiederum schon.

Was übersehe ich hier? Warum werden bei manchen (aber nicht allen) PNGs solche Outlines dargestellt?

Im Anhang sehr ihr einmal das Originalbild (in 32 px und 144 px) und was das TImage daraus macht (in 144 px).

Medium 14. Apr 2020 14:01

AW: PNG in TImage falsch dargestellt
 
TImage (zumindest das der VCL) basiert auf der alten GDI, welche mit Transparenzen nicht wirklich umzugehen weiß, auch wenn sie korrekt in den Rohdaten stehen. Wenn du bei VCL bleiben willst (bzw. musst), ist die Graphis32 Lib eine sehr sehr gute freie und offene Alternative, die auch mit Transparenz vernünftig spielt. Man könnte auch auf die GDI+ zurückgreifen, da gibt es auch freie Header zu, jedoch fand ich die Arbeit damit immer recht klobig. Dazu kommt, dass auch GDI+ schon seit Jahren abgekündigt ist.

Sherlock 14. Apr 2020 15:10

AW: PNG in TImage falsch dargestellt
 
Mein Favorit ist das deutlich modernere Delphi-Referenz durchsuchenTWicImage.

Sherlock

himitsu 14. Apr 2020 15:58

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von Sherlock (Beitrag 1462021)

Natürlich nur in der VCL, da es die WinAPI nutzt und leider sind auch da paar Dinge blöd eingebaut, vor allem da im StretchDraw nicht deren API Inteface genutzt wird, sondern das auf brutalst mögliche Weise selbst implementiert wurde.

Redeemer 14. Apr 2020 18:11

AW: PNG in TImage falsch dargestellt
 
Sind die PNGs, wo es nicht geht, Palettenbilder?

tumo 14. Apr 2020 21:12

AW: PNG in TImage falsch dargestellt
 
Danke für die schnellen Antworten.

@Medium
Habe mir die graphics32 mal angeschaut. Nach fast einer halben Stunde Harreraufen mit den Delphi Settings ging es dann endlich. Es tut, was es muss, aber nicht so richtig was es soll. Nicht falsch verstehen, meine Bitmaps werden bildschön, skaliert und mit Transparenz angezeigt, aber die eigentliche Zuweisung der Bitmaps ist alles andere als verständlich für mich :stupid:. Habe eine Liste mit Objekten, die Namen, ein paar andere Daten und eben auch die Bilder selbst speichern sollen. Diese sollen dann bei Bedarf angezeigt werden, aber irgendwie bekomme ich die Bitmap nicht von meinem Objekt in das Image32 gedrückt :|.

@Redeemer
Darf ich erfahren, was Palettenbilder sind?

himitsu 14. Apr 2020 21:26

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von tumo (Beitrag 1462053)
Darf ich erfahren, was Palettenbilder sind?

Wie z.B. bei den 2-, 16- oder 256-Farben-Bitmaps.

PNG kann die Pixel jeweils als RGB speichern, aber es geht auch als Index in einer Farbpalette.

tumo 14. Apr 2020 21:42

AW: PNG in TImage falsch dargestellt
 
Ah.
Nun, nicht das ich wüsste.

Medium 15. Apr 2020 07:29

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von tumo (Beitrag 1462053)
[...]irgendwie bekomme ich die Bitmap nicht von meinem Objekt in das Image32 gedrückt :|.

Grundsätzlich sollte das mit einem TBitmap32.DrawTo(TImage32.Bitmap) erledigt sein, ggf. noch ein TImage32.Bitmap.Clear vorausgeschickt. Zeig im Zweifel doch mal das Stück Code, in dem das gemacht wird. Dann kann man evtl. konkreter helfen.

Redeemer 15. Apr 2020 07:43

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von tumo (Beitrag 1462058)
Ah.
Nun, nicht das ich wüsste.

Na ja, die PNG wird es dir nicht von selbst sagen. Da musst du mit einem geeigneten Programm nachschauen. Die Unterstützung für PNG8 mit Alphakanal ist sehr uneinheitlich.

tumo 15. Apr 2020 08:58

AW: PNG in TImage falsch dargestellt
 
@Redeemer
Das war mir jetzt auch klar. Da ich aber alle PNGs einheitlich abgespeichert habe, vermute ich mal, entweder sind alle Pallettenbilder oder keins. Wenn dem nicht so ist, verstehe ich den Algorithmus von Paint.net nicht :/

@Medium
Perfekt, damit funktioniert es. Warum eine Zuweisung oder ein Assign nicht funktioniert, bleibt mir zwar ein Rätsel, aber das ist ja nicht so wichtig.

Final werden die Bilder in meiner Klasse so geladen:
Delphi-Quellcode:
fSrcPic, fDestPic: TBitmap32;
(...)
property SrcPicture: TBitmap32 read fSrcPic;
property DestPicture: TBitmap32 read fDestPic;
(...)
fSrcPic.Clear;
fDestPic.Clear;
if FileExists(fSrcPath) then
  LoadBitmap32FromPNG(fSrcPic, fSrcPath);

if FileExists(fDestPath) then
  LoadBitmap32FromPNG(fDestPic, fDestPath);
Und so werden sie dann dargestellt.
Delphi-Quellcode:
e
ist das ausgewählte Objekt.
Delphi-Quellcode:
Image1.Bitmap.SetSize(e.SrcPicture.Width, e.SrcPicture.Height);
e.SrcPicture.DrawTo(Image1.Bitmap);
(...)
//Image2.Bitmap.Clear; <-- Offenbar nicht nötig
Image2.Bitmap.SetSize(e.DestPicture.Width, e.DestPicture.Height);
e.DestPicture.DrawTo(Image2.Bitmap);

Rolf Frei 17. Apr 2020 17:34

AW: PNG in TImage falsch dargestellt
 
Liste der Anhänge anzeigen (Anzahl: 1)
Mit der PNG Unit von D7 kann man transparente PNG problemlos laden und anzeigen. Dass das in Rio nicht mehr geht hat ganz andere Gründe. Da hat nämlich irgend ein Witzbold einfach den transparenten Teil auf fix schwarz gesetzt. Keine Ahung was man damit errreichen wollte, aber auf jeden Fall kann man so keine transparentten PNG's mehr an eine Bitmap assignen. Die Hintergrundfarbe müsste auf jeden Fall vom Anwender bestimmt werden und nciht fix Schwarz sein. In meinem Fall will ich da nämlich weiss als Hintergrundfarbe und nicht schwarz. Dafür müsste es ein Property geben.

Habe noch eine Beispiel PNG angehängt, die einen Alphchannel hat und transparent sein sollte. Dieses wird nun fix mit schwarzem Hintergrund angezeigt, wenn es an ein Bitmap assigned wird.

Das ist der entsprechende Code in der alten D7 PNGImage unit, der einwandfrei mit PNG's mit einem Alphachannel funktioniert:
Delphi-Quellcode:
**** PNGImage von D7 ****

{Assigns this TPNGImage to another object}
procedure TPNGImage.AssignTo(Dest: TPersistent);
{$IFDEF UseDelphi}
  function DetectPixelFormat: TPixelFormat;
  begin
    with Header do
    begin
      {Always use 24bits for partial transparency}
      if TransparencyMode = ptmPartial then
        DetectPixelFormat := pf24bit
      else
        case BitDepth of
          {Only supported by COLOR_PALETTE}
          1: DetectPixelFormat := pf1bit;
          2, 4: DetectPixelFormat := pf4bit;
          {8 may be palette or r, g, b values}
          8, 16:
            case ColorType of
              COLOR_RGB, COLOR_GRAYSCALE: DetectPixelFormat := pf24bit;
              COLOR_PALETTE: DetectPixelFormat := pf8bit;
              else raise Exception.Create('');
            end {case ColorFormat of}
          else raise Exception.Create('');
        end {case BitDepth of}
    end {with Header}
  end;
var
  TRNS: TChunkTRNS;
{$ENDIF}
begin
  {If the destination is also a TPNGImage make it assign}
  {this one}
  if Dest is TPNGImage then
    TPNGImage(Dest).AssignPNG(Self)
  {$IFDEF UseDelphi}
  {In case the destination is a bitmap}
  else if (Dest is TBitmap) and HeaderPresent then
  begin
    {Copies the handle using CopyImage API}
    TBitmap(Dest).PixelFormat := DetectPixelFormat;
    TBitmap(Dest).Width := Width;
    TBitmap(Dest).Height := Height;

    if Palette <> 0 then
      TBitmap(Dest).Palette := CopyPalette(Palette);

    if (TransparencyMode = ptmBit) then
    begin
      TRNS := Chunks.ItemFromClass(TChunkTRNS) as TChunkTRNS;
      TBitmap(Dest).TransparentColor := TRNS.TransparentColor;
      TBitmap(Dest).Transparent := True;
      SetStretchBltMode(TBitmap(Dest).Canvas.Handle, COLORONCOLOR);
      StretchDiBits(TBitmap(Dest).Canvas.Handle, 0, 0, Width, Height, 0, 0,
        Width, Height, Header.ImageData,
        pBitmapInfo(@Header.BitmapInfo)^, DIB_RGB_COLORS, SRCCOPY)

    end {if (TransparencyMode = ptmBit)}
    else
      TBitmap(Dest).Canvas.Draw(0, 0, Self);
  end
  else
    {Unknown destination kind}
    inherited AssignTo(Dest);
  {$ENDIF}
end;
Dieser Code wurde in Rio (oder auch schon füher), so abgeändert, dass da fix schwarz als Hintergrund verwendet wird. Folgende 2 Zeilen wurde da eingefügt, die nun den Effekt haben, das der Alpahachannel ncht merh funktioniert und alles, was transparent sein sollte, nun schwarz ist. (siehe ungefähr in der Mitte des Quelcodes)

TBitmap(Dest).Canvas.Brush.Color := 0;
TBitmap(Dest).Canvas.FillRect(Bounds(0,0,Width, Height));

Delphi-Quellcode:
**** PNGImage von 10.3 ***

{Assigns this TPngImage to another object}
procedure TPngImage.AssignTo(Dest: TPersistent);
{$IFDEF UseDelphi}
  function DetectPixelFormat: TPixelFormat;
  begin
    with Header do
    begin
      {Always use 24bits for partial transparency}
      if TransparencyMode = ptmPartial then
        DetectPixelFormat := pf24bit
      else
        case BitDepth of
          {Only supported by COLOR_PALETTE}
          1: DetectPixelFormat := pf1bit;
          2, 4: DetectPixelFormat := pf4bit;
          {8 may be palette or r, g, b values}
          8, 16:
            case ColorType of
              COLOR_RGB, COLOR_GRAYSCALE: DetectPixelFormat := pf24bit;
              COLOR_PALETTE: DetectPixelFormat := pf8bit;
              else raise Exception.Create('');
            end {case ColorFormat of}
          else raise Exception.Create('');
        end {case BitDepth of}
    end {with Header}
  end;
var
  TRNS: TChunkTRNS;
{$ENDIF}
begin
  {If the destination is also a TPngImage make it assign}
  {this one}
  if Dest is TPngImage then
    TPngImage(Dest).AssignPNG(Self)
  {$IFDEF UseDelphi}
  {In case the destination is a bitmap}
  else if (Dest is TBitmap) and HeaderPresent then
  begin
    TBitmap(Dest).SetSize(Width, Height);

    if (TransparencyMode = ptmPartial) then
    begin
      TBitmap(Dest).PixelFormat := pf32bit;
      TBitmap(Dest).AlphaFormat := afDefined;
// Die 2 folgenden Zeilen sind neu: Wer hat sich diesen Blödsinn überlegt?!
      TBitmap(Dest).Canvas.Brush.Color := 0; // <<< zumindest das hier sollte vom Anwender wählbar sein, also als Property zur Verfügung stehen.
      TBitmap(Dest).Canvas.FillRect(Bounds(0,0,Width, Height));
    end
    else
    begin
      TBitmap(Dest).PixelFormat := DetectPixelFormat;
      TBitmap(Dest).AlphaFormat := afIgnored;
    end;

    if Palette <> 0 then
      TBitmap(Dest).Palette := CopyPalette(Palette);

    if (TransparencyMode = ptmBit) then
    begin
      TRNS := TChunkTRNS(Chunks.ItemFromClass(TChunkTRNS));
      TBitmap(Dest).TransparentColor := TRNS.TransparentColor;
      TBitmap(Dest).Transparent := True;
      SetStretchBltMode(TBitmap(Dest).Canvas.Handle, COLORONCOLOR);
      StretchDiBits(TBitmap(Dest).Canvas.Handle, 0, 0, Width, Height, 0, 0,
        Width, Height, Header.ImageData,
        pBitmapInfo(@Header.BitmapInfo)^, DIB_RGB_COLORS, SRCCOPY)

    end {if (TransparencyMode = ptmBit)}
    else
      TBitmap(Dest).Canvas.Draw(0, 0, Self);
  end
  else
    {Unknown destination kind}
    inherited AssignTo(Dest);
  {$ENDIF}
end;
Eine Zuweisung einer PNG mit Alphachannel an eine Bitmap mit Assign, wird deswegen immer mit schwarzem Hintergrund dargestellt. Mit der alten Unit von D7 funktioniert das noch tadellos und ist bei mir seit Jahren so im Einsatz, ohne dass ich da auf GDI+ oder ähnliches zugreiffen müsste. In Rio ist da was "kaputt" gemacht worden.

himitsu 17. Apr 2020 17:37

AW: PNG in TImage falsch dargestellt
 
Das musst du schnell noch melden, damit der Bugfix heute noch ins Delphi 10.4 rein kommt, bevor es raus kommt. :stupid:

Medium 17. Apr 2020 17:53

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von Rolf Frei (Beitrag 1462372)
Mit der PNG Unit von D7 kann man transparente PNG problemlos laden und anzeigen. Dass das in Rio nicht mehr geht hat ganz andere Gründe. Da hat nämlich irgend ein Witzbold einfach den transparenten Teil auf fix schwarz gesetzt.

Ja Moment, das stimmt nur teilweise. Die Farbe wird auf "0" gesetzt, d.h. 100% transparent Schwarz! Sichtbares Schwarz wäre clBlack, oder rgb(0, 0, 0) oder $FF000000 oder 4278190080. Das ist meines Erachtens nach richtig, und letztlich nur ein Initialisieren des soeben ggf. in der Größe geänderten Bitmaps um Restmüll aus dem Speicherbereich sicher zu entfernen.

Das Problem müsste später auftreten; da wo dieses Bitmap auf einen Bildschirm-Canvas gemalt wird. Und DAS ist wiederum Aufgabe der GDI. Eventuell wurde hier etwas an den Aufrufen geändert, das kann ich grad nicht prüfen, aber ich habe gute Erinnerung daran, dass ich mit Alphakanälen unter purer GDI immer irgendwo Probleme hatte. Mindestens in Delphi 7, aber auch noch in 2007. Mit neueren hatte ich bislang nicht mit Transparenzen zu tun.

Redeemer 17. Apr 2020 18:13

AW: PNG in TImage falsch dargestellt
 
BMP.Assign(PNG) klappt auch in D2009 schon nicht richtig. Die PNG wird zu Schwarz geglättet, die Transparenz bleibt aber. Sprich aus zu 50% deckendem Weiß wird zu 50% deckendes Mittelgrau. Man darf sich nach Assign dann die Scanlines kopieren. Ganz toll.

In Delphi 2005 gab es meines Wissens kein PNG, da musste man PNGDelphi installieren.

Medium 17. Apr 2020 18:19

AW: PNG in TImage falsch dargestellt
 
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.

Rolf Frei 17. Apr 2020 19:24

AW: PNG in TImage falsch dargestellt
 
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?!

Medium 17. Apr 2020 20:43

AW: PNG in TImage falsch dargestellt
 
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.

Redeemer 17. Apr 2020 21:26

AW: PNG in TImage falsch dargestellt
 
Liste der Anhänge anzeigen (Anzahl: 3)
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.)

TurboMagic 19. Apr 2020 14:09

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von Rolf Frei (Beitrag 1462372)
Mit der PNG Unit von D7 kann man transparente PNG problemlos laden und anzeigen. Dass das in Rio nicht mehr geht hat ganz andere Gründe. Da hat nämlich irgend ein Witzbold einfach den transparenten Teil auf fix schwarz gesetzt. Keine Ahung was man damit errreichen wollte, aber auf jeden Fall kann man so keine transparentten PNG's mehr an eine Bitmap assignen. Die Hintergrundfarbe müsste auf jeden Fall vom Anwender bestimmt werden und nciht fix Schwarz sein. In meinem Fall will ich da nämlich weiss als Hintergrundfarbe und nicht schwarz.

Hast du mal geschaut, ob das Problem schon in QP gemeldet ist und fals nicht würdest du das dann bitte melden?

Rolf Frei 20. Apr 2020 17:04

AW: PNG in TImage falsch dargestellt
 
Ich stehe da im Moment etwas auf Kriegsfuss mit der Embarcadero Website, da ich da aktuell nicht mehr den Überblick habe, was da nun aktuell ist und was nicht. Wo muss ich das genau machen, damit ich nicht irgendwo was erfasse, das garnicht mehr genutzt wird? Für mich wirkt das alles aktuell wie eine grosse Baustelle, wo man nicht mehr recht weiss, was wo zu machen ist.

Ist da qualitiy.embarcadero.com noch der richtige Platz dafür?

TurboMagic 20. Apr 2020 19:30

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von Rolf Frei (Beitrag 1462524)
Ich stehe da im Moment etwas auf Kriegsfuss mit der Embarcadero Website, da ich da aktuell nicht mehr den Überblick habe, was da nun aktuell ist und was nicht. Wo muss ich das genau machen, damit ich nicht irgendwo was erfasse, das garnicht mehr genutzt wird? Für mich wirkt das alles aktuell wie eine grosse Baustelle, wo man nicht mehr recht weiss, was wo zu machen ist.

Ist da qualitiy.embarcadero.com noch der richtige Platz dafür?

Ja, https://quality.embarcadero.com ist noch der richtige Platz dafür!

Uwe Raabe 20. Apr 2020 23:40

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von Redeemer (Beitrag 1462386)
(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.

scrat1979 21. Apr 2020 15:06

AW: PNG in TImage falsch dargestellt
 
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

tumo 21. Apr 2020 15:14

AW: PNG in TImage falsch dargestellt
 
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)

scrat1979 21. Apr 2020 18:52

AW: PNG in TImage falsch dargestellt
 
@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 :)

Rolf Frei 22. Apr 2020 11:57

AW: PNG in TImage falsch dargestellt
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von scrat1979 (Beitrag 1462589)
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.

scrat1979 22. Apr 2020 12:12

AW: PNG in TImage falsch dargestellt
 
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.

Redeemer 22. Apr 2020 18:13

AW: PNG in TImage falsch dargestellt
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Uwe Raabe (Beitrag 1462543)
Hast du vergessen zu speichern?[/DELPHI]

Ups. Ist angehängt.

Zitat:

Zitat von scrat1979 (Beitrag 1462677)
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).

Dann haben sie das wohl inzwischen repariert, dass Replace mit Transparenz klarkommt so wie es Add und Insert schon vorher konnten.

tumo 22. Apr 2020 18:16

AW: PNG in TImage falsch dargestellt
 
Okay, ich habe noch ein wenig weiter probiert:

Beim Auslesen der Header-Daten ist mir aufgefallen, dass ich folgende PNGs im Testset habe:
PNG 1: RGBA (Mode 6) ; 8bit/ch -> 32bit/px ; Transparenz-Modus: Partial (Nur Binärer Alpha-Channel)
PNG 2: RGB (Mode 2) ; 8bit/ch -> 24bit/px ; Transparenz-Modus: None
PNG 3: Palette (Mode 3) ; 8bit/ch -> 8bit/px ; Transparenz-Modus: None
PNG 4: Palette (Mode 3) ; 8bit/ch -> 8bit/px ; Transparenz-Modus: Bit
PNG 5: Palette (Mode 3) ; 4bit/ch -> 4bit/px ; Transparenz-Modus: None

Zur Darstellung habe ich einige Codeschnipsel gebastelt:
Code 1:
Delphi-Quellcode:

Image.Picture.LoadFromStream(AStream);
Code 2:
Delphi-Quellcode:
png := TPNGImage.Create;
png.LoadFromStream(AStream);
Image.Picture.Graphic := png;
Code 3:
Delphi-Quellcode:
png := TPNGImage.Create;
png.LoadFromStream(AStream);
bmp := TBitmap.Create;
bmp.Assign(png);
Image.Picture.Graphic := bmp;
Code 4:
Delphi-Quellcode:
png := TPNGImage.Create;
png.LoadFromStream(AStream);
bmp := TBitmap.Create;
bmp.Assign(png);
Image.Picture.Graphic := bmp;
Image.Transparent := png.TransparencyMode = ptmBit
Daraus habe ich diese Tabelle kreiert:
 Code 1 Code 2 Code 3 Code 4
PNG 1 Ok Ok Ok Ok
PNG 2 Ok Ok Ok Ok
PNG 3 Ok Ok Ok Ok
PNG 4 Schwarze Outlines (Siehe OP) Schwarze Outlines (Siehe OP) Tranzparenz wird schwarz dargestellt Ok, Leichter Bildversatz im Vergleich zu PNG<>4
PNG 5 Ok Ok Ok Ok

Es wird deutlich, dass die pngimage Library von Delphi Probleme mit dem Darstellen von BitAlpha PNGs hat. Wie bereits gesagt, die Pixeldaten selbst geben beim Zugriff über
Delphi-Quellcode:
png.Pixels
aber auch
Delphi-Quellcode:
bmp.Pixels
die korrekten Farbdaten an. Deswegen ist meine Vermutung, dass im TPNGImage.Draw ein Fehler passiert, vllt in Kombination mit dem Stretch? pngimage hat einen extra AlphaBit-Case in seiner Draw-Funktion. Da hier aber hauptsächlich mit Windows-Funktionen hantiert wird, kann ich ab diesem Punkt nicht wirklich weiter ermitteln, besonders, da ich mir nicht sicher sein kann, dass dort tatsächlich der Fehler liegt.
Ich wollte mal erfahren, ob Ihr den Fehler reproduzieren könnt?

Redeemer 22. Apr 2020 18:41

AW: PNG in TImage falsch dargestellt
 
Lad mal die PNGs hoch.

tumo 22. Apr 2020 18:50

AW: PNG in TImage falsch dargestellt
 
Liste der Anhänge anzeigen (Anzahl: 5)
Ok.
Hier sind sie :)

Redeemer 23. Apr 2020 09:14

AW: PNG in TImage falsch dargestellt
 
Kriege das nicht reproduziert mit Delphi 10.3... Habe LoadFromFile probiert und Laden zur Entwurfszeit. Kein Fehler.

Spannend wird es eh erst bei Palettenbildern mit Alpha-Kanal.

HolgerX 23. Apr 2020 10:40

AW: PNG in TImage falsch dargestellt
 
Hmm..

Zitat:

Zitat von tumo (Beitrag 1462735)
Ok.
Hier sind sie :)

Damit die Bilder im Original angehängt werden können, musst Du diese in nen ZIP packen..

Die Website recodiert die Bilder sonst beim Hochladen ;)

tumo 23. Apr 2020 10:52

AW: PNG in TImage falsch dargestellt
 
Liste der Anhänge anzeigen (Anzahl: 1)
Das wusste ich nicht.
Dann hier nochmal als Zip.

Redeemer 23. Apr 2020 11:20

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von HolgerX (Beitrag 1462758)
Hmm..

Zitat:

Zitat von tumo (Beitrag 1462735)
Ok.
Hier sind sie :)

Damit die Bilder im Original angehängt werden können, musst Du diese in nen ZIP packen..

Die Website recodiert die Bilder sonst beim Hochladen ;)

Nein.

tumo 23. Apr 2020 12:22

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von Redeemer (Beitrag 1462752)
Kriege das nicht reproduziert mit Delphi 10.3... Habe LoadFromFile probiert und Laden zur Entwurfszeit. Kein Fehler.
Spannend wird es eh erst bei Palettenbildern mit Alpha-Kanal.

Das wäre PNG 4 (Das mit der "Blume"). Dort bekomme ich sowohl zur Design-Zeit, als auch mit LoadFromStream und LoadFromFile diese schwarzen Ränder. Meine pngimage Library Version ist übrigens 1.564 (Was offenbar die aktuellste ist). Hast du auch Stretch=true gesetzt (und optional auch Proportional=true)? Ich nutze Delphi 10.3.3 Community und der Fehler tritt wie auf Kommando auf. Warum nur ich damit gepeinigt werden sollte ist mir ein Rätsel :gruebel:

Redeemer 23. Apr 2020 19:11

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von tumo (Beitrag 1462766)
Zitat:

Zitat von Redeemer (Beitrag 1462752)
Kriege das nicht reproduziert mit Delphi 10.3... Habe LoadFromFile probiert und Laden zur Entwurfszeit. Kein Fehler.
Spannend wird es eh erst bei Palettenbildern mit Alpha-Kanal.

Das wäre PNG 4 (Das mit der "Blume").

Die Blume hat keinen Alphakanal sondern eine transparente Farbe.
Ich benutze übrigens das bei Delphi 10.3 enthaltene pngimage.

tumo 24. Apr 2020 13:20

AW: PNG in TImage falsch dargestellt
 
Nun, der Fehler tritt offenbar auch bei BitTransparency auf. Ich nutze ebenfalls die von Delphi mitgelieferte pngimage-Lib.
Kannst du denn die Blume in Stretch=true und Proportional=true korrekt darstellen lassen?

Medium 24. Apr 2020 16:52

AW: PNG in TImage falsch dargestellt
 
Aha! Nur bei 1-Bit bzw. transparenter Farbe (welche artverwandt sind). Das lässt darauf schließen, dass die verwendete Resampling-Methode den "Alphakanal" für diese falsch behandelt. Ich habe das jetzt nicht mehr ganz im Kopf: Was für ein Filter wird denn beim Vergrößern benutzt? Bei Nutzung von Nearest-Neighbour würde ich fast vermuten, dass es kein Problem geben sollte. (Sieht natürlich auch nicht so schick aus.) Aber das wäre die Richtung, in die ich weiter forschen würde.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:39 Uhr.
Seite 1 von 2  1 2      

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