Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi TPNGImage - Alphachannel in Bitmap anzeigen (https://www.delphipraxis.net/67945-tpngimage-alphachannel-bitmap-anzeigen.html)

turboPASCAL 22. Apr 2006 11:09


TPNGImage - Alphachannel in Bitmap anzeigen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,

ich grübele schon eine gamze Weile darüber wie man aus einer PNG-Graphik die Alphamaske auslesen kann.
Bei der Lib PNGImage gibt es die Möglichkeit über PNGObject.AlphaScanline[YLine] darauf zuzugreifen. Leider konnte ich noch kein Beispiel finden wie es gemacht wird.

Bei meinen Versuchen ist es mir nicht gelungen ein vernünftiges Bild zu bekommen.

Mit Scanline und 32 -Bit Bitmaps kenn ich mich jetzt nicht so aus.


Delphi-Quellcode:
    for y := 0 to PNG.Height - 1 do
    begin
      p := PNG.AlphaScanline[y];
      p2 := MaskBmp.ScanLine[y];
      for x := 0 to (PNG.Width -1)*4 do
        p2[x] := p[x];
    end;
Könnte mir da jemand helfen ?


Die Gr32 Kompo. will ich nicht verwenden.

chaosben 22. Apr 2006 12:05

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi!

Wenn du sowas wie im Anhang suchst dann kannst du diesen Code nehmen:
Delphi-Quellcode:
var
  PNG : TPNGObject;
  AlphaBMP : TBitmap;
  Scanline : pByteArray;
  x,y : Integer;

begin
  PNG:=TPNGObject.Create;
  PNG.LoadFromFile('E:\Icons\PNGIcons\nuvola\64x64\filesystems\link.png');
  png.Draw(Image1.Canvas,Rect(0,0,Png.Width,png.Height));

  AlphaBMP:=TBitmap.Create;
  AlphaBMP.Width:=png.Width;
  AlphaBMP.Height:=png.Height;
  AlphaBMP.PixelFormat:=pf8bit;

  for y:=0 to png.Height-1 do
  begin
    Scanline:=png.AlphaScanline[y];
    for x:=0 to png.Width-1 do
      AlphaBMP.Canvas.Pixels[x,y]:=RGB(Scanline^[x],Scanline^[x],Scanline^[x]);
  end;
  PaintBox1.Canvas.Draw(0,0,AlphaBMP);
  AlphaBMP.SaveToFile('c:\test.bmp');
  AlphaBMP.Free;
  png.Free;
end;

turboPASCAL 22. Apr 2006 12:29

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Ja sowas such ich, allerdings ohne das .Pixels[x,y].

Ich komme mal wieder mit dem Scanline nicht zurrecht. ;)

chaosben 22. Apr 2006 13:03

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Zitat:

Zitat von turboPASCAL
Ja sowas such ich, allerdings ohne das .Pixels[x,y].

Wie jetzt? Das versteh ich nicht.
Stört dich die Mal-Routine und/oder deren Geschwindigkeit? :gruebel:

turboPASCAL 22. Apr 2006 13:08

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Die Geschwindigkeit. Und wenn ich mal mit Scanline anfange mache ich dann auch damit gern weiter...

;)

Khabarakh 22. Apr 2006 13:38

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Du musst beachten, dass AlphaScanline ein Byte, Scanline aber ein TRGBQuad (bzw. je nach PixelFormat) liefert.
Mit meinem Avatar erfolgreich getestet:
Delphi-Quellcode:
  TCardinalArray = Array[0..0] of Cardinal;
  PCardinalArray = ^TCardinalArray;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  Png: TPNGObject;
  x, y: Integer;
  pTo: PCardinalArray;
  pFrom: PByteArray;
  Alpha: Byte;
begin
  if OpenPictureDialog1.Execute then
  begin
    Png := TPNGObject.Create;
    try
      Png.LoadFromFile(OpenPictureDialog1.FileName);

      Image1.Width := Png.Width * 2;
      Image1.Height := Png.Height;
      Image1.Picture.Bitmap.Width := Png.Width * 2;
      Image1.Picture.Bitmap.Height := Png.Height;
      Image1.Picture.Bitmap.PixelFormat := pf32bit;
      Image1.Canvas.Draw(0, 0, Png);
     
      for y := 0 to Png.Height - 1 do
      begin
        pFrom := Png.AlphaScanline[y];
        pTo := Image1.Picture.Bitmap.ScanLine[y];
        for x := 0 to Png.Width - 1 do
        begin
          Alpha := pFrom[x];
          pTo[x + Png.Width] := Alpha or Alpha shl 8 or Alpha shl 16;
        end;
      end;
    finally
      Png.Free;
    end;
  end;
end;

turboPASCAL 22. Apr 2006 14:01

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Vielen Dank, das muss ich mir erst einmal angucken (durchdenken)
Delphi-Quellcode:
pTo[x + Png.Width] := Alpha or Alpha shl 8 or Alpha shl 16;
das mit dem RGBQuad hatte ich auch schon vwesucht, hat aber nicht funktionieren wollen...

:thumb:

chaosben 22. Apr 2006 19:18

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Zitat:

Zitat von turboPASCAL
Vielen Dank, das muss ich mir erst einmal angucken (durchdenken)
Delphi-Quellcode:
pTo[x + Png.Width] := Alpha or Alpha shl 8 or Alpha shl 16;

Naja, das ist im Prinzip das Gleiche wie oben:
Delphi-Quellcode:
Pixels[x,y]:=RGB(Scanline^[x],Scanline^[x],Scanline^[x]);
Wenn du nicht darauf angewiesen bist, das es nur Grau-Werte in deinem Bild gibt, kannst du in meinem Beispiel die Schleife dahin abändern:
Delphi-Quellcode:
  for y:=0 to png.Height-1 do
  begin
    Scanline:=png.AlphaScanline[y];
    ToScanLine:=AlphaBMP.ScanLine[y];
    CopyMemory(ToScanLine,Scanline,png.Width);
  end;
