Recent

Author Topic: Broken example "Creating and drawing a transparent bitmap for a TImage" in Linux  (Read 5716 times)

jipété

  • Full Member
  • ***
  • Posts: 182
You are absoluteley right.
Thanks, 
;D

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
My default image viewer, for example is IrfanView;
Same, on Windows I assume its one of the fastest "optional free" image viewer available with a very stable and robust format support.
I set its background to some unusual color; with that it not very likely that I can be fooled about the presence of transparency.
clFuchsia :D Hello Telekom haha
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

wp

  • Hero Member
  • *****
  • Posts: 12457
clFuchsia :D Hello Telekom haha
Huuu, I hate that, and it is used by some ancient Delphi bitmaps as transparent color which makes it difficult to tell whether such an image is alpha- or color-transparent. I prefer some medium gray

jipété

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

Many years ago, I've written a little program to look inside the bitmaps header, where the data are ok, for example, the first image shows what is retrieved with ghex, and we can read at position 1C the value 18 for one file, meaning 24 bits, and 20 for the other file, meaning 32 bits.
analyse_3x2_2432_v1.png
On that file, look at the bytes FF in the second screenshot, it's the alpha channel, not available in the top screenshot where we see underlined (by me) "00" for padding.
That image (zoomed at 800% in the top windows) has only six colored pixels, so easy to analyze.
The 6 blocks of data in the bottom window come from a ColorPicker, and we retrieve the values seen in the hexa tables but read from right to left.

I've tried my tool with many many many files and everything is OK : if no alpha channel, 1C = 18, if alpha channel, 1C = 20.

When we look at the beginning of the data, we read FF 00 00 FF 00 00 etc. so 3 bytes per pixel, coming from the 24 bits file, and we read FF 00 00 00 FF 00 00 00 etc. so 4 bytes per pixel coming from the 32 bits file.

And I don't understand why the DataDescription is not able to retrieve the good values :
Code: Pascal  [Select][+][-]
  1. lii.DataDescription.Depth // is always at 24
  2. lii.DataDescription.BitsPerPixel // is always at 32
How is it possible ?

On the other side, I've found a web page updated in feb.24 and anyway, outdated...
wrong_lazarus_intfgraphics.img
That's really a pity !

A last word :
Found in IntfGraphics.pas :
Code: Pascal  [Select][+][-]
  1. procedure TLazWriterBMP.Initialize(AImage: TLazIntfImage);
  2. begin
  3.   // set BPP
  4.   // we can also look at PixelFormat, but it can be inexact <-- ha ha ha ! lol !
  5.   BitsPerPixel := AImage.DataDescription.Depth;
  6. end;
BitsPerPixel := AImage.DataDescription.Depth; ok, so why do I read 32 24 ?
retrieve_descr.png

What is this mess (to be polite) ?
« Last Edit: May 27, 2024, 03:19:49 pm by jipété »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
TBitmap got bug at PixelFormat and everything related to BPP since a longer time, unsure why it does not getting fixed.
To analyze images using whatever TImageFormatClass is in many cases overkill, just load as filestream the neccessary bytes to get your result.
Its a zillion times faster than any class could do.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

jipété

  • Full Member
  • ***
  • Posts: 182
TBitmap got bug at PixelFormat and everything related to BPP since a longer time, unsure why it does not getting fixed.
To analyze images using whatever TImageFormatClass is in many cases overkill, just load as filestream the neccessary bytes to get your result.
Its a zillion times faster than any class could do.

Thanks for the tip.

And what do you think 'bout that : starting with the link https://wiki.freepascal.org/fcl-image#See_also (third line, Stretching...),I get a canvas.pdf file and after compiling the example found on page 6, I execute it with a true 32bits bitmap file which becomes a 24bits at the end of the prog.
'cos the only useful instructions are
Code: Pascal  [Select][+][-]
  1.     Img.LoadFromFile(ReadFile);
  2.     Img.SaveToFile(WriteFile);
, I don't imagine what to do to keep the 32bits structure...

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Thanks for the tip.
You are welcomed.
And what do you think 'bout that : starting with the link https://wiki.freepascal.org/fcl-image#See_also (third line, Stretching...),I get a canvas.pdf file and after compiling the example found on page 6, I execute it with a true 32bits bitmap file which becomes a 24bits at the end of the prog.
'cos the only useful instructions are
Code: Pascal  [Select][+][-]
  1.     Img.LoadFromFile(ReadFile);
  2.     Img.SaveToFile(WriteFile);
