Recent

Author Topic: [SOLVED] Transparent background in TFPMemoryImage saved to a PNG stream, howto  (Read 571 times)

alpine

  • Hero Member
  • *****
  • Posts: 1412
I'm kinda stuck here, I want to do some drawing on a transparent background and save it to a png stream. It should be something simple, but I can't figure it out ...

Thanks in advance!

Code: Pascal  [Select][+][-]
  1.   Image := TFPMemoryImage.Create(ARect.Width, ARect.Height);
  2.   Canvas := TFPImageCanvas.Create(Image);
  3.   Writer := TFPWriterPNG.Create;
  4.  
  5.   with TFPWriterPNG(Writer) do
  6.   begin
  7.     Indexed := False;
  8.     WordSized := False;
  9.     UseAlpha := False;
  10.     GrayScale := False;
  11.   end;
  12.  
  13.   try
  14.     with Canvas as TFPImageCanvas do
  15.     begin
  16.       Brush.FPcolor := colTransparent //Desn't work!
  17.       Brush.Style := bsSolid;
  18.  
  19.       // Clear background
  20.       Clear;
  21.  
  22.      // Some drawing stuff here...
  23.  
  24.     end;
  25.     Image.SaveToStream(AStream, Writer);
  26.   finally
  27.     Canvas.Free;
  28.     Image.Free;
  29.     Writer.Free;
  30.   end;
  31.  
« Last Edit: January 12, 2026, 11:25:47 am by alpine »
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

wp

  • Hero Member
  • *****
  • Posts: 13350
Re: Transparent background in TFPMemoryImage saved to a PNG stream, howto
« Reply #1 on: January 11, 2026, 07:04:50 pm »
When your Png-Writer has "UseAlpha=false" it does not write the alpha channel. When you set it to true, transparency should be in the file.

This sample project works:
Code: Pascal  [Select][+][-]
  1. program alphablend;
  2. uses
  3.   FPImage, FPImgCanv, FPCanvas, FPWritePNG;
  4. var
  5.   img: TFPMemoryImage;
  6.   canvas: TFPImageCanvas;
  7.   writer: TFPWriterPNG;
  8. begin
  9.   img := TFPMemoryImage.Create(200, 200);
  10.   canvas := TFPImageCanvas.Create(img);
  11.   try
  12.     canvas.DrawingMode := dmAlphaBlend;  // This activates the alpha-blend mode
  13.  
  14.     // Background
  15.     canvas.Pen.Style := psClear;
  16.     canvas.Brush.FPColor := colTransparent;
  17.     canvas.Clear;
  18. //    canvas.FillRect(0, 0, img.Width, img.Height);
  19.  
  20.     // Yellow opaque rectangle
  21.     canvas.Brush.FPColor := FPColor($FFFF, $FFFF, 0);
  22.     canvas.Rectangle(10, 10, 190, 100);
  23.  
  24.     // Overlapping semi-transparent red circle
  25.     canvas.Brush.FPColor := FPColor($FFFF, 0, 0, $4000);
  26.     canvas.Ellipse(60, 60, 140, 140);
  27.  
  28.     // Overlapping semi-transparent blue circle
  29.     canvas.Brush.FPColor := FPColor(0, 0, $FFFF, $8000);
  30.     canvas.Ellipse(0, 100, 100, 200);
  31.  
  32.     writer := TFPWriterPNG.Create;
  33.     try
  34.       writer.UseAlpha := true;
  35.       img.SaveToFile('alphablend.png', writer);
  36.     finally
  37.       writer.Free;
  38.     end;
  39.   finally
  40.     canvas.Free;
  41.     img.Free;
  42.   end;
  43. end.
« Last Edit: January 11, 2026, 07:08:20 pm by wp »

alpine

  • Hero Member
  • *****
  • Posts: 1412
Very much appreciated, thank you wp!
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

ginoo

  • Full Member
  • ***
  • Posts: 149
Re: Transparent background in TFPMemoryImage saved to a PNG stream, howto
« Reply #3 on: January 13, 2026, 09:31:18 am »
When your Png-Writer has "UseAlpha=false" it does not write the alpha channel. When you set it to true, transparency should be in the file.

