[SOLVED] Create and save PNG lazarus / 39-Graphics ---------------------------------------------------------------------- tk · 2016-12-30 11:53 Hi, I would like to create a new PNG image, modify its pixels and save it. I adapted code from following example (http://wiki.lazarus.freepas cal.org/Developing_with_Graphics#Drawing_text_with_sharp_edges_.28non_ antialiased.29) but it does not work properly, alpha channel is not respected: 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  IntfGraphics, FPImage; { TForm1 } procedure TForm1.Button1Click(Sender: TObject);var  I, J, W, H: Integer;  FC: TFPColor;  IM: TLazIntfImage;  Png: TPortableNetworkGraphic;begin  W := 32;  H := 32;  Png := TPortableNetworkGraphic.Create;  try    Png.SetSize(W, H);    IM := Png.CreateIntfImage;    try      for I := 0 to W - 1 do      begin        for J := 0 to H - 1 do        begin        FC.red := (128 + I) shl 8;          FC.green := (128 + J) shl 8;          FC.blue := 128 shl 8;          FC.alpha := 128 shl 8; // no matter what value here, always get full opacity          IM.Colors[I, J] := FC;        end;      end;      Png.LoadFromIntfImage(IM);    finally      IM.Free;    end;    Png.SaveToFile('test.png');  finally    Png.Free;  end;end; Bug? ---------------------------------------------------------------------- derek.john.evans · 2016-12-30 13:05 TPortableNetworkGraphic.CreateIntfImage doesn't create an image that supports alpha. It also loads the PNG into the image, which isn't required if you are creating a new image. Also, you dont need TPortableNetworkGraphic, since TLazIntfImage will load/save png/jpeg/etc. So, try this: 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  X, Y: integer;  LColor: TFPColor;  LImage: TLazIntfImage;begin  LImage := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);  try    LImage.SetSize(32, 32);    for X := 0 to LImage.Width - 1 do begin    for Y := 0 to LImage.Height - 1 do begin        LColor.red := (128 + X) shl 8;        LColor.green := (128 + Y) shl 8;        LColor.blue := 128 shl 8;        LColor.alpha := 200 shl 8; // no matter what value here, always get full opacity        LImage.Colors[X, Y] := LColor;      end;    end;    LImage.SaveToFile('test.png');  finally  LImage.Free;  end;end;   NOTE: There does seem to be a bug in TLazIntfImage which I've know about for a while. You cant provide a width/height via the constructor. Hence the additional SetSize() command. ---------------------------------------------------------------------- derek.john.evans · 2016-12-30 13:12 O, bugger. You do need TPortableNetworkGraphic. TLazIntfImage.SaveToFile() doesn't save the alpha. So, yes, you also need todo: 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 TPortableNetworkGraphic.Create do begin      try        LoadFromIntfImage(LImage);        SaveToFile('test.png');      finally        Free;      end;    end; ---------------------------------------------------------------------- tk · 2016-12-30 13:49 Hi Geepster, thank you, it works now. Summarized to my example: 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  I, J, W, H: Integer;  FC: TFPColor;  IM: TLazIntfImage;  Png: TPortableNetworkGraphic;begin  W := 32;  H := 32;  Png := TPortableNetworkGraphic.Create;  try    IM := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);    try      IM.SetSize(W, H);      for I := 0 to W - 1 do      begin        for J := 0 to H - 1 do        begin          FC.red := (128 + I) shl 8;        FC.green := (128 + J) shl 8;          FC.blue := 128 shl 8;        FC.alpha := 128 shl 8; // now works fine          IM.Colors[I, J] := FC;        end;      end;      Png.LoadFromIntfImage(IM);    finally    IM.Free;    end;    Png.SaveToFile('test.png');  finally    Png.Free;  end;end; ---------------------------------------------------------------------- geraldholdsworth · 2021-04-09 07:54 I found this when looked at how to do something similar. What it doesn't mention above is what units are required (as I kept getting 'Identifier unknown' for riqfRGB and riqfAlpha). I was also needing to convert to bitmap and show on screen rather than save it. So, using the above as a basis and some other code I was given, I knocked the following up: 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.CreatePNG;//Requires FPImage,IntfGraphics,GraphType in uses clausevar img: TLazIntfImage; png: TPortableNetworkGraphic; col: TFPColor; x,y: Integer;begin //Creates and fills a PNG, then converts to BMP png:=TPortableNetworkGraphic.Create; png.PixelFormat:=pf32bit; //32bpp is required for the alpha channel img:=TLazIntfImage.Create(0,0,[riqfRGB, riqfAlpha]); img.SetSize(256,256); for y:=0 to img.Height-1 do  for x:=0 to img.Width-1 do  begin   // $FF is non-transparent down to $00 fully transparent   col.Alpha:=(128-(x div 2))+(128-(y div 2));   col.Red  :=x;   col.Green:=y;   col.Blue :=(128-(x div 2))+(128-(y div 2));   //TFPColor is 16 bit per colour   col.Alpha:=col.Alpha or col.Alpha<<8;   col.Red  :=col.Red or col.Red<<8;   col.Green:=col.Green or col.Green<<8;   col.Blue :=col.Blue or col.Blue<<8;   //Set the pixel colour   img.Colors[x,y]:=col;  end; //Save to PNG png.LoadFromIntfImage(img); //And to file png.SaveToFile('Test.png'); //Load into the picture, so we can see it...and convert to BMP at the same time Image2.Picture.Bitmap.Pix elFormat:=pf32bit; Image2.Picture.Bitmap.Assign(png); //Save to file I mage2.Picture.Bitmap.SaveToFile('Test.bmp'); img.Free; png.Free;end; Produces a nice image too - quite random. I then spent ages trying to get fully Blue eminating from the top left, fully Red from the top right and fully Green from the bottom left. I just added a fading Alpha from the bottom right as an afterthought.