Einzelnen Beitrag anzeigen

Redeemer

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

AW: PNG in TImage falsch dargestellt

  Alt 26. Apr 2020, 22:31
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;
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.
Janni
2005 PE, 2009 PA, XE2 PA
  Mit Zitat antworten Zitat