Delphi-PRAXiS
Seite 5 von 6   « Erste     345 6      

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)

venice2 24. Apr 2020 17:28

AW: PNG in TImage falsch dargestellt
 
Ich habe jetzt nicht alles gelesen..
Aber was für eine Qualität bzw. Ansicht erwartest du bei einem Indizierten *.png!
Das kann nur inkorrekt dargestellt werden.

Ändere es doch einfach mal von 8 auf 32Bit.
Ich behaupte jetzt einfach mal das TImage mit indizierten *.png's nicht klar kommt.

Redeemer 25. Apr 2020 11:24

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von venice2 (Beitrag 1462840)
Ich habe jetzt nicht alles gelesen..
Aber was für eine Qualität bzw. Ansicht erwartest du bei einem Indizierten *.png!
Das kann nur inkorrekt dargestellt werden.

Nein.

tumo 25. Apr 2020 16:10

AW: PNG in TImage falsch dargestellt
 
@Medium
Ich wüsste jetzt nicht, wo man den Vergrößerungs-Algorithmus einstellen kann. Tatsächlich macht er das schon mit NearestNeighbour (oder etwas, was verdammt danach aussieht), was auch das ist, was ich will. Verfolgt man die Draw()-Methode von PNGImage landet man mit BitTransparency früher oder später in einer Prozedur mit dem schönen Namen "DrawTransparentBitmap". Da drin wird mit Windows-Blt-Befehlen weiter gearbeitet. Ab da verstehe ich nicht mehr wirklich viel :/.

@venice2
Ich erwarte, dass die Pixeldaten korrekt dargestellt werden, auch in vergrösserter Version. Es gibt noch einen Unterschied zwischen hässlich und inkorrekt darstellen. Es "einfach" mal von 8bit auf 32bit zu ändern (1.) geht mit Palettenbildern nicht, (2.) lässt TPNGImage á la BitDepth=32bit nicht zu, (3.) ist in meinem Fall nicht möglich, da die Bilder so gegeben sind. Die Behauptung ist zwar ganz nett, aber eben nicht richtig bzw. offensichtlich. TPNGImage hat einen extra Case für BitTransparency (die nur in Palettenbildern vorkommt) in der Draw()-Methode. Andere, nicht-transparente, indizierte PNGs kann es ja problemlos.

venice2 25. Apr 2020 18:50

AW: PNG in TImage falsch dargestellt
 
Zitat:

aber eben nicht richtig bzw. offensichtlich. TPNGImage hat
Ihr solltet euch mal langsam einigen.
Was denn nu TImage oder TPNGImage

Zitat:

(1.) geht mit Palettenbildern nicht
geht nicht gibt es nicht.

Es ist ein einfaches dein Paletten Bild im Speicher zu einem vollwertigen 32Bit PNG Image zu konvertieren.
Was hindert dich daran.
Zitat:

(2.) lässt TPNGImage á la BitDepth=32bit nicht zu
Wofür braucht man die Komponente wenn ich das im Speicher erledigen kann.
Es scheint mir ohne Komponente seid ihr alle aufgeschmissen.
Zitat:

Ab da verstehe ich nicht mehr wirklich viel :/.
Bestätigt meine vermutung.
Zitat:

(3.) ist in meinem Fall nicht möglich, da die Bilder so gegeben sind.
Nichts ist gegeben hinzunehmen. Siehe beide Kommentare zuvor.

Redeemer 26. Apr 2020 09:24

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von venice2 (Beitrag 1462878)
Zitat:

aber eben nicht richtig bzw. offensichtlich. TPNGImage hat
Ihr solltet euch mal langsam einigen.
Was denn nu TImage oder TPNGImage

Zitat:

Zitat von venice2 (Beitrag 1462878)
Wofür braucht man die Komponente wenn ich das im Speicher erledigen kann.
Es scheint mir ohne Komponente seid ihr alle aufgeschmissen.

So große Töne spucken, wenn man noch nicht mal weiß, was Delphi-Referenz durchsuchenTPNGImage ist... :wall:

Zitat:

Zitat von venice2 (Beitrag 1462878)
Zitat:

(1.) geht mit Palettenbildern nicht
geht nicht gibt es nicht.

Du suchst eine Herausforderung? Alles klar, dann erstell doch einfach mal ein Computerprogramm, das irgendein Problem aus dieser Liste in polynomieller Zeit löst.

Zitat:

Zitat von venice2 (Beitrag 1462878)
Es ist ein einfaches dein Paletten Bild im Speicher zu einem vollwertigen 32Bit PNG Image zu konvertieren.

Das ist dennoch ein richtiger Ansatz.

tumo 26. Apr 2020 14:46

AW: PNG in TImage falsch dargestellt
 
Zitat:

Zitat von Redeemer (Beitrag 1462894)
Das ist dennoch ein richtiger Ansatz.

