Lazarus

Programming => Graphics and Multimedia => Graphics => Topic started by: widoman on January 19, 2013, 02:18:48 am

Title: How to make color of PNG image transparent
Post by: widoman on January 19, 2013, 02:18:48 am
Hi,

%) I try various ways but none work, or the png have white background(not transparent) or this last situation.
How to create a correct transparent png in Lazarus??
What its wrong?

PNG opened in applications
pnggoogleearth.png
pngphotoeditor.png

Same PNG edited manually with Microsoft Photo editor and opened in google-earth
png2photoeditor.png
png2googleearth.png

Code: [Select]
function fmyScreen.MakeBitmap(pControl:TCustomControl):TBitmap;
var
  tmp: TBitmap;
  r: TRect;
begin
  r:= Rect(0, 0, pControl.ClientWidth, pControl.ClientHeight);
  tmp:= TBitmap.Create;
  tmp.SetSize(pControl.ClientWidth, pControl.ClientHeight);
  tmp.Canvas.CopyRect(r, pControl.Canvas, r);
  result:= tmp;
end;

procedure fmyScreen.MakePng(FileName: String; Trans: TColor);
var
  screen: TBitmap;
  c: TBGRABitmap;
  i,j: integer;
  xcolor: TBGRAPixel;
  zcolor: TFPColor;
begin
  screen := MakeBitmap(fmyScreen);//form
  xcolor:= ColorToBGRA(trans,255);
  zcolor.alpha := xcolor.alpha;
  zcolor.red := xcolor.red;
  zcolor.green := xcolor.green;
  zcolor.blue := xcolor.blue;

  c := TBGRABitmap.Create(screen);
  for i:=0 to c.Width-1 do
  begin
      for j:=0 to c.Height-1 do
      begin
        if(c.Canvas.Pixels[i,j]=Trans)then
        begin
          c.CanvasBGRA.Colors[i,j]:= zcolor;
        end;
      end;
  end;
  c.SaveToFile(FileName);
  c.free;
  screen.free;
end;

************
on button click
************
procedure fmyScreen.Button1Click(Sender: TObject);
begin
   MakePng('aa.png', clWhite);
end;
Title: Re: How to make color of PNG image transparent
Post by: dcelso on January 27, 2013, 05:07:30 pm
You can do it converting it in 32 bits and change white color for a color with alpha channel equals to 0.
You must change bmp.pixelformat To pf32bit
and after of your copy add the next lines

Myimg :Tlazintfimage
 
myimg:=bmp.createlazintf

for i:=0 to bmp.width -1
 for j:=0 to bmp.height -1
    if myimg.colors[i,j]= colwhite then
       myimg.colors[i,j]:= coltransparent
Bmp.loadfrominterfaz(myimg)

NOTE: This method in linux does not work. :'(
Title: Re: How to make color of PNG image transparent
Post by: widoman on January 29, 2013, 12:35:36 am
dcelso, i cant make work
 :'( the background of the png its not transparent, its black or white

Code: [Select]
procedure TfGrid.CrearPng(FileName: String; Transparencia: TColor);
var
  pantalla: TBitmap;
  c: TBGRABitmap;
  i,j: integer;
  xcolor: TBGRAPixel;
  zcolor: TFPColor;
  m1: Tlazintfimage;
begin
  pantalla := CrearBitmap(fGrid);
  m1:= pantalla.CreateIntfImage;
  xcolor:= ColorToBGRA(transparencia, 0);
  for i:=0 to m1.width -1 do
  begin
    for j:=0 to m1.height -1 do
    begin
      if(FPColorToTColor(m1.colors[i,j]) = Transparencia) then
        m1.colors[i,j]:= BGRAToFPColor(xcolor);
        //colTransparent => black background not transparent
        //BGRAToFPColor(xcolor) => white background not transparent
    end;
  end;
  pantalla.LoadFromIntfImage(m1);
  c := TBGRABitmap.Create(pantalla);
  c.SaveToFile(FileName);
end;

function TfGrid.CrearBitmap(pControl : TCustomControl):TBitmap;
var
  tmp: TBitmap;
  r: TRect;
begin
  r:= Rect(0, 0, pControl.ClientWidth, pControl.ClientHeight);
  tmp:= TBitmap.Create;
  tmp.PixelFormat := pf32bit;
  tmp.SetSize(pControl.ClientWidth, pControl.ClientHeight);
  tmp.Canvas.CopyRect(r, pControl.Canvas, r);
  result:= tmp;
end;
Title: Re: How to make color of PNG image transparent
Post by: circular on January 29, 2013, 12:52:25 am
Try this:
Code: [Select]
procedure fmyScreen.MakePng(FileName: String; Trans: TColor);
var
  screen: TBitmap;
  c: TBGRABitmap;
  i,j: integer;
  xcolor: TBGRAPixel;
