Yet again transparent PNG lazarus / 39-Graphics ---------------------------------------------------------------------- Zaher · 2017-01-14 13:18 I want to make png have text with tranpsparent background, all i got it black background, even in LazPaint it open it as black, i tried most example in the forum, but same. I test example from wiki with some modification. http://wiki.freepascal.org/Graphics_-_Working_with_TCanvas 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 PaintAliased(Canvas: TCanvas; x,y: integer; const TheText: string);var  w,h: integer;  IntfImg: TLazIntfImage;  Img: TPortableNetworkGraphic;  dy: Integer;  dx: Integer;  col: TFPColor;  FontColor: TColor;  c: TColor;begin  w:=0;  h:=0;  Canvas.GetTextSize(TheText,w,h);  if (w<=0) or (h<=0) then exit;  Img:=TPortableNetworkGraphic.Create;  IntfImg:=nil;  try    // paint text to a bitmap    Img.Masked:=true;    Img.SetSize(w,h);    Img.Canvas.Brush.Style:=bsSolid;    Img.Canvas.Brush.Color:=clWhite;  Img.Canvas.FillRect(0,0,w,h);    Img.Canvas.Font:=Canvas.Font;    Img.Canvas.TextOut(0,0,TheText);    // get memory image    IntfImg:=Img.CreateIntfImage;    // replace gray pixels    FontColor:=ColorToRGB(Canvas.Font.Color);    for dy:=0 to h-1 do begin      for dx:=0 to w-1 do begin        col:=IntfImg.Colors[dx,dy];        c:=FPColorToTColor(col);        if c<>FontColor then          IntfImg.Colors[dx,dy]:=colTransparent;    end;    end;    // create bitmap    Img.LoadFromIntfImage(IntfImg);  Img.Transparent := True;    Img.TransparentColor := clBlack;    Img.SaveToFile('d:\temp\myfont4.png');    // paint    Canvas.Draw(x,y,Img);  finally    IntfImg.Free;    Img.Free;  end;end;  Any idea why i cant save as transparent file? ---------------------------------------------------------------------- lainz · 2017-01-14 13:28 You need to do it all yourself with the stuff that comes with lazarus or you can use another library? ---------------------------------------------------------------------- Zaher · 2017-01-14 16:56 I don't like to use external big library, if it small it is not problem I prefer official one that come with Lazarus of Freepascal I don't like to use bgrabitmap it is so big for my project https://github.com/bgrabitmap/bgrabitmap/tree/master/bgrabitmap ---------------------------------------------------------------------- lainz · 2017-01-14 19:21 Is not that big, you only need to include two files to work with it =) ---------------------------------------------------------------------- derek.john.evans · 2017-01-14 19:56 First up::: There is a difference between alpha transparent, and keycolor transparent. The Transparent/TransparentColor properties are for keycolor transparency. Keycolor comes in 2 flavours. Runtime color lookup and "pre calculated" masks. Lazarus uses masks as apposed to DirectDraw which supports runtime color lookup. Masked keycolor transparency pre-creates a secondary mask. The background is first AND'ed with the mask to clear bits for the bitmap. Then the bitmap is OR'ed onto the background. Anyway  None of that matters, since a mask is not saved to the PNG. You are wanting to create a 32bit BGRA transparent PNG. The problem is, the GDI (TCanvas) doesn't support 32bit. GDI wil draw to a 32bit bitmap, but it will set the alpha to zero, effectively making your drawing transparent. There are 3 ways to fix this. 1) Save to a 24bit image. It works, but then you loose your alpha. 2) Iterate the raw pixels and fill in the alpha channel based on a key color. This works for images created via the GDI, but can be an issue if you are drawing on top of a loaded picture. 3) inc/dec the alpha before/after drawing. This is a little trick I came up with . The GDI draws using alpha 0. We want it alpha 255. So, if we increase the apha by 1 before drawing, and then draw, then decrease the alpha by 1, the original alpha will remain unchanged, but everything which was drawn at alpha 0, will now be 255. ie: Opaque. Anything that was already 255 will also remain at 255. The problem then is, how to make this easy to use: 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 type   TPictureEx = class(TPicture)  strict private    FAlpha: byte;  public    procedure UseAlpha(AAlpha: integer);    procedure EndAlpha;  end; procedure TPictureEx.UseAlpha(AAlpha: integer);var  LPos, LEnd: PByte;begin  Assert(Bitmap.PixelFormat = pf32bit);  FAlpha := 256 - AAlpha;  Bitmap.BeginUpdate;  LPos := Bitmap.RawImage.Data + 3;  LEnd := Bitmap.RawImage.Data + Bitmap.RawImage.DataSize;  while LPos < LEnd do begin    Inc(LPos^, FAlpha);    Inc(LPos, 4);  end;end; procedure TPictureEx.EndAlpha;var  LPos, LEnd: PByte;begin  Assert(Bitmap.PixelFormat = pf32bit);  LPos := Bitmap.RawImage.Data + 3;  LEnd := Bitmap.RawImage.Data + Bitmap.RawImage.DataSize;  while LPos < LEnd do begin    Dec(LPos^, FAlpha);    Inc(LPos, 4);  end;  Bitmap.EndUpdate;end;   Then you can do stuff like: 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   with TPictureEx.Create do begin    try      Bitmap.PixelFormat := pf32bit;      Bitmap.SetSize(100, 100);      UseAlpha(0);      try        Bitmap.Canvas.Brush.Color := clBlack;        Bitmap.Canvas.FillRect(0, 0, Width, Height);      finally        EndAlpha;      end;      UseAlpha(255);      try        Bitmap.Canvas.Brush.Color := clRed;      Bitmap.Canvas.Ellipse(0, 0, Width, Height);      finally        EndAlpha;      end;      UseAlpha(128);      try        Bitmap.Canvas.Brush.Color := clBlue;        Bitmap.Canvas.FillRect(20, 20, Width - 20, Height - 20);      finally        EndAlpha;      end;      UseAlpha(255);      try        Bitmap.Canvas.Brush.Style := bsClear;        Bitmap.Canvas.Font.Color := clWhite;        Bitmap.Canvas.Font.Height := 40;        Bitmap.Canvas.TextOut(0, 0, 'Aplha');        Bitmap.Canvas.Font.Height := 35;        Bitmap.Canvas.TextOut(0, 45, 'Picture');      finally        EndAlpha;      end;      SaveToFile('c:\test.png');    finally      Free;    end;  end; Note, 1) This method allows you to draw via the GDI at any alpha. 2) This method does _not_ support blending. 3) Text will look chunky because the font smoothing is not valid. Anyway, that might help. Its only a quick and dirty way of drawing alpha graphics using the GDI. Edit: A little talked about unit is imagemagick which comes with FreePascal. http://www.imagemagick.org/script/index.php It might suit your purposes if you dont like BGRABitmap. ---------------------------------------------------------------------- wp · 2017-01-14 22:12 Here's another example which does not need any external libraries. It is based on LazIntfImage and FreeType (see also: http://forum.lazarus. freepascal.org/index.php/topic,26426.msg162327.html#msg162327). And if you use the forum search for FreeType LazIntfImage you'll certainly find more: 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  GraphType, FpImage, intfGraphics, EasyLazFreeType, LazFreeTypeIntfDrawer; procedure TForm1.Button1Click(Sender: TObject);var  png: TPortableNetworkGraphic;  img: TLazIntfImage;  drw: TIntfFreeTypeDrawer;  fnt: TFreeTypeFont;begin  png := TPortableNetworkGraphic.Create;  try    img := TLazIntfImage.Create(0,0, [riqfRGB, riqfAlpha]);    try      img.SetSize(400, 200);      drw := TIntfFreeTypeDrawer.Create(img);    fnt := TFreeTypeFont.Create;      try        fnt.Name := 'c:\Windows\fonts\Arial.ttf';        fnt.SizeInPixels := 36;        fnt.Hinted := true;        fnt.ClearType := true;        fnt.Quality := grqHighQuality;         // Transparent background        drw.FillPixels(colTransparent);        // Yellow rectangle on transparent background        drw.FillRect(30, 30, img.Width-30, img.Height-30, colYellow);        // Text, partially on transparent background, partially on yellow rectangle        drw.DrawText('Lazarus', fnt, 0, 100, colRed);         png.LoadFromIntfImage(img);        png.saveToFile('d:\test.png');    finally        fnt.Free;        drw.Free;      end;    finally      img.Free;    end;  finally    png.Free;  end;end; ---------------------------------------------------------------------- lainz · 2017-01-14 23:12 Of course you can try bgrabitmap if you want, at least give it a try, then decide if you want to use it or not: These are all the uses you need, 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  BGRABitmap, BGRABitmapTypes; Or only use BGRABitmap unit alone if you don't need to change the font quality and use BGRAPixel (for example text with alpha on it). You can use TColor only if you want it, or if you need the background only to be transparent and not the text itself. 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 var  bmp: TBGRABitmap;begin  bmp := TBGRABitmap.Create(640, 480);  bmp.FontQuality := fqFineAntialiasing; // optional  bmp.FontHeight := 30;  bmp.TextOut(10, 10, 'Hello World', clBlack); // BGRABlack or BGRA(r, g, b, a) to specify easily rgba values  bmp.SaveToFile('text.png');  bmp.Free; ---------------------------------------------------------------------- Zaher · 2019-12-24 20:18 Quote from: wp on January 14, 2017, 11:12:34 pmHere's another example which does not need any external libraries. It is based on LazIntfImage and FreeType (see also: http://forum.lazarus.freepascal.o rg/index.php/topic,26426.msg162327.html#msg162327). And if you use the forum search for FreeType LazIntfImage you'll certainly find more: 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  GraphType, FpImage, intfGraphics, EasyLazFreeType, LazFreeTypeIntfDrawer; procedure TForm1.Button1Click(Sender: TObject);var  png: TPortableNetworkGraphic;  img: TLazIntfImage;  drw: TIntfFreeTypeDrawer;  fnt: TFreeTypeFont;begin  png := TPortableNetworkGraphic.Create;  try    img := TLazIntfImage.Create(0,0, [riqfRGB, riqfAlpha]);    try      img.SetSize(400, 200);      drw := TIntfFreeTypeDrawer.Create(img);    fnt := TFreeTypeFont.Create;      try        fnt.Name := 'c:\Windows\fonts\Arial.ttf';        fnt.SizeInPixels := 36;        fnt.Hinted := true;        fnt.ClearType := true;        fnt.Quality := grqHighQuality;         // Transparent background        drw.FillPixels(colTransparent);        // Yellow rectangle on transparent background        drw.FillRect(30, 30, img.Width-30, img.Height-30, colYellow);        // Text, partially on transparent background, partially on yellow rectangle        drw.DrawText('Lazarus', fnt, 0, 100, colRed);         png.LoadFromIntfImage(img);        png.saveToFile('d:\test.png');    finally        fnt.Free;        drw.Free;      end;    finally      img.Free;    end;  finally    png.Free;  end;end; Thank you, that solved my problem.