This sample project works:
Code: Pascal  [Select][+][-]
  1. program alphablend;
  2. uses
  3.   FPImage, FPImgCanv, FPCanvas, FPWritePNG;
  4. var
  5.   img: TFPMemoryImage;
  6.   canvas: TFPImageCanvas;
  7.   writer: TFPWriterPNG;
  8. begin
  9.   img := TFPMemoryImage.Create(200, 200);
  10.   canvas := TFPImageCanvas.Create(img);
  11.   try
  12.     canvas.DrawingMode := dmAlphaBlend;  // This activates the alpha-blend mode
  13.  
  14.     // Background
  15.     canvas.Pen.Style := psClear;
  16.     canvas.Brush.FPColor := colTransparent;
  17.     canvas.Clear;
  18. //    canvas.FillRect(0, 0, img.Width, img.Height);
  19.  
  20.     // Yellow opaque rectangle
  21.     canvas.Brush.FPColor := FPColor($FFFF, $FFFF, 0);
  22.     canvas.Rectangle(10, 10, 190, 100);
  23.  
  24.     // Overlapping semi-transparent red circle
  25.     canvas.Brush.FPColor := FPColor($FFFF, 0, 0, $4000);
  26.     canvas.Ellipse(60, 60, 140, 140);
  27.  
  28.     // Overlapping semi-transparent blue circle
  29.     canvas.Brush.FPColor := FPColor(0, 0, $FFFF, $8000);
  30.     canvas.Ellipse(0, 100, 100, 200);
  31.  
  32.     writer := TFPWriterPNG.Create;
  33.     try
  34.       writer.UseAlpha := true;
  35.       img.SaveToFile('alphablend.png', writer);
  36.     finally
  37.       writer.Free;
  38.     end;
  39.   finally
  40.     canvas.Free;
  41.     img.Free;
  42.   end;
  43. end.

Sorry if I ask you a question, how do you write text inside TFPMemoryImage?

wp

  • Hero Member
  • *****
  • Posts: 13350

ginoo

  • Full Member
  • ***
  • Posts: 149
I did it, you need to create a TFreeTypeFont.

wp

  • Hero Member
  • *****
  • Posts: 13350
What do you want to say?

This is the complete code that I used for testing (on Windows), it is working (except of a drawing glitch of the character boundary blocks above alpha-blended parts - I reported this in https://gitlab.com/freepascal.org/fpc/source/-/issues/41577). [EDIT - the issue already has been fixed, that was fast!]

Code: Pascal  [Select][+][-]
  1. program alphablend;
  2. uses
  3.   FPImage, FPImgCanv, FPCanvas, FTFont, FPWritePNG;
  4. var
  5.   img: TFPMemoryImage;
  6.   canvas: TFPImageCanvas;
  7.   writer: TFPWriterPNG;
  8.   font: TFreeTypeFont;
  9. begin
  10.   // initialize free type font manager
  11.   FTFont.InitEngine;
  12.   {$IFNDEF MSWINDOWS}
  13.   FontMgr.SearchPath:='/usr/share/fonts/truetype/ttf-dejavu/';  // not needed on Windows
  14.   {$ENDIF}
  15.   font:=TFreeTypeFont.Create;
  16.  
  17.   img := TFPMemoryImage.Create(200, 200);
  18.   canvas := TFPImageCanvas.Create(img);
  19.   try
  20.     canvas.DrawingMode := dmAlphaBlend;  // This activates the alpha-blend mode
  21.  
  22.     // Background
  23.     canvas.Pen.Style := psClear;
  24.     canvas.Brush.FPColor := colTransparent;
  25.     canvas.Clear;
  26.  
  27.     // Yellow opaque rectangle
  28.     canvas.Brush.FPColor := FPColor($FFFF, $FFFF, 0);
  29.     canvas.Rectangle(10, 10, 190, 100);
  30.  
  31.     // Overlapping semi-transparent red circle
  32.     canvas.Brush.FPColor := FPColor($FFFF, 0, 0, $4000);
  33.     canvas.Ellipse(60, 60, 140, 140);
  34.  
  35.     // Overlapping semi-transparent blue circle
  36.     canvas.Brush.FPColor := FPColor(0, 0, $FFFF, $8000);
  37.     canvas.Ellipse(0, 90, 100, 190);
  38.  
  39.     // Paint text
  40.     canvas.Font := font;
  41.     canvas.Font.Name := 'DejaVuSans';
  42.     canvas.Font.Size := 64;
  43.     canvas.Font.FPColor := FPColor($0FFF, $0FFF, $0FFF, $6000);
  44.     canvas.TextOut(5, 140, 'Test');
  45.  
  46.     // Write to file
  47.     writer := TFPWriterPNG.Create;
  48.     try
  49.       writer.UseAlpha := true;
  50.       img.SaveToFile('alphablend.png', writer);
  51.     finally
  52.       writer.Free;
  53.     end;
  54.   finally
  55.     canvas.Free;
  56.     img.Free;
  57.     font.Free;
  58.   end;
  59. end.            
« Last Edit: January 13, 2026, 05:46:03 pm by wp »

 

TinyPortal © 2005-2018