begin
  screen := MakeBitmap(fmyScreen);//form
  xcolor:= ColorToBGRA(trans,255);

  c := TBGRABitmap.Create(screen);
  screen.free;
  for i:=0 to c.Width-1 do
  begin
      for j:=0 to c.Height-1 do
      begin
        if(c.GetPixel(i,j)=xcolor)then
          c.SetPixel(i,j, BGRAPixelTransparent);
      end;
  end;
  c.SaveToFile(FileName);
  c.free;
end;
Title: Re: How to make color of PNG image transparent
Post by: widoman on January 29, 2013, 01:55:42 am
circular,
Png created open with:
Microsoft Word 2000 => image transparent OK
Microsoft Photo Editor => some fuchsia lines changed to black, image transparent OK
Google-earth => KML with image as overlay the image background its black not transparent  :'(
** image like the first example in this post
Title: Re: How to make color of PNG image transparent
Post by: circular on January 29, 2013, 12:37:03 pm
What if you do c.SetPixel(0,0,BGRAPixelTransparent) before c.SaveToFile ?
Title: Re: How to make color of PNG image transparent
Post by: dcelso on January 29, 2013, 01:44:05 pm
Without using BGRA library would be as the next, using it, I dont know.
Code: [Select]
unit unit3;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, IntfGraphics, FPimage;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    function CrearBitmap(pControl : TCustomControl):TPortableNetworkGraphic;
    procedure CrearPng(FileName: String; Transparencia: TColor);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

function TForm1.CrearBitmap(pControl : TCustomControl):TPortableNetworkGraphic;
var
  tmp: TPortableNetworkGraphic;
  r: TRect;
begin
  r:= Rect(0, 0, pControl.ClientWidth, pControl.ClientHeight);
  tmp:= TPortableNetworkGraphic.Create;
  tmp.PixelFormat := pf32bit;
  tmp.SetSize(pControl.ClientWidth, pControl.ClientHeight);
  tmp.Canvas.CopyRect(r, pControl.Canvas, r);
  result:= tmp;
end;

procedure TForm1.CrearPng(FileName: String; Transparencia: TColor);
var
  pantalla: TPortableNetworkGraphic;
  m1: Tlazintfimage;
  tempcolor: TFPColor;
  i,j : Integer;
begin
  pantalla := CrearBitmap(Form1);
  m1:= pantalla.CreateIntfImage;
  for i:=0 to m1.width -1 do
    for j:=0 to m1.height -1 do
    begin
      tempcolor:=m1.colors[i,j];
      if  tempcolor= TColorToFPColor(Transparencia) then
       tempcolor.alpha:=0
      else
       tempcolor.alpha:=$FFFF;

      m1.colors[i,j]:= tempcolor; // if you want keep RGB information
   end;
  pantalla.LoadFromIntfImage(m1);
  m1.free;
  pantalla.SaveToFile(FileName);
  pantalla.free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
      CrearPng(Edit1.Text,clWhite);
end;

end.


The form example is the next:
Code: [Select]
object Form1: TForm1
  Left = 292
  Height = 46
  Top = 224
  Width = 321
  Caption = 'Form1'
  ClientHeight = 46
  ClientWidth = 321
  LCLVersion = '1.1'
  object Edit1: TEdit
    Left = 16
    Height = 23
    Top = 18
    Width = 176
    Color = clWhite
    TabOrder = 0
    Text = '32bits.png'
  end
  object Button1: TButton
    Left = 216
    Height = 25
    Top = 16
    Width = 75
    Caption = 'Button1'
    OnClick = Button1Click
    TabOrder = 1
  end
end
Title: Re: How to make color of PNG image transparent
Post by: User137 on January 29, 2013, 03:02:29 pm
Code: [Select]
r:= Rect(0, 0, pControl.ClientWidth, pControl.ClientHeight);
tmp.Canvas.CopyRect(r, pControl.Canvas, r);
You use CopyRect for drawing everything. Would Draw() work? There used to be some problems with CopyRect dealing with transparency.
Title: Re: How to make color of PNG image transparent
Post by: widoman on January 30, 2013, 02:54:55 am
Code: [Select]
r:= Rect(0, 0, pControl.ClientWidth, pControl.ClientHeight);
tmp.Canvas.CopyRect(r, pControl.Canvas, r);
You use CopyRect for drawing everything. Would Draw() work? There used to be some problems with CopyRect dealing with transparency.
:'( dont work, same result.
I used Draw() with GetFormImage() like you say, GetFormImage() return a Bitmap.
Title: Re: How to make color of PNG image transparent
Post by: widoman on January 30, 2013, 03:04:34 am
Without using BGRA library would be as the next, using it, I dont know.
Code: [Select]
function TForm1.CrearBitmap(pControl : TCustomControl):TPortableNetworkGraphic;
begin
   //exactly like your example