Schneller gehts imho nicht.

turboPASCAL 22. Apr 2006 23:31

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Schneller geht es nicht, aber ich brauche schon die Graustufen der Maske. ;)

Spes 18. Jan 2008 12:22

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Hi zusammen,

was mache ich falsch, wenn aus diesem Bild (der weiße Bereich ist laut Fireworks transparent)

http://www.andreaswortmann.de/temp/test.png

durch folgenden Code (siehe auch oben)

Code:
var
  PNG : TPNGObject;
  AlphaBitmap : TBitmap;
  Scanline , ToScanLine : pByteArray ;
  y : Integer;

begin
  PNG := TPNGObject.Create;
  PNG.LoadFromFile('test.png');

  AlphaBitmap := TBitmap.Create;
  AlphaBitmap.Width := PNG.Width;
  AlphaBitmap.Height := PNG.Height;
  AlphaBitmap.PixelFormat := pf8bit;

  for y:=0 to png.Height-1 do
  begin
    Scanline := PNG.AlphaScanline[y];
    ToScanLine := AlphaBitmap.ScanLine[y];
    CopyMemory(ToScanLine, Scanline, PNG.Width);
  end;

  Image1 . Picture . Assign ( AlphaBitmap ) ;
  AlphaBitmap.Free;
  PNG.Free;
end;
dieses Bild

http://www.andreaswortmann.de/temp/ausgabe.png

wird?

Gibt es (mitterlweile) irgendeine native oder elegantere Möglichkeit PNGs samt Transparenz auf VCL-Komponenten abzubilden?

Danke im Voraus,
Spes

OregonGhost 18. Jan 2008 13:40

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Das Bild ist doch absolut korrekt. Ein Alphakanal ist 1 (bzw. 255) für sichtbar und 0 für unsichtbar. Wenn du den Wert direkt als Helligkeit verwendest, hast du also weiß für sichtbar und schwarz für unsichtbar. Und genau das zeigt dein Bild doch.

Muetze1 18. Jan 2008 14:03

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Zitat:

Zitat von Spes
Gibt es (mitterlweile) irgendeine native oder elegantere Möglichkeit PNGs samt Transparenz auf VCL-Komponenten abzubilden?

Delphi-Quellcode:
  VCLComponentenCanvas.Draw(0, 0, DeinPiNGImage);
Oder was?

Spes 18. Jan 2008 17:00

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Hi ihr beiden,

vielen Dank für die Hinweise. Vielleicht verstehe ich die Alphatransparenz noch nicht so ganz.
Ich habe mittlerweile folgendes - komplexeres - Bild (der Hintergrund ist eigentlich transparent; das Pink dient hier nur der Veranschaulichung):
http://www.andreaswortmann.de/temp/test3.png
Die Transparenz bei PNGs erlaubt mir doch eigentlich für jedes Pixel anzugeben, wie transparent dieses sein soll (eben von 0 (garnicht) bis 255 (vollständig transparent)). Dieses benötige ich um 'weiche' Ränder entlang der Grafik zu erhalten.

Binde ich die Grafik jetzt wie folgt ein:
Code:
PNG := TPNGObject . Create ;
PNG . LoadFromFile ( 'test3.png' ) ;
Image . Canvas . Draw ( 0 , 0 , PNG ) ;
wird der Hintergrund nicht transparent, sondern weiß.

Geht das überhaupt, oder kann ich nur diese binäre ja/nein Transparenz verwenden?

Entschuldigt bitte, falls ich mich unverständlich ausgedrückt habe. Ich stehe da seid zwei Tagen total auf dem Schlauch.

Danke im Voraus,
Spes

Spes 18. Jan 2008 20:07

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Hi nochmal,

dank der von SirThornberry in diesem Thread geposteten Lösung, hat sich mein Problem erledigt.

Vielen Dank für eure Hinweise.

Muetze1 18. Jan 2008 20:29

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Zitat:

Zitat von Spes
Binde ich die Grafik jetzt wie folgt ein:
Code:
PNG := TPNGObject . Create ;
PNG . LoadFromFile ( 'test3.png' ) ;
Image . Canvas . Draw ( 0 , 0 , PNG ) ;
wird der Hintergrund nicht transparent, sondern weiß.

Logisch. Du malst das PiNG Image auf ein Bitmap und das hat grundsätzlich erstmal einen weißen Hintergrund. Bereite das Bitmap auf das du zeichnest entsprechend vor, damit dann die PiNG Transparenz beim zeichnen dort eingerechnet wird.

Zitat:

Zitat von Spes
dank der von SirThornberry in diesem Thread geposteten Lösung, hat sich mein Problem erledigt.

Dort wird nichts anderes gemacht, als das PiNG direkt im Image zu belassen. Aber das wäre genau das gleiche als wenn du dir das Image auf die Form packst und über den Objektinspektor das PiNG Image lädst. Oder du benutzt das LoadFromFile() von TPicture, welches dann auch die passende GraphicInstanz suchen & instanziieren sollte.

Spes 19. Jan 2008 19:49

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Zitat:

Zitat von Muetze1
Bereite das Bitmap auf das du zeichnest entsprechend vor

Wie meinst du das?

Muetze1 19. Jan 2008 20:16

Re: TPNGImage - Alphachannel in Bitmap anzeigen
 
Na bringe den von dir gewünschten Hintergrund auf das Bitmap, weil anscheinend gefällt dir der weiße Bitmap-Standard-Hintergrund nicht.


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