, I don't imagine what to do to keep the 32bits structure...
We do have some kind of wierd communication problem.
The link you shared is about getting dimension and I can't find anything with canvas.pdf ....
In short, when you load an 32bpp TBitmap via "bitmap.LoadFromFile()" where you are sure that it is 32bpp (do not rely on TBitmap itself!) add straight after "bitmap.PixelFormat := pf32bpp", when you now do "bitmap.SaveToFile()" it is 32bpp and not 24bpp, at least on my windows with stable FPC and Lazarus trunk.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

jipété

  • Full Member
  • ***
  • Posts: 182
We do have some kind of wierd communication problem.
The link you shared is about getting dimension and I can't find anything with canvas.pdf...
If you click on my link, you go to a page where the last line ("Stretching...") is a link to the page "https://www.freepascal.org/~michael/articles/#canvas" where you can find
Download this article in PDF: canvas
Click "canvas" to dl the pdf.
stretching.png

... at least on my windows with stable FPC and Lazarus trunk.
Well, I think the problem is here, as usual : so many things work fine in Windows and not or badly in other systems.
That's life...

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
I really like to help .... but ....
you do not really want us to open a link, download a pdf, install a pdf reader, read pdf and tryout everything written in there to test if it is accurate, or?
If whatever is written in your link shows some code and it still matches to this topic, add a snippet showing what you do or what link tells you to do.
Your snippet should contain everything needed to copy/paste/run.
If it does not match in this thread, create a new.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

wp

  • Hero Member
  • *****
  • Posts: 12457
Bitmaps historically always have been "difficult": paletted images, full color images, transparency achieved by means of a transparent color, no alpha channel - well... the alpha channel has been added in some Windows version. But, I was just trying to save one of the Lazarus general-purpose images (they are png with alpha channel) as bmp with several programs and was not successful, it always ended up in a 24-bpp image without transparency.

The same with FPC (fcl-image): When I use the code in Michael Van Canneyt's article (which is an excellent introduction to fcl-image, by the way) and store a transparent png to bmp it becomes opaque, too.

But there is a solution: When you have to save a file with alpha-transparency do not write to bmp, but write to png. Here the fcl-image writer is equipped with an option to write the alpha channel correctly, property UseAlpha := true. The problem is that this option is not active by default, so even when I specify a png as output image it will become opaque. To avoid this you must create the writer explicitely by yourself, set its UseAlpha to true and then use it in the SaveToFile call.