end;

procedure TForm1.CrearPng(FileName: String; Transparencia: TColor);
begin
   //exactly like your example
end;
I change the functions
CrearBitmap() => use TPortableNetworkGraphic and return a PNG like you say
CrearPng() => modify alpha and use PNG like you say
 :'( dont work
Microsoft Word => ok image transparent
Microsoft Photo Editor => ok image transparent, some fuchsia lines changed to white
Google-earth => show png with white background not transparent
** image like the first example in this post
** I have to edit png manually to change transparent color but some lines dissapear because are white like background detected to make transparent
Title: Re: How to make color of PNG image transparent
Post by: widoman on January 30, 2013, 03:07:27 am
What if you do c.SetPixel(0,0,BGRAPixelTransparent) before c.SaveToFile ?
:'( dont work, same result.
Title: Re: How to make color of PNG image transparent
Post by: widoman on January 30, 2013, 03:31:12 am
 :) maybe the problem is the software
Lazarus 1.0.4
Rev SVN: 39422
FPC 2.6.0
Packages list
Title: Re: How to make color of PNG image transparent
Post by: lainz on January 30, 2013, 05:06:19 am
Attach a transparent PNG not generated in lazarus that works in all the programs you've mentioned, then maybe circular can analize it, im wrong?

5) Paint in Windows 8 load transparent as White.. and if you save it loses transparency. So transparency in this program is not supported.
Title: Re: How to make color of PNG image transparent
Post by: widoman on January 30, 2013, 05:37:28 am
Example image not generated in Lazarus => 12345rq.png
its transparent in: Microsoft Word 2000, Google-earth and Microsoft Photo Editor
* image  "12345rq.png" need to be in same place than "xyz.kml"
* open  "xyz.kml" with google-earth

Save next xml has "xyz.kml"
Code: [Select]
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<ScreenOverlay id="12345">
<name>12345rq</name>
<Icon><href>12345rq.png</href></Icon>
<overlayXY x="0.5" y="0.5" xunits="fraction" yunits="fraction"/>
<screenXY x="0.5" y="0.5" xunits="fraction" yunits="fraction"/>
<size x="0" y="0" xunits="pixels" yunits="pixels"/>
</ScreenOverlay>
</kml>
Title: Re: How to make color of PNG image transparent
Post by: widoman on February 05, 2013, 10:48:11 pm
 :'(conclusion, Lazarus can not create a transparent PNG.

I will change manually the PNG.

 :D Thanks for your time.

Title: Re: How to make color of PNG image transparent
Post by: User137 on February 06, 2013, 12:13:04 am
Just tried this quickly, seems to work fine on Windows 7 32-bit, and somewhat new Lazarus. It saves both BMP and PNG. There is clear difference in their file size, and both show alpha channel in Gimp too, PNG also in Windows Photo viewer and explorer.
Code: [Select]
TForm1 = class(TForm)
    ..
  private
    bmp: TBitmap;
  end;
..
procedure TForm1.FormCreate(Sender: TObject);
var i, j, n: integer; data: PByte;
    pic: TPicture;
begin
  randomize;
  bmp:=TBitmap.Create;
  bmp.PixelFormat:=pf32bit;
  bmp.SetSize(256, 256);
  data:=bmp.RawImage.Data;
  for i:=0 to 255 do
    for j:=0 to 255 do begin
      n:=(j*256+i)*4;
      data[n+0]:=0;   // B
      data[n+1]:=255; // G
      data[n+2]:=0;   // R
      data[n+3]:=i*2 mod 256; // A
    end;
  bmp.SaveToFile('tmp.bmp');

  pic:=TPicture.Create;
  pic.Assign(bmp);
  pic.SaveToFile('tmp.png');
  pic.Free;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  bmp.Free;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  canvas.Clear;
  canvas.Draw(0, 0, bmp);
end;
Title: Re: How to make color of PNG image transparent
Post by: widoman on February 06, 2013, 03:05:55 am
User137,  ;D you rule man

This code work :o, the PNG is transparent in google-earth

THANK YOU  :D
Title: Re: How to make color of PNG image transparent
Post by: widoman on February 06, 2013, 04:08:12 am
 ::) Two observations
::) One last error with this code
the image is cropped .. i guess "n" its wrong calculated %)

The final code
Code: [Select]
procedure TfGrid.CrearPng(FileName: String; Transparency: TColor);
var
  screen: TBitmap;
  pic: TPicture;
  data: PByte;
  i, j, n: integer;