Gibt es da irgend einen Trick? Mein Ansatz wäre jetzt das pixelweise Parsen in ein neues TPNGObject, bin mir aber nicht sicher, ob das nicht noch effizienter geht.

Das umgeht dann ja aber nur das Problem. Mit anderen Worten, ich muss einen Edgecase für ebendiese Problembilder machen. Naja, ich schätze mal, das ist der sinnvollste Weg für mich, manchmal kann man eben nicht alles haben.
Wäre das ein Bug, den man so bei Embarcadero einreichen müsste? Hab bisher nichts dazu gefunden, kann also gut sein, dass ich der erste bin, der auf diesen Fehler stößt (was mich aber auch wundern würde).

Danke trotzdem für die bisherige Hilfe.

venice2 26. Apr 2020 16:01

AW: PNG in TImage falsch dargestellt
 
Nur damit du siehst das es geht von wegen (So große Töne spucken)
ABer da du Herrn Redeemer angesprochen hast und dieser nur die Leute beleidigen kann soll er dir auch helfen.

Aus deinem indizierten *.png im Speicher 24Bit erstellt und extrem vergrößert bzw. auf mein Fenster angepasst.
Nicht mal 5 Minuten Arbeit.

Damit du nicht denkst es wäre ein fake habe ich noch 2 Bitmaps drüber gelagert.
Es ist dein Paletten Bild unverändert. (1 Bit). Einfach nur als Hintergrund geladen

Ich werde das Thema nun verlassen.
Schönen Tag noch.

Redeemer 26. Apr 2020 21:31

AW: PNG in TImage falsch dargestellt
 
Hab mir das nochmal angesehen:
  • Paletten-PNG an sich kennt überhaupt keine 1-Bit-Transparenz. Dies ist nur ein Spezialfall von Palette+Alphakanal, wo alle Alphawerte entweder 0 oder 255 sind. TPngImage behandelt den Spezialfall anders (ptmBit) als Palette+Alphakanal (ptmPartial), obwohl es dafür keinen wirklichen Grund gibt. Man könnte jetzt versuchen, das Attribut TransparentColor zu verwenden, dies ist jedoch problematisch, da einen niemand daran hindert, beispielsweise die beiden Paletteneinträge Schwarz 0 Alpha und Schwarz 255 Alpha zu speichern. Dies in eine 24-Bit-PNG mit transparenter Farbe umzuwandeln und die transparente Farbe auf Schwarz zu setzen, funktioniert dann nicht.
  • Dein PNG 4 hat 256 Paletteneinträge, aber nur 77 Farben.
  • Dein PNG 4 enthält 256 Alphawerte. Der letzte ist völlig transparent. Eigentlich macht man das andersrum (erster Eintrag ist völlig transparent), damit man die restlichen nicht speichern muss, da man keine Alphawerte speichern muss, wenn alle folgenden Alphawerte komplett deckend sind.
  • Mein PNGDelphi in D2009 versagt bei 4-Bit- und 1-Bit-Paletten-PNGs.

Ich habe jetzt folgenden Code geschrieben. Der führt zumindest bei meinem PNGDelphi dazu, dass ein Paletten-PNG in True Color umgewandelt wird. Das funktioniert auch mit den bisher zumindest von meinem PNGDelphi nicht unterstützten 1- und 4-Bit-PNGs. Es gibt sogar 1-Bit- und 4-Bit-PNGs mit Alphakanal. Auch das wird unterstützt.
Delphi-Quellcode:
procedure Deindex(PNG: TPngImage);
var
  Chroma: array[Byte] of TPaletteEntry;
  Alpha, ScanlineSource, ScanlineTarget, AlphaScanline: PByteArray;
  DoAlpha: Boolean;
  NewPNG: TPngImage;
  y, x: Integer;
  BitDepth: Byte;
  Mask: Byte;
  x2: Integer;
  Shift: Byte;
