[Solved] How to change the hue of a Tbitmap lazarus / 39-Graphics ---------------------------------------------------------------------- Jurassic Pork · 2013-05-18 10:46 hello, i am beginner with graphics in Lazarus, i want to change only the hue of an image. This image (png with transparency)  is loaded in a Tpicture.  I don't want use the BGRAbitmap library because this library is too big for my purpose (growing size > 1Mb). I have found a solution but i am sure that there is a better solution. And i have a problem with the transparency. here is my code (FPictureOn is a Tpicture : size 32x32)  : Code: [Select]  SetHue( hue : byte); var  t: TLazIntfImage;   px,py : integer;   CurFPColor: TFPColor;   CurColor: Tcolor;   r,g,b,h,l,s : byte; begin   try     t :=  FpictureON.Bitmap.CreateIntfImage;     for py:=0 to t.Height-1 do begin     for px:=0 to t.Width-1 do begin     // Read and/or write to the pixels     CurColor:= FPColorToTColor(t.Colors[px,py]); //lire la couleur source     RedGreenBlue(CurColor,r,g,b);     RGBtoHLS(r,g,b,h,l,s);     HLStoRGB(hue,l,s,r,g,b);     t.Colors[px,py]:=TColorToFPColor(RGBToColor(r,g,b));     end;     end;     FpictureON.Bitmap.LoadFromIntfImage(t);   finally     t.Free;   end;         With this i can change the hue but i loose the transparency.  Optimization is not necessary because the image is very small. Can you help me ? ---------------------------------------------------------------------- Jurassic Pork · 2013-05-18 11:59 i have found a solution for the transparency : Code: [Select]  alpha :=  t.Colors[px,py].alpha;     if alpha > 0 then     begin     CurColor:= FPColorToTColor(t.Colors[px,py]); //lire la couleur source     RedGreenBlue(CurColor,r,g,b);     RGBtoHLS(r,g,b,h,l,s);     HLStoRGB(150,l,s,r,g,b);     t.Colors[px,py]:=TColorToFPColor(RGBToColor(r,g,b));     end;  if i am in a transparent pixel (alpha = 0 -> invisible), i don't change the value of this pixel. ---------------------------------------------------------------------- User137 · 2013-05-18 12:07 You don't need to create a new image, but you can just edit the FpictureON directly. This command FpictureON.bitmap.Canvas.Colors[px,py]:=TColorToFPColor(RGBToColor(r,g ,b)); is sure to abandon Alpha, but what if you individually set FpictureON.bitmap.Canvas.Colors[px,py].red:=r; (i don't remember exact syntax) or if there is RGBAToColor(r,g,b,a) ---------------------------------------------------------------------- taazz · 2013-05-18 12:12 1) alpha is transparent when 0 in some widgetsets and in other when it is 255, just for your information. 2) fpimage.TFpColor is a record type you can access the rgb values directly do not convert it to tcolor and then use an rgb convertion function. If you use the TFPcolor directly then the alpha value will be preserved. Remember to add fpimage in your uses clause. ---------------------------------------------------------------------- Jurassic Pork · 2013-05-18 15:53 thanks for your help  but there are some "dark points" 1 - if i use FPictureON.Bitmap.Canvas.Colors[px,py] the alpha channel doesn't work ( read or write). For this i use always in my code the temporary TLazIntfImage. 2 - the members of the TFPColor are word not byte and if i affect for example the red member to a byte value r, this doesn't work . I must use TColorToFPColor to have the good values in the TFPColor finally here is my code : Code: [Select] SetHue( hue : byte);   t: TLazIntfImage;   px,py : integer;   CurColor: TColor;   CurFPColor: TFPColor;   r,g,b,h,l,s : byte;   alpha : word; begin   try     t :=  FpictureON.Bitmap.CreateIntfImage;     for py:=0 to FPictureON.Bitmap.Height-1 do begin     for px:=0 to FPictureON.Bitmap.Width-1 do begin     curFPColor := t.Colors[px,py];     RedGreenBlue(CurColor,r,g,b);     alpha := curFPColor.alpha;      RGBtoHLS(lo(curFPColor.red),lo(curFPColor.green),lo(curFPColor.bl ue),h,l,s);      HLStoRGB(hue,l,s,r,g,b);  //    curFPColor.red := r; //  doesn't work      curFPColor := TColorToFPColor(RGBToColor(r,g,b));      curFPColor.alpha := alpha;       t.Colors[px,py] :=  curFPColor;     end;     end;     FpictureON.Bitmap.LoadFromIntfImage(t);   finally     t.free;   end;          Friendly, J.P ---------------------------------------------------------------------- User137 · 2013-05-18 17:28 To convert byte channel into word format, you can multiply it by 256. Or in opposite direction it is divided. You didn't follow mine or taazz instructions. t.Colors[px,py] :=curFPColor; this is still a direct assignment. I meant something like: Code: [Select]t.Colors[px,py].red:=r; t.Colors[px,py].green:=g; t.Colors[px,py].blue:=b; ---------------------------------------------------------------------- Jurassic Pork · 2013-05-18 23:14 For my first problem ( need to use a temporary TLazIntfImage  ) read this : QuoteTLazIntfImage is a memory image. I can store transparency and 16-bit values for each channel. TBitmap is compatible with Delphi and use TColor type for pixels which do not contain alpha information. So TLazIntfImage is better suited for image processing. This component provide faster access to pixels because it is an array in memory like our TFastBitmap. For direct assignment like this : Code: [Select]t.Colors[px,py].red:=r;i can't compile with this error : Quote.pas(133,22) Error: Argument can't be assigned tolook like this bug :  http://lists.lazarus.freepascal.org/pipermail/lazarus/2010- January/048371.html to avoid this error i use a TFPColor variable For the TFPColor to convert the r,v,b bytes i must multiply these values by 256 because : Quote The TFPColor record contains the Red, Green, Blue and Alpha channel values as left adjusted 16 bit words, with increasing intensity from 0 to $FFFF. Alpha=0 indicates transparent pixels.The internal representation uses the high order bits of these values, as specified by the color Depth of the image description. finally my code (work for me) : Code: [Select]procedure SetHue (hue: byte) ; var   t: TLazIntfImage;   px,py : integer;   CurFPColor: TFPColor;   r,g,b,h,l,s : byte;   alpha : word; begin   try     t :=  FpictureON.Bitmap.CreateIntfImage;     for py:=0 to t.Height-1 do begin     for px:=0 to t.Width-1 do begin     curFPColor := t.Colors[px,py];     RGBtoHLS(hi(curFPColor.red),hi(curFPColor.green),hi(curFPColor.blu e),h,l,s);     HLStoRGB(hue,l,s,r,g,b);     curFPColor.red := r shl 8;     curFPColor.green := g shl 8;     curFPColor.blue := b shl 8;     t.Colors[px,py] :=  curFPColor;     end;     end;    FpictureON.Bitmap.LoadFromIntfImage(t);   finally     t.free;   end; end;