Recent

Author Topic: [SOLVED] [BGRA] How to save image with alpha channel while keeping transparency?  (Read 2098 times)

jipété

  • Full Member
  • ***
  • Posts: 172
Hello,

starting with the tutorial number 4 (https://wiki.freepascal.org/BGRABitmap_tutorial_4), I copy/paste the code from FormPaint and F9 gives me a nice 4gradients, the same as the image in the wiki.
OK.

The problem arises when I look at the line   p^.alpha := 255; I tell me (yes, I talk to myself, sometimes) : try others values (before playing with TrackBar).

So I tried with 200, 100, 30 and everything becomes nice after i change
Code: Pascal  [Select][+][-]
  1.   image.Draw(Canvas,0,0,True);
to
Code: Pascal  [Select][+][-]
  1.   image.Draw(Canvas,0,0,False); //!\\ +1

Anyway, trying to save what I see discards the Alpha channel :
Code: Pascal  [Select][+][-]
  1.   image.SaveToFile('/tmp/2820.bmp');
Left side of screenshot = image drawn on Form1, OK, Right side is what I get opening the saved file, not the same as expected.
Image is reduced by 50%.
gradients-alpha_not-alpha.png

The file is 32bits, as seen with an hexeditor.
What I am missing ?

PS : OS Linux-Debian 11.9 64bits, GTK2, FPC 3.2.2 Lazarus 3.4
« Last Edit: June 20, 2024, 05:58:02 pm by jipété »

lainz

  • Hero Member
  • *****
  • Posts: 4572
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Hi, you need to diferentiate when you draw into a canvas and when you save to file.

The drawing to a canvas and save to file are not related.

So the image object contains the 255 alpha.

lainz

  • Hero Member
  • *****
  • Posts: 4572
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Try this before saving:
Code: Pascal  [Select][+][-]
  1. image.ApplyGlobalOpacity(200);

jipété

  • Full Member
  • ***
  • Posts: 172
Try this before saving:
Code: Pascal  [Select][+][-]
  1. image.ApplyGlobalOpacity(200);
Tried, same bad result (and why "200" ? Why not 150 or 201 or ... ?)

Hi, you need to diferentiate when you draw into a canvas and when you save to file.

The drawing to a canvas and save to file are not related.

So the image object contains the 255 alpha.
Not understood what you mean, sorry... I just want to save in a file what I see on my monitor.

Somewhere (https://forum.lazarus.freepascal.org/index.php/topic,67424.msg518990.html#msg518990 -- last line of the post) I've read
Quote
However, I'd transfer the bitmap via stream (rather than using Assign) because this way the transparency is preserved
so I tried the following :
Code: Pascal  [Select][+][-]
  1.   ...
  2.       p^.alpha := 30;
  3.   ...
  4. //image.Draw(Canvas,0,0,True);
  5.   image.Draw(Canvas,0,0,False);      //!\\ +1
  6.   image.SaveToFile('/tmp/sf2820.bmp'); // wrong colours
  7.  
  8.   image.SaveToStreamAs(ms, ifBmp);
  9.   ms.Position:=0;
  10.   ms.SaveToFile('/tmp/ms2820.bmp'); // wrong colours
  11.  
  12.   img.Picture.LoadFromStream(ms);
  13.   img.Picture.SaveToFile('/tmp/2820.bmp'); // wrong colours

img is a TImage with Center := True and Transparent := True.
Dunno what to do to get a file with transparency, as if I did a screenshot.

Is it related to Linux ?

circular

  • Hero Member
  • *****
  • Posts: 4300
    • Personal webpage
BMP format with 32-bit pixels has limited support in most viewers. Even though there is room for the alpha channel, many readers will assume that there is no alpha channel and discard the information. I believe that initially, this 32-bit format was introduced to align to every 4 bytes, even though it was only containing RGB values (the "alpha" part was simply zero). So unless you have a reader that is aware of this alpha channel, it is better to use another format that has solid alpha support, typically PNG.

So I tried with 200, 100, 30 and everything becomes nice after i change
Code: Pascal  [Select][+][-]
  1.   image.Draw(Canvas,0,0,True);
to
Code: Pascal  [Select][+][-]
  1.   image.Draw(Canvas,0,0,False); //!\\ +1
That's right. Even though using Opaque:=True will be slightly faster in many cases when the image is in fact opaque, to draw a transparent image, it is indeed necessary to change this parameter to False.
Conscience is the debugger of the mind

jipété

  • Full Member
  • ***
  • Posts: 172
So unless you have a reader that is aware of this alpha channel, it is better to use another format that has solid alpha support, typically PNG.
Is it possible to have easy access to pixels with PNG ?
For example, I can play with BGRA pixels like that :
Code: Pascal  [Select][+][-]
  1.   with aBmp do begin
  2.     BeginUpdate();
  3.     for h := 0 to img.Height-1 do begin
  4.       p := pRGBQuad(RawImage.GetLineStart(h));
  5.       for w := 0 to img.Width-1 do begin
  6.         p^.rgbred   := w*256 div Width;
  7.         p^.rgbgreen := h*256 div Height;
  8.         p^.rgbblue  := 0;
  9.         p^.rgbreserved := trkBar.Position; // <<<<<<< ! to play with transparency
  10.         {$IFDEF LINUX}
  11.         SwapRBdatas; // /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\
  12.         {$ENDIF}
  13.         inc(p);
  14.       end;
  15.     end;
  16.     EndUpdate();
  17.     img.Picture.Assign(aBmp);
  18.   end;

More material tomorrow, have a good night with nice dreams.

TRon

  • Hero Member
  • *****
  • Posts: 2903
Is it possible to have easy access to pixels with PNG ?
BGRABitmap can load and save png files so you can use the same approach.

jipété

  • Full Member
  • ***
  • Posts: 172
Hello,

Before starting learning the PNG format, I've noticed that when I work with 32bits bitmap files, the data are good, looking inside the file with an hex editor.

And I've also noticed that using an OpenPictureDialog for browsing files, the preview window on the right side of the tool displays good images, except when the value of Alpha channel is 000 (where it returns 255), displaying an opaque image. Little bug ?

In the attached zip are screenshots from the OpenPictureDialog, with the name as the value of the Alpha channel, and the program is available in the .zip.

The problems are within FPC/Lazarus; for example, the display of miniatures in a folder doesn't take care of the Alpha channel : see attached wrong_miniatures.png

Better data is in the 7files_32bits.gif (except the bad colors related to the gif compression), one may prefer looking at the .xcf Gimp file.

And I've also noticed a bug in the dialog, look at the broken_bottoms_open-bmp400%.gif, the bottom of the miniatures are strange.

Dunno what to do with all these things...
In the meantime, I'll setup the trackbar used to change Alpha value from 001 rather than 000 to 255, but the problem with that trick is the fact that using a color picker to look at the TImage displaying the results, the position 1 pf the trackbag creates a 236 235 234 RGB color...

See you later,

One zip for 6 files :
wrong_miniatures.png
7files_32bits.xcf gimp file
7files_32bits.gif
broken_bottoms_bmp400%.xcf gimp file
broken_bottoms_bmp400%.gif
bitmap_alpha.zip test program

TRon

  • Hero Member
  • *****
  • Posts: 2903
And I've also noticed that using an OpenPictureDialog for browsing files, the preview window on the right side of the tool displays good images, except when the value of Alpha channel is 000 (where it returns 255), displaying an opaque image. Little bug ?
...
I do not know how to properly respond on your attached images.

Yes, there is an outstanding report regarding transparency an images but other than that are you aware that about 80-90% of the picture viewers (amongst them famous ones) that do not know how to properly handle alpha channels ? Those that show full transparent pixels as black... or white or use hard-coded rgb only. The proper way at least for a picture viewer and imho is to display a checkerboard and overlay the image.

Though it can be annoying to work with I would not worry too much about it (unless that is the aim of your post). As long as you save your images in a format that properly supports transparency then your should not have any issues, at least not when using BGRABitmap. Mileage might vary when using other solutions.
« Last Edit: June 18, 2024, 11:46:55 am by TRon »

circular

  • Hero Member
  • *****
  • Posts: 4300
    • Personal webpage
And I've also noticed that using an OpenPictureDialog for browsing files, the preview window on the right side of the tool displays good images, except when the value of Alpha channel is 000 (where it returns 255), displaying an opaque image. Little bug ?
It is rather a feature. 32bit BMP format can be used to save image without alpha channel, and thus with zero value where you would expect the alpha value. However it can be argued that using later header version for BMP images, it is possible to confirm an image uses the alpha channel.

It would be worth trying to improve the image writer to use the BITMAPV4HEADER instead of BITMAPINFOHEADER. Then, when using BI_BITFIELDS value for "compression method", the bit mask for R, G, B and alpha would be included in the header. This would be confirmed by the size specified for the header. If this is recognized by image viewers, then it would be worth improving the BMP reader to check for the alpha mask. If found, then even if the image is fully empty, the alpha channel should not be set to 255.
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4572
  • Web, Desktop & Android developer
    • https://lainz.github.io/
I don't think it worth the effort.

Bmp files are always opaque and that's the thing everyone expects.

For transparent images use png.

jipété

  • Full Member
  • ***
  • Posts: 172
Hello,

Bmp files are always opaque...
No (see images below), problems are related to viewers, I think.

For example, I open a file with an hexa editor, which shows a 32bpp value but The Gimp doesn't deal with that : I can see in the toolbox, Layers part, the option to add Alpha layer !
Dunno why the file is opened that way.
In another side, ImageMagick shows a gray checkerboard, meaning transparency.
prog+ImMagick.png

And after many try-and-restart with ImageMagick (I understand nothing to this tool...), I've got a good result :
The attached image shows, on left side, the program while running, with a trackbar to adjust transparency and that works fine ;
In the middle is ImageMagick opening the file created at previous step (with some settings that I don't understand) ;
And the right side is ImageMagick's file saved and reopened with the default viewer of Linux-Debian, which usually displays a strong image without transparency.
3gradienst.png

I've written "I've got a good result" but it is not perfect because I don't know how ImageMagick works and so, the colours are not exactly the same as the original.
Sorry.
And yes, I'm studying closely for PNG format.

lainz

  • Hero Member
  • *****
  • Posts: 4572
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Hello,

Bmp files are always opaque...
No (see images below), problems are related to viewers, I think.

It depends what's your goal. If you want to share these files and open with other viewers, consider for better that .bmp are not transparent, believe me I'm graphic designer and no graphic designer will send you a .bmp with transparency. Better use .png in that case.

If the case is you want to open and edit that files in your own program, save as .bmp with transparency if BGRABitmap supports it it's ok. Because is just for you.

jipété

  • Full Member
  • ***
  • Posts: 172
OK, and thanks you for yours tips (and Circular too).

And yes, I love gradients,  ;)  :D  8-)

lainz

  • Hero Member
  • *****
  • Posts: 4572
  • Web, Desktop & Android developer
    • https://lainz.github.io/
I love gradients too. As well circular AFAIK
 :)

 

TinyPortal © 2005-2018