begin
  AlphaScanline := nil; // Compiler-Mimimi
  Alpha := nil; // Compiler-Mimimi
  if PNG.Header.ColorType = COLOR_PALETTE then
  begin
    DoAlpha := PNG.TransparencyMode <> ptmNone;
    if DoAlpha then
    NewPNG := TPngImage.CreateBlank(COLOR_RGBALPHA, 8, PNG.Width, PNG.Height)
    else
    NewPNG := TPngImage.CreateBlank(COLOR_RGB, 8, PNG.Width, PNG.Height);
    try
      GetPaletteEntries(PNG.Palette, 0, 256, Chroma);
      BitDepth := PNG.Header.BitDepth;
      Mask := Word(1) shl BitDepth - 1;
      if DoAlpha then
      Alpha := @((PNG.Chunks.FindChunk(TChunktRNS) as TChunktRNS).PaletteValues); // hier bin ich mir unsicher in Sachen Speicherverletzung
      for y := 0 to PNG.Height - 1 do
      begin
        ScanlineSource := PNG.Scanline[y];
        ScanlineTarget := NewPNG.Scanline[y];
        if DoAlpha then
        AlphaScanline := NewPNG.AlphaScanline[y];
        for x := 0 to PNG.Width - 1 do
        begin
          x2 := x * BitDepth div 8;
          Shift := 8 - BitDepth - ((BitDepth * x) mod 8);
          ScanlineTarget^[x*3  ] := Chroma[(ScanlineSource^[x2] shr Shift) and Mask].peBlue;
          ScanlineTarget^[x*3+1] := Chroma[(ScanlineSource^[x2] shr Shift) and Mask].peGreen;
          ScanlineTarget^[x*3+2] := Chroma[(ScanlineSource^[x2] shr Shift) and Mask].peRed;
          if DoAlpha then
          AlphaScanline^[x] := Alpha[ScanlineSource^[x2] shr Shift and Mask];
        end;
      end;
    except
      NewPNG.Free();
      raise;
    end;
    PNG.Assign(NewPNG);
    NewPNG.Free();
  end;
end;
Zitat:

Zitat von venice2 (Beitrag 1462917)
Nur damit du siehst das es geht von wegen (So große Töne spucken)
ABer da du Herrn Redeemer angesprochen hast und dieser nur die Leute beleidigen kann soll er dir auch helfen.

Aus deinem indizierten *.png im Speicher 24Bit erstellt und extrem vergrößert bzw. auf mein Fenster angepasst.
Nicht mal 5 Minuten Arbeit.

Damit du nicht denkst es wäre ein fake habe ich noch 2 Bitmaps drüber gelagert.
Es ist dein Paletten Bild unverändert. (1 Bit). Einfach nur als Hintergrund geladen

Ich werde das Thema nun verlassen.
Schönen Tag noch.

Kann ich auch mit Grafiksoftware, APIs (in deinem Fall LEAD Technologies) oder anderweitig ohne Delphi machen. Dass du es mit Delphi gemacht hast, dafür gibt es keine Hinweise.

Rolf Frei 27. Apr 2020 12:43

AW: PNG in TImage falsch dargestellt
 
@OP
Hast du denn nun schon mal die VCL.Imaging.PNGimages.pas in dein loakels Anwendungsverzeichnis kopiert und die beiden von mir erwähnten Zeilen gelöscht und neu kompiliert?

@venice2
TImage und TPNGImage haben nichts miteinander zu tun. TPNGImage ist die Grafikklasse (TGraphic), die ein PNG Bild rendert und darstellt. TImage ist eine allgmeine Darstellungskomponente (TControl), die nichts anderes macht als die Paint Funktion der geladenen Graphic-Klasse aufzurufen. Dieses Problem hier hat mit der TImage Komponente nichts zu tun, sondern betrifft die Implementation der TPNGImage Klasse.

tumo 27. Apr 2020 16:13

AW: PNG in TImage falsch dargestellt
 
@Rolf Frei
Ach ja. Das ist im Eifer des Gefechtes etwas in Vergessenheit geraten. Hab es gerade mal probiert, ändert leider nichts an der Situation, besagte PNG wird mit schwarzem Hintergrund dargestellt :/.
Hier mein Quellcode:
Delphi-Quellcode:
png := TPNGImage.Create;
    png.LoadFromFile(Path);
    bmp := TBitmap.Create;
    bmp.Assign(png); // <-- TPNGImage AssignTo() ist modifiziert. Es fehlen das Brush.Color := 0 sowie das FillRect.
    Image3.Picture.Graphic := bmp;
@Redeemer
Dieser Code funktioniert :-). So oder so ähnlich hätte ich es natürlich auch gelöst :P. Spaß beiseite, vielen Dank!
Dass die Bilder nicht optimal gespeichert sind, hab ich auch schon gemerkt. Wie gesagt, manche sind mir so gegeben, andere sind von mir in Paint.net erstellt, keine Ahnung, warum es da solche Späßchen generiert.

Jetzt hat das Problem einen Workaround. Warum Delphi überhaupt eine Unterscheidung zwischen Partial- und BitTransparency macht, bleibt mir ein Rätsel. Hat das einen entscheidenden Vorteil?
Mein Problem ist jetzt jedenfalls behoben bzw. umgangen. Danke euch.

Habe es jetzt folgendermaßen gelöst (mit der Prozedur von Redeemer):
Delphi-Quellcode:
var
  gfx: TPicture;
begin
  gfx := TPicture.Create;
  gfx.LoadFromFile(Path);
  if gfx.Graphic is TPNGImage then
    Deindex(gfx.Graphic as TPNGImage);
  Image3.Picture.Assign(gfx);
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:22 Uhr.
Seite 5 von 6   « Erste     345 6      

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