begin
  screen := CrearBitmap(fGrid);
  data:= screen.RawImage.Data;
  for i:=0 to screen.Width-1 do
  begin
    for j:=0 to screen.Height-1 do
    begin
      n:=(j*screen.Height + i)*4;
      data[n+3]:= 255;//Alpha
      if(RGBToColor(data[n+2], data[n+1], data[n+0])=Transparency)then
        data[n+3]:= 1;//Alpha
    end;
  end;
  pic:=TPicture.Create;
  pic.Assign(screen);
  pic.SaveToFile(FileName);
  pic.Free;
end;

function TfGrid.CrearBitmap(pControl : TCustomControl):TBitmap;
var
  bmp: TBitmap;
  r: TRect;
begin
  r:= Rect(0, 0, pControl.ClientWidth, pControl.ClientHeight);
  bmp:= TBitmap.Create;
  bmp.PixelFormat:=pf32bit;
  bmp.SetSize(pControl.ClientWidth, pControl.ClientHeight);
  bmp.Canvas.CopyRect(r, pControl.Canvas, r);
  result:= bmp;
end;             
Title: Re: How to make color of PNG image transparent
Post by: User137 on February 06, 2013, 05:03:43 am
You should change the Fuchsia to some other color too, like black or white. It was purple in original picture only to show clearly, but now you want to hide it. So here:
Code: [Select]
if (RGBToColor(data[n+2], data[n+1], data[n+0])=Transparency) then begin
  data[n+0]:=0;
  data[n+1]:=0;
  data[n+2]:=0;
  data[n+3]:=1; // or 0 ...
end;
Title: Re: How to make color of PNG image transparent
Post by: widoman on February 06, 2013, 08:26:31 am
User137, you misunderstood what i want:

I cant figure why the png is cropped ??
the bottom rectangles are incomplete like the image was sliced
Title: Re: How to make color of PNG image transparent
Post by: User137 on February 06, 2013, 09:47:28 am
Wouldn't it be a Google earth image size limitation? If so, image file itself could not change it... Can you load fullscreen non-transparent image that goes under the cropped part?
Title: Re: How to make color of PNG image transparent
Post by: widoman on February 06, 2013, 06:56:53 pm
User137, the problem not is google-earth

The problem is in Lazarus when create PNG
bmp is 1152x808 => correct image, grid lines and white bakcground
png is 1152x808 => some grid lines disappear (transparent)
Title: Re: How to make color of PNG image transparent
Post by: User137 on February 06, 2013, 07:30:51 pm
I can't reproduce. This is 2048x2048 transparent fuschia grid between every 100 pixels. Both bmp and png are showing fine in Gimp.
Code: [Select]
procedure TForm1.FormCreate(Sender: TObject);
var i, j, n: integer; data: PByte;
    pic: TPicture;
begin
  randomize;
  bmp:=TBitmap.Create;
  bmp.PixelFormat:=pf32bit;
  bmp.SetSize(2048, 2048);
  data:=bmp.RawImage.Data;
  for i:=0 to 2047 do
    for j:=0 to 2047 do begin
      n:=(j*2048+i)*4;
      if (i mod 100=0) or (j mod 100=0) then begin
        data[n+0]:=255; // B
        data[n+1]:=0;   // G
        data[n+2]:=255; // R
        data[n+3]:=255; // A
      end else begin
        data[n+0]:=255; // B
        data[n+1]:=255; // G
        data[n+2]:=255; // R
        data[n+3]:=0;   // A
      end;
    end;
  bmp.SaveToFile('d:\netti\tmp.bmp');

  pic:=TPicture.Create;
  pic.Assign(bmp);
  pic.SaveToFile('d:\netti\tmp.png');
  pic.Free;
end;
By the way, such image could also be created manually using MsPaint for grid and editing with Gimp for making it tranparent.

edit: This code could be problem:
Code: [Select]
n:=(j*screen.Height + i)*4;It seems this is right, when i tested with non square image:
Code: [Select]
n:=(j*screen.Width + i)*4;
Title: Re: How to make color of PNG image transparent
Post by: widoman on February 06, 2013, 11:30:09 pm
User137, this is working THANK YOU  ;D this is the end

Observations
The final code
Code: [Select]
procedure TfGrid.CrearPng(FileName: String; Transparency: TColor);
var
  screen: TBitmap;
  pic: TPicture;
  data: PByte;
  i, j, n: integer;
begin
  screen := CrearBitmap(fGrid);
  data:= screen.RawImage.Data;
  for i:=0 to screen.Height-1 do
  begin
    for j:=0 to screen.Width-1 do
    begin
      if(i>0)then begin
        n:=(i*screen.Width + j)*4;
        data[n+3]:= 255;//Alpha
        if(RGBToColor(data[n+2], data[n+1], data[n+0])=Transparency)then
          data[n+3]:= 1;//Alpha
      end;
    end;
  end;
  pic:=TPicture.Create;
  pic.Assign(screen);
  pic.SaveToFile(FileName);
  pic.Free;
end;               
TinyPortal © 2005-2018