Wo ist der Alpha-Kanal (TBitmap)

Rund um die LCL und andere Komponenten
Antworten
Mathias
Beiträge: 7004
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Wo ist der Alpha-Kanal (TBitmap)

Beitrag von Mathias »

Ich habe folgenden Test-Code, welcher die Bitmap ausliest, einmal mit Pixels und einmal direkt über RawImage.Data.
Bei Pixels fehlt der Alphawert, wo ist der hingekommen ?

Bei der Bitmap handel es sich um eine 8x8x32 Bitmap.
Das die Werte um 8Bit verschoben sind kann ich noch verstehen, das aber immer 00xxxxxx kommt ?

Code: Alles auswählen

procedure TForm1.Button3Click(Sender: TObject);
var
  Bitmap: TBitmap;
  x, y: integer;
begin
  Bitmap := TBitmap.Create;
  Bitmap.LoadFromFile('verkleinert40.bmp');
 
  Writeln(Bitmap.PixelFormat);
 
  Writeln(#13#10'Pixels:'#13#10);
 
  for y := 0 to Bitmap.Width - 1 do begin
    for x := 0 to Bitmap.Height - 1 do begin
      Write(IntToHex(Bitmap.Canvas.Pixels[x, y], 8), '  ');
    end;
  end;
 
  Writeln(#13#10'RawImage.Data:'#13#10);
 
  for x := 0 to Bitmap.RawImage.DataSize - 1 do begin
    Write(IntToHex(Bitmap.RawImage.Data[x], 2));
    if x mod 4 = 3 then begin
      Write('  ');
    end;
  end;
 
  Canvas.Draw(0, 0, Bitmap);
 
  Bitmap.Free;
end; 
Ausgabe:

Code: Alles auswählen

pf32bit
 
Pixels:
 
00000000  00010000  00070102  00121414  001D2926  00050707  00000000  00000000
002B403C  00427D70  00397A6A  0031806C  0052B29D  00273935  00000101  00020302
0053A18F  00057456  000D644B  001E6758  00479380  00344341  00000000  00020302
004D9384  002F7762  00285A55  00265C53  00257862  00285B4D  00101413  00010101
004F8176  0045A48D  00379687  001E6859  001C6450  00407D6E  00101111  00000101
0066BDA9  00258E75  00308A77  001B8268  0024705B  0042917E  0022332F  00000000
001B2523  003D5A53  00378976  00377170  00253D37  00212C2A  000C100F  00000000
00000000  00000000  002E3637  008CA9B9  00262F2F  00000000  00000000  00000000
 
RawImage.Data:
 
00000000  01000000  07010200  12141403  1D29261C  05070703  00000000  00000000
2B403C35  427D7087  397A6A9B  31806CBA  52B29DD9  27393527  00010101  02030202
53A18FB9  057456FF  0D644BFF  1E6758FF  479380C8  34434122  00000000  02030202
4D9384A3  2F7762D5  285A55F6  265C53FB  257862E8  285B4DA3  1014130A  01010101
4F817672  45A48DD7  379687FA  1E6859FC  1C6450F5  407D6E9E  10111107  00010101
66BDA9CB  258E75FF  308A77FF  1B8268FF  24705BFF  42917ED4  22332F2C  00000000
1B252316  3D5A533F  378976DD  377170E5  253D3748  212C2A22  0C100F0B  00000000
00000000  00000000  2E363720  8CA9B9B9  262F2F1B  00000000  00000000  00000000
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

magnetron
Beiträge: 44
Registriert: Di 4. Nov 2014, 14:04

Re: Wo ist der Alpha-Kanal (TBitmap)

Beitrag von magnetron »

Hallo Mathias,
Nach meiner Information hat ein Bitmap im Sinne des filetypes bmp keinen alphakanal, auch wenn es 32 bit gross ist.
Die ersten 8bit sind wohl immer Null, zumindest ist das der kleinste gemeinsame Nenner (siehe wikipedia oder auch msdn)
Softwarespezifisch (z.B. ms GDI+) werden die ersten 8 bit unter Umständen für irgendwas wie Alphakanal verwendet.
In Lazarus scheint die "offizielle" Spezifikation implementiert zu sein, die auf allen Plattformen geht.
Auch die Property Canvas.Pixels deutet darauf hin, weil dort ein TColor zurückkommt, welches m.W. auch nur RGB und keinen
Alphakanal hat.

Eventuell kannst Du ein PNG (TPortableNetworkGraphic) verwenden oder ein LazIntfImage - je nach Ziel.
Ich verwende erfolgreich TLazIntfImage. Da hat man einen Alphakanal, allerdings auch alles im Überfluss
weil gleich 64bit....
Auf die Pixels kann man zum Beispiel mit Colors [x,y:integer] : TFPColor zugreifen, wobei der TFPColor ja Alpha kennt.

Wenn man das ganze dann mittels Canvas.Draw oder Canvas.CopyRect zeichnet, dann passt alles mit der Transparenz,
auch wenn man es vorher für diesen Zweck in ein TBitmap umgewandelt hat (dann pf32bit).
Und hier steige ich aus, weil mir bisher schleierhaft ist warum das geht (läuft unter gtk2, qt4 und windows).
So wie im freepascal wiki beschrieben Bitmap -> Lazintfimage, hier Bild incl. Transparenz ändern... -> Bitmap --> Canvas funktioniert es, siehe
http://wiki.freepascal.org/Developing_w ... ng_example
Grüsse, Stefan

soerensen3
Beiträge: 104
Registriert: Fr 22. Jun 2012, 01:51
OS, Lazarus, FPC: Fedora-Linux 23 (Korora) Lazarus 1.6 FPC 3.0
CPU-Target: 64Bit
Wohnort: Bonn

Re: Wo ist der Alpha-Kanal (TBitmap)

Beitrag von soerensen3 »

BGRA Bitmap könnte für dich auch interessant sein.

Gruß Johannes

Mathias
Beiträge: 7004
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Wo ist der Alpha-Kanal (TBitmap)

Beitrag von Mathias »

Ein bisschen weiter bin ich gekommen, der Baum kommt schon recht gut.
Der Baum ist eine *.bmp Datei. So wie es aussieht, hat bmp einen Alpha-Kanal.
Oder entspricht dies nicht dem Standard.

Code: Alles auswählen

var
  tx, ty, x, y, i: integer;
begin
  tx := Bitmap.Width;
  ty := Bitmap.Height;
  Width := tx;
  Height := ty;
  SetLength(Data, tx * ty);
  if Bitmap.PixelFormat = pf32bit then begin
    for y := 0 to ty - 1 do begin
      for x := 0 to tx - 1 do begin
        for i := 0 to 3 do begin
          Data[y * tx + x].ar[i] := Bitmap.RawImage.Data[(y * tx + x) * 4 + i];
        end;
      end;
    end;
  end else begin
    for y := 0 to ty - 1 do begin
      for x := 0 to tx - 1 do begin
        Data[y * tx + x].i := Bitmap.Canvas.Pixels[x, (ty - 1) - y];
        Data[y * tx + x].a := $FF;
        //      if TexturData.Data[y * tx + x] = 0 then TexturData.Data[y * tx + x] := $FFFFFF;
      end;
    end;
  end;
BGRA Bitmap könnte für dich auch interessant sein.
Bei glTexImage2D musste ich von RGBA auf BGRA ändern, damit der Baum richtig kommt.

Ich werde später mal die BGRA Bitmap angucken.
Dateianhänge
Zwischenablage-1.png
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1641
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Wo ist der Alpha-Kanal (TBitmap)

Beitrag von corpsman »

Du versuchst also Bilder nach OpenGL zu laden..

Dann schau dir doch mal meine OpenGLGraphikEngine an. Laden mit Alpha Kanal gibts dort auch.
--
Just try it

Mathias
Beiträge: 7004
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Wo ist der Alpha-Kanal (TBitmap)

Beitrag von Mathias »

Ich habe meinen obersten Code abgeändert, so das er auch PNG laden kann.
mauer1.bmp und mauer1.png sind beide in 8Bit (256 Color) gespeichert.
Was aber komisch ist, wen ich die BMP lade, dann ist Pixelformat pf24bit, aber bei PNG ist es pf32bit und der Alphawert ist überall dann $BA.
OpenGL nimmt dann den Alphawert von $BA, somit wird halbtransparent gerendert, was ich natürlich nicht will.
Bei Canvas.Draw ist nichts von Alpha ersichtlich.

Was aber komisch ist, wen ich ein echtes 32Bit PNG lade, dann macht Canvas.Draw transparente Pixel.

Somit müsste in der TBitmap noch irgendwo ein Vermerk sein, das es um eine Alpha-Textur handelt, ausser pf24bit und pf32bit.
Ich habe es noch mit Bitmap.Masked probiert, dort kommt aber immer FALSE.

Code: Alles auswählen

procedure TForm1.Button2Click(Sender: TObject);
var
  Picture: TPicture;
  x, y: integer;
begin
  Picture := TPicture.Create;
  Picture.LoadFromFile('mauer1.png');
 
  Writeln(Picture.Bitmap.PixelFormat);   // readln;
  writeln(Picture.Bitmap.Masked);
 
  Sleep(1000);
 
  Writeln(#13#10'Pixels:'#13#10);
 
  for y := 0 to Picture.Width - 1 do begin
    for x := 0 to Picture.Height - 1 do begin
      Write(IntToHex(Picture.Bitmap.Canvas.Pixels[x, y], 8), '  ');
    end;
  end;
                                 // readln;
  Writeln(#13#10'RawImage.Data:'#13#10);
 
  for x := 0 to Picture.Bitmap.RawImage.DataSize - 1 do begin
    Write(IntToHex(Picture.Bitmap.RawImage.Data[x], 2));
    if x mod 4 = 3 then begin
      Write('  ');
    end;
  end;
 
  Canvas.Draw(0, 0, Picture.Bitmap);
 
  Picture.Free;
end;  
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 7004
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Wo ist der Alpha-Kanal (TBitmap)

Beitrag von Mathias »

Ich bin weiter gekommen.
Wen ich einen Umweg über TLazIntfImage, dann funktioniert es mit dem Alpha-Kanal. :)
Jetzt geht es, egal ob BMP oder PNG, dir Textur kommt immer richtig.

Code: Alles auswählen

 
var 
    Data: packed array of packed record
      case byte of
        0: (r, g, b, a: byte);
        1: (i: GLenum);
        2: (ar: packed array[0..3] of byte);
    end;
 
 
    case Bitmap.PixelFormat of
      pf24bit, pf32bit: begin
        format := GL_RGBA;
        Img := TLazIntfImage.Create(0, 0);
        Img.LoadFromBitmap(Bitmap.Handle, Bitmap.MaskHandle);
        for y := 0 to ty - 1 do begin
          for x := 0 to tx - 1 do begin
            Data[y * tx + x].r := Img.Colors[x, y].red div $100;
            Data[y * tx + x].g := Img.Colors[x, y].green div $100;
            Data[y * tx + x].b := Img.Colors[x, y].blue div $100;
            Data[y * tx + x].a := Img.Colors[x, y].alpha div $100;
          end;
        end;
 
        Img.Free;
      end;
 
Ich habe aber immer noch eine Frage, wieso ist Img.Color[..].xxx als Word anstelle Byte deklariert ?

Code: Alles auswählen

  TFPColor = record
    red,green,blue,alpha : word;
  end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10973
Registriert: Mo 11. Sep 2006, 19:01

Re: Wo ist der Alpha-Kanal (TBitmap)

Beitrag von theo »

Mathias hat geschrieben:Ich habe aber immer noch eine Frage, wieso ist Img.Color[..].xxx als Word anstelle Byte deklariert ?

Code: Alles auswählen

  TFPColor = record
    red,green,blue,alpha : word;
  end;
Weil es offenbar Anwedungsfälle gibt, die dies benötigen.
http://de.wikipedia.org/wiki/Farbtiefe_ ... #Anwendung

Antworten