Here is MvC's code modified such that the alphachannel is retained in a png output image:
Code: Pascal  [Select][+][-]
  1. { From Michael Van Canneyt's article about the Canvas }
  2.  
  3. program imgconv;
  4.  
  5. {$mode objfpc}{$h+}
  6.  
  7. uses
  8.   FPWriteXPM, FPWritePNG, FPWriteBMP, fpwritejpeg, fpwritetga,
  9.   FPReadXPM, FPReadPNG, FPReadBMP, fpreadjpeg, fpreadtga,
  10.   fpreadpnm, FPImage, sysutils;
  11. var
  12.   img : TFPMemoryImage;
  13.   ReadFile, WriteFile : string;
  14.   readerClass: TFPCustomImageReaderClass;
  15.   writerClass: TFPCustomImageWriterClass;
  16.   reader: TFPCustomImageReader;
  17.   writer: TFPCustomImageWriter;
  18. begin
  19.   if paramcount = 2 then
  20.   begin
  21.     ReadFile := paramstr(1);
  22.     WriteFile := paramstr(2);
  23.   end
  24.   else
  25.   begin
  26.     Writeln('Usage: imconv infile outfile');
  27.     Halt(1);
  28.   end;
  29.   If CompareText(ReadFile,WriteFile)=0 then
  30.   begin
  31.     Writeln('Input file cannot be the same as output file');
  32.     Halt(1);
  33.   end;
  34.  
  35.   readerClass := TFPMemoryImage.FindReaderfromFileName(ReadFile);
  36.   if readerClass = nil then
  37.   begin
  38.     WriteLn('The graphics format of ' + ReadFile + ' is not supported for reading.');
  39.     Halt(1);
  40.   end;
  41.  
  42.   writerClass := TFPMemoryImage.FindWriterFromFileName(WriteFile);
  43.   if writerClass = nil then
  44.   begin
  45.     WriteLn('The graphics format of ' + ReadFile + ' is not supported for writing.');
  46.     Halt(1);
  47.   end;
  48.  
  49.   Img:=TFPMemoryImage.Create(0,0);
  50.   try
  51.     reader := readerClass.Create;
  52.     Img.LoadFromFile(ReadFile, reader);
  53.     reader.Free;
  54.  
  55.     writer := writerClass.Create;
  56.     try
  57.       if writer is TFPWriterPNG then
  58.         TFPWriterPNG(writer).UseAlpha :=true;
  59.       Img.SaveToFile(WriteFile, writer);
  60.     finally
  61.       writer.Free;
  62.     end;
  63.  
  64.   Finally
  65.     Img.Free;
  66.   end;
  67. end.
« Last Edit: May 27, 2024, 07:58:29 pm by wp »

wp

  • Hero Member
  • *****
  • Posts: 12457
In short, when you load an 32bpp TBitmap via "bitmap.LoadFromFile()" where you are sure that it is 32bpp (do not rely on TBitmap itself!) add straight after "bitmap.PixelFormat := pf32bpp", when you now do "bitmap.SaveToFile()" it is 32bpp and not 24bpp, at least on my windows with stable FPC and Lazarus trunk.
Please show me your code for this (along with a possible input image, 32-bit bmps are hard to find). I'd be interested, because in all my experiments this has not been possible with TBitmap.

jipété

  • Full Member
  • ***
  • Posts: 182
When I use the code in Michael Van Canneyt's article (which is an excellent introduction to fcl-image, by the way)
Hé hé !

Here is MvC's code modified such that the alphachannel is retained in a png output image:
Thanks !
You made my day (or my night, or my tomorrow morning !)
That's cool !

I'd be interested, because in all my experiments this has not been possible with TBitmap.
No time for that, now. Please wait...
(and not sure I understand the question...)

(along with a possible input image, 32-bit bmps are hard to find).
Hard to find but really easy to create with The Gimp,  :D
The attached file has been made with PixelFormat = 32bits, BitsPerPïxels = 32 also and BytesPerPixel = 4.
HTH,
src32.bmp
« Last Edit: June 04, 2024, 09:45:11 am by jipété »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Attached is a 32bit Bitmap test file.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   LBitmap: TBitmap;
  4. begin
  5.   LBitmap := TBitmap.Create;
  6.   try
  7.     LBitmap.LoadFromFile('Test.bmp');
  8.     LBitmap.PixelFormat := pf32bit;
  9.     LBitmap.SaveToFile('Test2.bmp');
  10.   finally
  11.     LBitmap.Free;
  12.   end;
  13. end;
It will save a 32bit bitmap.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

wp

  • Hero Member
  • *****
  • Posts: 12457
Attached is a 32bit Bitmap test file.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   LBitmap: TBitmap;
  4. begin
  5.   LBitmap := TBitmap.Create;
  6.   try
  7.     LBitmap.LoadFromFile('Test.bmp');
  8.     LBitmap.PixelFormat := pf32bit;
  9.     LBitmap.SaveToFile('Test2.bmp');
  10.   finally
  11.     LBitmap.Free;
  12.   end;
  13. end;
It will save a 32bit bitmap.
Ah, yes! You can even skip setting the pixel format. And even the MvC code is working. Why didn't it work before?

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Ah, yes! You can even skip setting the pixel format.
On my system not, when I not force it, it saves random 32/24 bpp, so chance is fifty fifty that it works without :D
And even the MvC code is working. Why didn't it work before?
I have not tested, just tried to help OP, my current doing with the FPC graphics is more than enough to make me happy even when I sometime hate it, like having an idea, begin with a FP format (not unit Graphics) and stuck on simple things like TextOut() where I just get informed at runtime that its not implemented yet... so formatswitch and retry, yeah yeah, it can keep me busy :D
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

 

TinyPortal © 2005-2018