Broken example "Creating and drawing a transparent bitmap for a TImage" in Linux lazarus / 39-Graphics ---------------------------------------------------------------------- jipété · 2024-05-23 06:39 Hello, Running a Linux-Debian 12.5 64bits gtk2 computer, if I try the example https://wiki.freepascal.org/Developing_with_Graphics#Creating_and_draw ing_a_transparent_bitmap_for_a_TImage using Copy-and-Paste, the only display I get is nothing in the TImage, due to the setup of Image1.Transparent to True (read it 3 lines above the example). If set to False, the TImage is black. Someone told me that the same example works fine in Windows : see img A little tip : I've added two lines : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ...    img := bmp.CreateIntfImage;    if bmp.PixelFormat = pf32bit then Caption := 'ok 32'; // line added, seen the word...      finally        cnv.Free;      end;      bmp.LoadFromIntfImage(img);      if bmp.PixelFormat = pf32bit then ShowMessage('ok 32'); // line added, message NOT seen...  Another help with bmp.SaveToFile('a_path') shows a black bitmap. Thanks a lot for your help. ---------------------------------------------------------------------- wp · 2024-05-23 15:42 Re-tested on gtk2, gtk3 and qt5: Sample working correctly (except for gtk3 where the red and blue channels are exchanged, but that's another issue). Quote from: jipété on May 23, 2024, 08:39:16 amthe only display I get is nothing in the TImage, due to the setup of Image1.Transparent to True (read it 3 lines above the example). If set to False, the TImage is black. Sorry, this is a left-over from the long history of this article... Added some clarification notes. The code that you copied and pasted does not use the Image.Transparent property (not 100% sure, but I'd even suggest to turn it off in this example). Image.Transparent is a property to control "color-transparency" in which one particular color is declared to be transparent and not painted. ---------------------------------------------------------------------- jipété · 2024-05-23 17:23 Hi ! Quote from: wp on May 23, 2024, 05:42:59 pmRe-tested on gtk2, gtk3 and qt5: Sample working correctly With Red-Hat ? Ubuntu ? Suse ? Other ? Quote from: wp on May 23, 2024, 05:42:59 pmThe code that you copied and pasted does not use the Image.Transparent property (not 100% sure, but I'd even suggest to turn it off in this example).I've tried off and on and never seen the beaufiful and colored image, except once at the start of my tests (three or four days ago), at one point, by randomly changing things here and there, I got the pretty image but as I was starting to get tired I didn't think about making a screenshot of the image and code, what a shame... Thanks a lot for the bug report in my other post. ---------------------------------------------------------------------- Handoko · 2024-05-23 18:03 I tested the code on Ubuntu Mate 23.10 GTK2 using Lazarus 3.0 64-bit. The "ok 32" message was fired. See the result on screenshot.png below. The only thing I couldn't make it works is, the saved bmp did not support transparency. See the saved-image.png below. (to reduce the file size, I converted the bmp to png) This is the code I used: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, Forms, Graphics, StdCtrls, fpImage, fpCanvas, IntfGraphics, ExtCtrls,  LazCanvas, Dialogs; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    Image1: TImage;    procedure Button1Click(Sender: TObject);  end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject);var  bmp: TBitmap;  img: TLazIntfImage;  cnv: TLazCanvas;begin  bmp := TBitmap.Create;  try    bmp.PixelFormat := pf32Bit;           // IMPORTANT!    bmp.SetSize(Image1.Width, Image1.Height);    bmp.Transparent := True;    bmp.TransparentColor := clBlack;    bmp.Clear;    bmp.TransparentColor := clBlack;    bmp.Transparent := True;    img := bmp.CreateIntfImage;    try      cnv := TLazCanvas.Create(img);      try        cnv.DrawingMode := dmAlphaBlend;  // This activates the alpha-blend mode.         // Background        cnv.Pen.Style := psClear;        cnv.Brush.FPColor := colTransparent;        cnv.FillRect(0, 0, img.Width, img.Height);         // Yellow opaque rectangle        cnv.Brush.FPColor := FPColor($FFFF, $FFFF, 0);      cnv.Rectangle(10, 10, 190, 100);         // Overlapping semi- transparent red circle        cnv.Brush.FPColor := FPColor($FFFF, 0, 0, $4000);        cnv.Ellipse(60, 60, 140, 140);         // Overlapping semi-transparent blue circle        cnv.Brush.FPColor := FPColor(0, 0, $FFFF, $8000);        cnv.Ellipse(0, 100, 100, 200);    finally        cnv.Free;      end;       bmp.LoadFromIntfImage(img);      if bmp.PixelFormat = pf32bit then ShowMessage('ok 32');      bmp.SaveToFile('Test.bmp');      Image1.Picture.Assign(bmp);    finally      img.Free;    end;  finally    bmp.Free;  end;end; end. Anyone if you want to help, please the download the code, run it and report back your test result. ---------------------------------------------------------------------- Fred vS · 2024-05-23 18:41 Quote from: Handoko on May 23, 2024, 08:03:56 pmI tested the code on Ubuntu Mate 23.10 GTK2 using Lazarus 3.0 64-bit. The "ok 32" message was fired. See the result on screenshot.png below. The only thing I couldn't make it works is, the saved bmp did not support transparency. See the saved-image.png below. (to reduce the file size, I converted the bmp to png) This is the code I used: ... Anyone if you want to help, please the download the code, run it and report back your test result. Hello Handoko. On Xubuntu 22.04 x86_64. In your code, adding this gives a Test2.png with transparency (but only with png files, bmp afaik is not champion of transparency things). But strangely Test.png is without transparency.  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     ....    bmp.LoadFromIntfImage(img);      if bmp.PixelFormat = pf32bit then ShowMessage('ok 32');      bmp.SaveToFile('Test.png');      Image1.Picture.Assign(bmp);      Image1.Picture.SaveToFile('Test2.png');   // Adding this gives transparency           .... ---------------------------------------------------------------------- wp · 2024-05-23 19:04 Quote from: jipété on May 23, 2024, 07:23:31 pmWith Red-Hat ? Ubuntu ? Suse ? Other ? What a mess... The initial test was with Mint / Laz-main / FPC3.2.2 - everything was fine with gtk2, qt5 (and gtk3 with the exception of red-blue order). Then I switched to Manjaro: gtk2 - black image as reported, but: qt5 - ok, gtk3 - "half-ok" with red-blue exchanged. Some more experiments in Manjaro/gtk2: Filled the bitmap with white color before creating the intfimage -> I see the expected image, but on a white background. The same image is returned when I leave the bitmap untouched but set the IntfImg's backgroud color to colWhite = ($FFFF, FFFF, FFFF, FFFF). When I set the alpha channel (the last $FFFF) to 0 the background turns black, but the circles and the rectangle remain visible.Taking the code from the previous experiment, I switched the Image.Transparent property to true. Now the image becomes "color-transparent" - everything what was black in the prvious image becomes transparent. OK? No, because the areas where the semitransparent circles overlap still have the black background below and look too dark.Knowing that a png file can be displayed correctly with alpha channel I wrote the generated image to a stream and read it back - same result: black background with embedded circles and rectangle. ---------------------------------------------------------------------- jipété · 2024-05-24 06:33 Hello, @Handoko : with your code using Copy/Paste, with Image1.Transparent set at True, nothing displayed on the form ; with Image1.Transparent set at False, black is shown. In both cases, test.bmp is black. @Fred : with your added line, with Image1.Transparent set at True, nothing displayed on the form ; with Image1.Transparent set at False, black is shown. In both cases, test2.png is black. @wp : >>> Filled the bitmap with white color before creating the intfimage I'll be happy to read your  code, just to be sure I'll do the same as you. Anyway, this story becomes a nightmare... Maybe there is something wrong in my computer but what ? Where ? See you later, thanks for your help. ---------------------------------------------------------------------- Thaddy · 2024-05-24 06:44 Can it be that the wrong transparency pixel is picked up, because of the rounded edges from the title bar? Because that corner is black! ---------------------------------------------------------------------- wp · 2024-05-24 09:14 Quote from: jipété on May 24, 2024, 08:33:05 am@wp : >>> Filled the bitmap with white color before creating the intfimage I'll be happy to read your  code, just to be sure I'll do the same as you. I am attaching a full project, ready for the compiler, so that you can test easily. It comes with build modes for gtk2, gtk3, qt5 and windows, gtk2 pre-selected. It creates the alpha-blended image of the wiki article in two ways: Button "Create image as LazIntfImage" works with a TLazIntfImage, like in the wiki. As already noted several times this works correctly in all widgetsets, except for gtk2 where the entire image turns black (this happens now also on my Mint-VM - strange...). When the "Use white background" checkbox is checked the blackness disappears, the drawing can be seen, however on a white background.Button "Create Image as FPImage" uses the must fundamental fcl-image library to create the alpha-blended drawing. Since this cannot be displayed directly in a TImage (at least to my knowledge) I saved the image to a temporary stream and made the TImage load the image from it - now the result is correct, even on gtk2!  I'd conclude that something is wrong with TLazIntfImage in gtk2. It definitely is not your hardware. [EDIT] Filed a bug report: https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40971 ---------------------------------------------------------------------- jipété · 2024-05-24 09:28 Quote from: wp on May 24, 2024, 11:14:26 amI'd conclude that something is wrong with TLazIntfImage in gtk2. It definitely is not your hardware. Oh, your project is wonderful ! Works really fine and nice with FPimage, thanks thanks thanks ! (images and more comments later...) ---------------------------------------------------------------------- jipété · 2024-05-24 17:43 Hello everybody ! Well, nothing more to say, simply displaying my results with Debian/Gtk2 : With LazIntfImage, the black window : LazIntfImage.png With LazIntfImage and the White Background, that's fine : LazIntfImage+white_bkg.png With FPImage, with or without the White Background, the same wonderful result : FPImage.png But (because there is always a "but") I've noticed a little rounding error, I think : compare the bottoms of the blue circles, left and round from LazIntfImage, right and flat from FPImage... little_rounding_error.png see below  If I try the following snippet, the bottom of the circle is ok ; Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     // Overlapping semi-transparent blue circle    canv.Brush.FPColor := FPColor(0, 0, $FFFF, $8000);//  canv.Ellipse(0, 100, 100, 200);    canv.Ellipse(0, 100, 100, 199);(and I cannot post the fifth image showing the corrected rounding error, due to forum limits, sorry, try yourself) Two images in one file  : little_rounding_error+error_corrected.png On the left side the striked text above, on the right side, the left image is made with Bottom @ 200, and the right image is made with Bottom @ 199. And again, thank's a lot for your time. Next step, learning FPImage ! ---------------------------------------------------------------------- wp · 2024-05-24 18:14 Ah, I think this is due to a tiny inconsistency in the two drawing routines: The lower button creates the TFPMemoryImage as 200x200 pixels; since the lower circle reaches down to exactly 200 it is a bit unclear whether the pixels at y=200 are drawn or not - the old question in graphics - search the forum, there has been a recent discussion abou this. Obviously, the last pixel row is not drawn here. The upper button, on the other hand, creates the TLazIntfImages as large as the TImage component - and this is much larger than 200x200! Therefore, the lower pixel row can be drawn for sure. Please change the code so that the upper image is 200x200 px as well, and you will see the same clipping effect in both images. ---------------------------------------------------------------------- wp · 2024-05-25 12:24 Quote from: wp on May 24, 2024, 11:14:26 amButton "Create Image as FPImage" uses the must fundamental fcl-image library to create the alpha-blended drawing. Since this cannot be displayed directly in a TImage (at least to my knowledge) I saved the image to a temporary stream and made the TImage load the image from it This statement is not correct, of course... An FPImage can be assigned to the Picture property of a TImage and this be displayed in a TImage without needing a temporary stream: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button2Click(Sender: TObject);var  img: TFPMemoryImage;  canv: TFPImageCanvas;begin  img := TFPMemoryImage.Create(200, 200);  canv := TFPImageCanvas.Create(img);  try    canv.DrawingMode := dmAlphaBlend;  // This activates the alpha-blend mode     // Background    canv.Pen.Style := psClear;    canv.Brush.FPColor := colTransparent;  canv.FillRect(0, 0, img.Width, img.Height);     // Yellow opaque rectangle    canv.Brush.FPColor := FPColor($FFFF, $FFFF, 0);    canv.Rectangle(10, 10, 190, 100);     // Overlapping semi-transparent red circle    canv.Brush.FPColor := FPColor($FFFF, 0, 0, $4000);    canv.Ellipse(60, 60, 140, 140);     // Overlapping semi-transparent blue circle    canv.Brush.FPColor := FPColor(0, 0, $FFFF, $8000);    canv.Ellipse(0, 100, 100, 200);     // Display image    Image1.Picture.Assign(img);  finally    canv.Free;    img.Free;  end;end; ---------------------------------------------------------------------- jipété · 2024-05-26 11:59 Quote from: wp on May 25, 2024, 02:24:16 pmAn FPImage can be assigned to the Picture property of a TImage and this be displayed in a TImage without needing a temporary stream:Not here ! I still get a black background... To look at a nice display, the only way (for me) is to use the stream : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     ...    stream := TMemoryStream.Create;    writer := TFPWriterPNG.Create;    try      writer.UseAlpha := True;  // Make sure that the alpha channel is not dropped.      img.SaveToStream(stream, writer);      // Save to image file      img.SaveToFile('Transp_with-stream.png'); // black background !      stream.Position := 0;      Image1.Picture.LoadFromStream(stream); // no background, nice !      Image1.Picture.SaveToFile('Transp_Picture.png'); // also ok    finally      writer.Free;      stream.Free;    end;  finally    canv.Free;    img.Free;  end;end;And I've discovered a trap : we must look at the created .png in an image editor (Gimp or whatever) because if looking at the images in a FileExplorer, there is no way to distinguish between a white background and a transparent background. Study my 2 images displayed in a FileExplorer : one with white background on top and the other below with a transparent background. white-or-none And compare with the same files in The Gimp compar_classic-stream.png Another nightmare... ---------------------------------------------------------------------- wp · 2024-05-26 16:08 Quote from: jipété on May 26, 2024, 01:59:33 pmQuote from: wp on May 25, 2024, 02:24:16 pmAn FPImage can be assigned to the Picture property of a TImage and this be displayed in a TImage without needing a temporary stream:Not here ! I still get a black background... Sorry I was confused by another thread (Too many different threads for my limited brain...). You are absoluteley right. Quote from: jipété on May 26, 2024, 01:59:33 pmAnd I've discovered a trap : we must look at the created .png in an image editor (Gimp or whatever) because if looking at the images in a FileExplorer, there is no way to distinguish between a white background and a transparent background. Study my 2 images displayed in a FileExplorer : one with white background on top and the other below with a transparent background. white-or-none And compare with the same files in The Gimp compar_classic-stream.png Well, when Gimp displays the checkboard background for an alpha- channel image you know for sure that the alpha channel and the transparency exists and is correct. When other programs do display a white background, it's not the image's fault. Quote from: jipété on May 26, 2024, 01:59:33 pmAnother nightmare... I would not call it a "nightmare". Just be prepared that the transparency of images may be a bit difficult to detect. My default image viewer, for example is IrfanView; I set its background to some unusual color; with that it not very likely that I can be fooled about the presence of transparency. ---------------------------------------------------------------------- jipété · 2024-05-26 16:26 Quote from: wp on May 26, 2024, 06:08:47 pmYou are absoluteley right. Thanks, ---------------------------------------------------------------------- KodeZwerg · 2024-05-26 16:38 Quote from: wp on May 26, 2024, 06:08:47 pmMy 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. Quote from: wp on May 26, 2024, 06:08:47 pmI set its background to some unusual color; with that it not very likely that I can be fooled about the presence of transparency.clFuchsia Hello Telekom haha ---------------------------------------------------------------------- wp · 2024-05-26 16:52 Quote from: KodeZwerg on May 26, 2024, 06:38:57 pmclFuchsia 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é · 2024-05-27 13:15 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i lii.DataDescription.Depth // is always at 24 lii.DataDescription.BitsPerPixel // is always at 32How 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TLazWriterBMP.Initialize(AImage: TLazIntfImage);begin  // set BPP  // we can also look at PixelFormat, but it can be inexact <-- ha ha ha ! lol !  BitsPerPixel := AImage.DataDescription.Depth;end;BitsPerPixel := AImage.DataDescription.Depth; ok, so why do I read 32 24 ? retrieve_descr.png What is this mess (to be polite) ? ---------------------------------------------------------------------- KodeZwerg · 2024-05-27 14:18 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. ---------------------------------------------------------------------- jipété · 2024-05-27 15:04 Quote from: KodeZwerg on May 27, 2024, 04:18:58 pmTBitmap 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     Img.LoadFromFile(ReadFile);    Img.SaveToFile(WriteFile);, I don't imagine what to do to keep the 32bits structure... ---------------------------------------------------------------------- KodeZwerg · 2024-05-27 15:50 Quote from: jipété on May 27, 2024, 05:04:26 pmThanks for the tip.You are welcomed. Quote from: jipété on May 27, 2024, 05:04:26 pmAnd 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     Img.LoadFromFile(ReadFile);    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. ---------------------------------------------------------------------- jipété · 2024-05-27 16:45 Quote from: KodeZwerg on May 27, 2024, 05:50:43 pmWe 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 Quote from: KodeZwerg on May 27, 2024, 05:50:43 pm... 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 · 2024-05-27 17:11 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. ---------------------------------------------------------------------- wp · 2024-05-27 17:56 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i { From Michael Van Canneyt's article about the Canvas } program imgconv; {$mode objfpc}{$h+} uses  FPWriteXPM, FPWritePNG, FPWriteBMP, fpwritejpeg, fpwritetga,  FPReadXPM, FPReadPNG, FPReadBMP, fpreadjpeg, fpreadtga,  fpreadpnm, FPImage, sysutils;var  img : TFPMemoryImage;  ReadFile, WriteFile : string;  readerClass: TFPCustomImageReaderClass;  writerClass: TFPCustomImageWriterClass;  reader: TFPCustomImageReader;  writer: TFPCustomImageWriter;begin  if paramcount = 2 then  begin    ReadFile := paramstr(1);    WriteFile := paramstr(2);  end  else  begin    Writeln('Usage: imconv infile outfile');    Halt(1);  end;  If CompareText(ReadFile,WriteFile)=0 then  begin    Writeln('Input file cannot be the same as output file');    Halt(1);  end;   readerClass := TFPMemoryImage.FindReaderfromFileName(ReadFile);  if readerClass = nil then  begin    WriteLn('The graphics format of ' + ReadFile + ' is not supported for reading.');    Halt(1);  end;   writerClass := TFPMemoryImage.FindWriterFromFileName(WriteFile);  if writerClass = nil then  begin    WriteLn('The graphics format of ' + ReadFile + ' is not supported for writing.');    Halt(1);  end;   Img:=TFPMemoryImage.Create(0,0);  try    reader := readerClass.Create;    Img.LoadFromFile(ReadFile, reader);    reader.Free;     writer := writerClass.Create;    try      if writer is TFPWriterPNG then        TFPWriterPNG(writer).UseAlpha :=true;    Img.SaveToFile(WriteFile, writer);    finally      writer.Free;    end;   Finally    Img.Free;  end;end. ---------------------------------------------------------------------- wp · 2024-05-27 18:07 Quote from: KodeZwerg on May 27, 2024, 05:50:43 pmIn 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é · 2024-05-27 18:18 Quote from: wp on May 27, 2024, 07:56:08 pmWhen I use the code in Michael Van Canneyt's article (which is an excellent introduction to fcl-image, by the way)Hé hé ! Quote from: wp on May 27, 2024, 07:56:08 pmHere 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 ! Quote from: wp on May 27, 2024, 08:07:09 pmI'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...) Quote from: wp on May 27, 2024, 08:07:09 pm(along with a possible input image, 32-bit bmps are hard to find). Hard to find but really easy to create with The Gimp,  The attached file has been made with PixelFormat = 32bits, BitsPerPïxels = 32 also and BytesPerPixel = 4. HTH, src32.bmp ---------------------------------------------------------------------- KodeZwerg · 2024-05-27 18:28 Attached is a 32bit Bitmap test file. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);var  LBitmap: TBitmap;begin  LBitmap := TBitmap.Create;  try    LBitmap.LoadFromFile('Test.bmp');  LBitmap.PixelFormat := pf32bit;    LBitmap.SaveToFile('Test2.bmp');  finally    LBitmap.Free;  end;end;It will save a 32bit bitmap. ---------------------------------------------------------------------- wp · 2024-05-27 21:56 Quote from: KodeZwerg on May 27, 2024, 08:28:25 pmAttached is a 32bit Bitmap test file. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);var  LBitmap: TBitmap;begin  LBitmap := TBitmap.Create;  try    LBitmap.LoadFromFile('Test.bmp');  LBitmap.PixelFormat := pf32bit;    LBitmap.SaveToFile('Test2.bmp');  finally    LBitmap.Free;  end;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 · 2024-05-27 22:12 Quote from: wp on May 27, 2024, 11:56:17 pmAh, 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 Quote from: wp on May 27, 2024, 11:56:17 pmAnd 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 ---------------------------------------------------------------------- KodeZwerg · 2024-05-28 00:05 Quote from: jipété on May 27, 2024, 03:15:32 pmMany years ago, I've written a little program to look inside the bitmaps header, where the data are okThis is how I would fetch amazing fast the needed info: This demonstration does not do any kind of checking, it just try to do its job done by assuming all is cool. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program project1; {$IfDef Windows}{$AppType Console}{$EndIf Windows} uses  SysUtils, Classes, BMPcomn; type  TFullBitmapHeader = packed record  BitMapFileHeader: TBitMapFileHeader;    BitMapInfoHeader: TBitMapInfoHeader;  end; function GetBitmapHeader(const AFilename: string): TFullBitmapHeader;var  FileStream: TFileStream;begin  FileStream := TFileStream.Create(AFilename, fmOpenRead);  try    FillChar(Result, SizeOf(Result), 0);    FileStream.Position := 0;    FileStream.Read(Result.BitMapFileHeader.bfType, SizeOf(Result.BitMapFileHeader.bfType));    FileStream.Read(Result.BitMapFileHeader.bfSize, SizeOf(Result.BitMapFileHeader.bfSize));    FileStream.Read(Result.BitMapFileHeader.bfReserved, SizeOf(Result.BitMapFileHeader.bfReserved));    FileStream.Read(Result.BitMapFileHeader.bfOffset, SizeOf(Result.BitMapFileHeader.bfOffset));    FileStream.Read(Result.BitMapInfoHeader.Size, SizeOf(Result.BitMapInfoHeader.Size));    FileStream.Read(Result.BitMapInfoHeader.Width, SizeOf(Result.BitMapInfoHeader.Width));    FileStream.Read(Result.BitMapInfoHeader.Height, SizeOf(Result.BitMapInfoHeader.Height));    FileStream.Read(Result.BitMapInfoHeader.Planes, SizeOf(Result.BitMapInfoHeader.Planes));    FileStream.Read(Result.BitMapInfoHeader.BitCount, SizeOf(Result.BitMapInfoHeader.BitCount));    FileStream.Read(Result.BitMapInfoHeader.Compression, SizeOf(Result.BitMapInfoHeader.Compression));    FileStream.Read(Result.BitMapInfoHeader.SizeImage, SizeOf(Result.BitMapInfoHeader.SizeImage));    FileStream.Read(Result.BitMapInfoHeader.XPelsPerMeter, SizeOf(Result.BitMapInfoHeader.XPelsPerMeter));    FileStream.Read(Result.BitMapInfoHeader.YPelsPerMeter, SizeOf(Result.BitMapInfoHeader.YPelsPerMeter));    FileStream.Read(Result.BitMapInfoHeader.ClrUsed, SizeOf(Result.BitMapInfoHeader.ClrUsed));    FileStream.Read(Result.BitMapInfoHeader.ClrImportant, SizeOf(Result.BitMapInfoHeader.ClrImportant));  finally    FileStream.Free;  end;end; var  BitmapHeader: TFullBitmapHeader;begin  WriteLn('Quick Bitmap Info by KodeZwerg.');  if FileExists(ParamStr(1)) then    begin      BitmapHeader := GetBitmapHeader(ParamStr(1));      WriteLn('Type: ' + IntToHex(Swap(BitmapHeader.BitMapFileHeader.bfType), SizeOf(BitmapHeader.BitMapFileHeader.bfType)));      WriteLn('Filesize: ' + IntToStr(BitmapHeader.BitMapFileHeader.bfSize));      WriteLn('Reserved: ' + IntToHex(Swap(BitmapHeader.BitMapFileHeader.bfReserved), SizeOf(BitmapHeader.BitMapFileHeader.bfReserved)));      WriteLn('Offset: ' + IntToStr(BitmapHeader.BitMapFileHeader.bfOffset));      WriteLn('Structure Size: ' + IntToStr(BitmapHeader.BitMapInfoHeader.Size));      WriteLn('Width: ' + IntToStr(BitmapHeader.BitMapInfoHeader.Width));      WriteLn('Height: ' + IntToStr(BitmapHeader.BitMapInfoHeader.Height));      WriteLn('Planes: ' + IntToStr(BitmapHeader.BitMapInfoHeader.Planes));      WriteLn('Bits Per Pixel: ' + IntToStr(BitmapHeader.BitMapInfoHeader.BitCount));    WriteLn('Compression Method: ' + IntToStr(BitmapHeader.BitMapInfoHeader.Compression));      WriteLn('Image Size: ' + IntToStr(BitmapHeader.BitMapInfoHeader.SizeImage));      WriteLn('Horizontal Resolution: ' + IntToStr(BitmapHeader.BitMapInfoHeader.XPelsPerMeter));      WriteLn('Vertical Resolution: ' + IntToStr(BitmapHeader.BitMapInfoHeader.YPelsPerMeter));      WriteLn('Colors Used: ' + IntToStr(BitmapHeader.BitMapInfoHeader.ClrUsed));      WriteLn('Colors Important: ' + IntToStr(BitmapHeader.BitMapInfoHeader.ClrImportant));    end  else    WriteLn('Usage: ' + ExtractFileName(ParamStr(0)) + ' "image.bmp"');  WriteLn('');  WriteLn('Done.');  {$IfDef Windows}  ReadLn;  {$EndIf Windows}end. ---------------------------------------------------------------------- jipété · 2024-06-27 17:45 Good evening, One month later, I come back here because nothing is moving forward... A few minute before, I started with  the two files kindly provided by me on May 27 (src32.bmp) and by KodeZwerg on May 27 also (test.zip), the first one has a BITMAPHEADER version 4 when the second has version 1, and I always used this code from the wiki : TLazIntfImage.LoadFromFile https://wiki.freepascal.org/Developing_with _Graphics#TLazIntfImage.LoadFromFile QuoteHere is an example how to load an image directly into a TLazIntfImage. It initializes the TLazIntfImage to a 32bit RGBA format. Keep in mind that this is probably not the native format of your screen.Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses LazLogger, Graphics, IntfGraphics, GraphType;procedure TForm1.FormCreate(Sender: TObject);var  AImage: TLazIntfImage;  lRawImage: TRawImage;begin  // create a TLazIntfImage with 32 bits per pixel, alpha 8bit, red 8 bit, green 8bit, blue 8bit,  // Bits In Order: bit 0 is pixel 0, Top To Bottom: line 0 is top  lRawImage.Init;  lRawImage.Description.Init_BPP32_A8R8G8B8_BIO_TTB(0,0);  lRawImage.CreateData(false);  AImage := TLazIntfImage.Create(0,0);  try    AImage.SetRawImage(lRawImage);    // Load an image from disk.  // It uses the file extension to select the right registered image reader.    // The AImage will be resized to the width, height of the loaded image.//    AImage.LoadFromFile('lazarus/examples/openglcontrol /data/texture1.png');    AImage.LoadFromFile(openpicturedialog1.FileName);    debugln(['TForm1.FormCreate ',AImage.Width,' ',AImage.Height]);  finally    AImage.Free;  end;end;and just before the finally line I added the command below after changing the last word : QuoteLoading a TLazIntfImage into a TImage The pixel data of a TImage is the TImage.Picture property, which is of type TPicture. TPicture is a multi format container containing one of several common image formats like Bitmap, Icon, Jpeg or PNG . Usually you will use the TPicture.Bitmap to load a TLazIntfImage:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     Image1.Picture.Bitmap.LoadFromIntfImage(IntfImg);becomes Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     Image1.Picture.Bitmap.LoadFromIntfImage(AImage); Result, it only works with the v1 file, with v4 nothing is displayed while the preview image in the OpenPictureDialog is fine...