Delphi code part 4 - Bitmap

March 7th, 2007 by William Yang

After I learned how colour can be manupilated, I started to work on bitmaps. Back then I even borrowed a book to learn how bitmaps can be modified, like blur, sharp, find edge, etc. The technique was called filtering.

Here is the code

Show Code | Download Grafman.pas

  1.  
  2. { ---------------------------------------------------
  3.     Graphics Manager
  4.     Copyright (r) by E-Port Software Team
  5.     Version : 4.0     Author : William Yang
  6.     Last Update       1 - Oct - 98
  7.   --------------------------------------------------- }
  8.  
  9. unit GrafMan;
  10.  
  11. interface
  12.  
  13. uses Windows, SysUtils, Graphics, Classes, ColorMan, ExtCtrls, Forms,
  14.   Drawman, NumMan;
  15.  
  16. { *************************************************************************
  17.   There is a small bug in this unit.
  18.   Becase I used a internal variable for each function that returns
  19.   a TBitmap object, which means if you are going to add another function
  20.   you must not cross use this variable.
  21.   I mean you cannot use in one of the function and not yet wait until it is finished
  22.   call another function in this unit.
  23.   _________________________________________________________________________ }
  24.  
  25. type
  26.   EBitmapOperationError = Exception;
  27.   TGraphicFilter = array[0..2, 0..2] of Integer;
  28.  
  29. procedure ColoriseImage(Bmp : TBitmap; BaseColor : TColor);
  30. procedure MergeBMP(Pic1, Pic2 : TBitmap);
  31. procedure SoftenBMP(Src : TBitmap);
  32. procedure GreyBMP(Src : TBitmap);
  33. procedure BWOnlyBMP(Src : TBitmap);
  34. procedure DarkenBMP(Bmp : TBitmap; Grade : Integer);
  35. procedure BrightenBMP(Bmp : TBitmap; Grade : Integer);
  36. procedure MergeBMPExt(Pic1, Pic2 : TBitmap; Grade: Byte);
  37. function BMPFromRes(ResName: String) : TBitmap;
  38. function ResizeBMP(Src: TBitmap; Width, Height: Integer): TBitmap;
  39. function LoadBMPFile(Filename: String): TBitmap;
  40. function DisabledBmp(Src: TBitmap; DisabledColor, FaceColor: TColor): TBitmap;
  41. function CreatePattern(Color1, Color2: TColor ): TBitmap;
  42. function BmpToLCD(Src: TBitmap; ForeColor, Backcolor: TColor): TBitmap;
  43. procedure BevelBmp(Src: TBitmap; Size: Integer);
  44. procedure DownButton(Src: TBitmap; Bevel: Integer);
  45. procedure UpButton(Src: TBitmap; Bevel: Integer);
  46.  
  47. procedure ApplyFilter(Src: TBitmap; GF: TGraphicFilter);
  48.  
  49. const
  50.   BlurFilter : TGraphicFilter = ( (5, 15, 5),
  51.                                   (15, 20, 15),
  52.                                   (5, 15, 5));
  53.  
  54.   SharpFilter : TGraphicFilter = ((0, -100, 0),
  55.                                   (-100, 500, -100),
  56.                                   (0, -100, 0));
  57.  
  58.   EdgeFilter : TGraphicFilter = ((0, -100, 0),
  59.                                   (-100, 400, -100),
  60.                                   (0, -100, 0));
  61.  
  62.   EmbossFilter : TGraphicFilter = ((-100, 0, 0),
  63.                                   (0, 0, 0),
  64.                                   (0, 0, 100));
  65.  
  66.   Enhance3DFilter : TGraphicFilter = ((-100, 5, 5),
  67.                                   (5, 5, 5),
  68.                                   (5, 5, 100));
  69.  
  70. var
  71.   Calcs: Integer;
  72.  
  73. implementation
  74.  
  75. var
  76.   TmpMem : TBitmap;
  77.  
  78.  
  79. function RollRGB(R, G, B: Real): TColor;
  80. begin
  81.   Result := RGB(Abs(Round(R) mod 255), Abs(Round(G) mod 255), Abs(Round(B) mod 255));
  82. end;
  83.  
  84. procedure ApplyFilter(Src: TBitmap; GF: TGraphicFilter);
  85. var
  86.   i, j: Integer;
  87.   x, y: Integer;
  88.   r, g, b: Integer;
  89.   p: PRGBArray;
  90.   Red, Green, Blue: Integer;
  91. begin
  92.   TmpMem.Width := Src.Width;
  93.   TmpMem.Height := Src.Height;
  94.   TmpMem.Canvas.Draw(0, 0, Src);
  95.   TmpMem.PixelFormat := pf24Bit;
  96.   Calcs := 0;
  97.   for y := 0 to Src.Height-1 do
  98.   begin
  99.     p := Src.Scanline[y];
  100.     for x := 0 to Src.Width-1 do
  101.     begin
  102.       Red := 0; Green := 0; Blue := 0;
  103.       for i := 0 to 2 do
  104.         for j := 0 to 2 do
  105.         begin
  106.           if Between((x+i-1), 0, Src.Width-1) and Between((y+j-1), 0, Src.Height-1) then
  107.           begin
  108.             Decolor(RGBToInt(PRGBArray(TmpMem.Scanline[y+j-1])[x+i-1]), r, g, b);
  109.             Red := Red + GF[i, j]*R;
  110.             Blue := Blue + GF[i, j]*B;
  111.             Green := Green + GF[i, j]*G;
  112.             Inc(Calcs, 3);
  113.           end;
  114.         end;
  115.       p[x] := IntToRGB(ERGB(Red/100, Green/100, Blue/100));
  116.     end;
  117.   end;
  118.   TmpMem.Width :=  1;
  119.   TmpMem.Height :=  1;
  120. end;
  121.  
  122. procedure DownButton(Src: TBitmap; Bevel: Integer);
  123. var
  124.   i, j : Integer;
  125.   p: PRGBArray;
  126. begin
  127.   if Bevel <= 0 then Bevel := 1;
  128.   if Src.PixelFormat <> pf24Bit then
  129.   begin
  130.     EBitmapOperationError.Create('Only 24 bit bitmaps can be operated.');
  131.   end;
  132.   for i := 0 to Src.Height-1 do
  133.   begin
  134.     P := Src.Scanline[i];
  135.     for j := 0 to Bevel-1 do
  136.     begin
  137.       P[j] := IntToRGB(DarkenColor(RGBToInt(P[j]), Round(100-(j)/Bevel*100)));
  138.      P[Src.Width-j-1] := IntToRGB(BrightenColor(RGBToInt(P[Src.Width-j-1]), Round(100-(j)/Bevel*100)));
  139.     end;
  140.     for j := 0 to Src.Width-1 do
  141.     begin
  142.       if Between(i, 0, Bevel-1) then
  143.         P[j] := IntToRGB(DarkenColor(RGBToInt(P[j]), Round(100-(i)/Bevel*100)));
  144.       if Between(i, Src.Height-Bevel-1, Src.Height-1) then
  145.         P[j] := IntToRGB(BrightenColor(RGBToInt(P[j]), Round(100-((Src.Height-i-1))/Bevel*100)));
  146.     end;
  147.   end;
  148. end;
  149.  
  150. procedure UpButton(Src: TBitmap; Bevel: Integer);
  151. var
  152.   i, j : Integer;
  153.   p: PRGBArray;
  154. begin
  155.   if Bevel <= 0 then Bevel := 1;
  156.   if Src.PixelFormat <> pf24Bit then
  157.   begin
  158.     EBitmapOperationError.Create('Only 24 bit bitmaps can be operated.');
  159.   end;
  160.   for i := 0 to Src.Height-1 do
  161.   begin
  162.     P := Src.Scanline[i];
  163.     for j := 0 to Bevel-1 do
  164.     begin
  165.       P[j] := IntToRGB(BrightenColor(RGBToInt(P[j]), Round(100-(j)/Bevel*100)));
  166.      P[Src.Width-j-1] := IntToRGB(DarkenColor(RGBToInt(P[Src.Width-j-1]), Round(100-(j)/Bevel*100)));
  167.     end;
  168.     for j := 0 to Src.Width-1 do
  169.     begin
  170.       if Between(i, 0, Bevel-1) then
  171.         P[j] := IntToRGB(BrightenColor(RGBToInt(P[j]), Round(100-(i)/Bevel*100)));
  172.       if Between(i, Src.Height-Bevel-1, Src.Height-1) then
  173.         P[j] := IntToRGB(DarkenColor(RGBToInt(P[j]), Round(100-((Src.Height-i-1))/Bevel*100)));
  174.     end;
  175.   end;
  176. end;
  177.  
  178. procedure BevelBmp(Src: TBitmap; Size: Integer);
  179. var
  180.   i, j : Integer;
  181.   p: PRGBArray;
  182. begin
  183.   if Size <= 0 then Size := 1;
  184.   if Src.PixelFormat <> pf24Bit then
  185.   begin
  186.     EBitmapOperationError.Create('Only 24 bit bitmaps can be operated.');
  187.   end;
  188.   for i := 0 to Src.Height-1 do
  189.   begin
  190.     P := Src.Scanline[i];
  191.     for j := 0 to Size-1 do
  192.     begin
  193.       P[j] := IntToRGB(BrightenColor(RGBToInt(P[j]), Round(100-(j+1)/Size*100)));
  194.      P[Src.Width-j-1] := IntToRGB(DarkenColor(RGBToInt(P[Src.Width-j-1]), Round(100-(j+1)/Size*100)));
  195.     end;
  196.     for j := 0 to Src.Width-1 do
  197.     begin
  198.       if Between(i, -1, Size) then
  199.         P[j] := IntToRGB(BrightenColor(RGBToInt(P[j]), Round(100-(i+1)/Size*100)));
  200.       if Between(i, Src.Height-Size-1, Src.Height) then
  201.         P[j] := IntToRGB(DarkenColor(RGBToInt(P[j]), Round(100-((Src.Height-i)+1)/Size*100)));
  202.     end;
  203.   end;
  204. end;
  205.  
  206. function CreatePattern(Color1, Color2: TColor ): TBitmap;
  207. var
  208.   X, Y: Integer;
  209. begin
  210.   TmpMem.Width := 8;
  211.   TmpMem.Height := 8;
  212.   with TmpMem.Canvas do
  213.   begin
  214.     Brush.Style := bsSolid;
  215.     Brush.Color := Color1;
  216.     FillRect(Rect(0, 0, TmpMem.Width, TmpMem.Height));
  217.     for Y := 0 to 7 do
  218.       for X := 0 to 7 do
  219.         if (Y mod 2) = (X mod 2) then  { toggles between even/odd pixles }
  220.           Pixels[X, Y] := Color2;    { on even/odd rows }
  221.   end;
  222.   Result := TmpMem;
  223. end;
  224.  
  225. function BmpToLCD(Src: TBitmap; ForeColor, Backcolor: TColor): TBitmap;
  226. var
  227.   x, y: Integer;
  228. begin
  229.   TmpMem.Width := Src.Width*4;
  230.   TmpMem.Height := Src.Height*4;
  231.   with TmpMem.Canvas do
  232.   begin
  233.     Brush.Color := BackColor;
  234.     Brush.Style := bsSolid;
  235.     FillRect(Rect(0, 0, TmpMem.Width, TmpMem.Height));
  236.     Brush.Color := ForeColor;
  237.     Pen.Color := MergeColor(ForeColor, BackColor);
  238.     for x := 0 to Src.Width do
  239.       for y := 0 to Src.Height do
  240.       begin
  241.         if not IsLightColor(Src.Canvas.Pixels[x, y]) then
  242.         begin
  243.           Rectangle(x*3+1, y*3+1, x*3+3, y*3+3);
  244.         end
  245.       end;
  246.   end;
  247.   Result := TmpMem;
  248. end;
  249.  
  250. function LoadBMPFile(Filename: String): TBitmap;
  251. begin
  252.   TmpMem.LoadFromFile(Filename);
  253.   Result := TmpMem;
  254. end;
  255.  
  256. function DisabledBmp(Src: TBitmap; DisabledColor, FaceColor: TColor): TBitmap;
  257. begin
  258.   TmpMem.Assign(Src);
  259.   GreyBMP(TmpMem);
  260.   BrightenBmp(TmpMem, 50);
  261.   Result := TmpMem;
  262. end;
  263.  
  264. function ResizeBMP(Src: TBitmap; Width, Height: Integer): TBitmap;
  265. var
  266.   DR, SR: TRect;
  267. begin
  268.   DR := Rect(0, 0, Width, Height);
  269.   SR := Rect(0, 0, Src.Width, Src.Height);
  270.   TmpMem.Width := Width;
  271.   TmpMem.Height := Height;
  272.   TmpMem.Canvas.CopyRect(DR, Src.Canvas, SR);
  273.   Result := TmpMem;
  274. end;
  275.  
  276. function BMPFromRes(ResName: String) : TBitmap;
  277. begin
  278.   TmpMem.LoadFromResourceName(HINSTANCE, PChar(UpperCase(ResName)));
  279.   Result := TmpMem;
  280. end;
  281.  
  282. procedure BrightenBMP(Bmp : TBitmap; Grade : Integer);
  283. var
  284.   i, j : Integer;
  285.   p: PRGBArray;
  286. begin
  287.   if Bmp.PixelFormat <> pf24Bit then
  288.   begin
  289.     EBitmapOperationError.Create('Only 24 bit bitmaps can be operated.');
  290.   end;
  291.   for i := 0 to Bmp.Height-1 do
  292.   begin
  293.     P := Bmp.Scanline[i];
  294.     for j := 0 to Bmp.Width-1 do
  295.     begin
  296.       P[j] := IntToRGB(BrightenColor(RGBToInt(P[j]), Grade));
  297.     end;
  298.   end;
  299. end;
  300.  
  301. procedure DarkenBMP(Bmp : TBitmap; Grade : Integer);
  302. var
  303.   i, j : Integer;
  304.   p: PRGBArray;
  305. begin
  306.   if Bmp.PixelFormat <> pf24Bit then
  307.   begin
  308.     EBitmapOperationError.Create('Only 24 bit bitmaps can be operated.');
  309.   end;
  310.   for i := 0 to Bmp.Height-1 do
  311.   begin
  312.     P := Bmp.Scanline[i];
  313.     for j := 0 to Bmp.Width-1 do
  314.     begin
  315.       P[j] := IntToRGB(DarkenColor(RGBToInt(P[j]), Grade));
  316.     end;
  317.   end;
  318. end;
  319.  
  320. procedure BWOnlyBMP(Src : TBitmap);
  321. begin
  322.   Src.Monochrome := True;
  323.   Src.Monochrome := False;
  324. end;
  325.  
  326. procedure GreyBMP(Src : TBitmap);
  327. var
  328.   i, j : Integer;
  329.   p: PRGBArray;
  330. begin
  331.   if Src.PixelFormat <> pf24Bit then
  332.   begin
  333.     EBitmapOperationError.Create('Only 24 bit bitmaps can be operated.');
  334.   end;
  335.   for i := 0 to Src.Height-1 do
  336.   begin
  337.     P := Src.Scanline[i];
  338.     for j := 0 to Src.Width-1 do
  339.     begin
  340.       P[j] := IntToRGB(ColorToGrey(RGBToInt(P[j])));
  341.     end;
  342.   end;
  343. end;
  344.  
  345. procedure MergeBMP(Pic1, Pic2 : TBitmap);
  346. begin
  347.   MergeBMPExt(Pic1, Pic2, 50);
  348. end;
  349.  
  350. procedure MergeBMPExt(Pic1, Pic2 : TBitmap; Grade: Byte);
  351. var
  352.   i, j : Integer;
  353.   p1, p2: PRGBArray;
  354. begin
  355.   if (Pic1.PixelFormat <> pf24Bit) or (Pic2.PixelFormat <> pf24Bit) then
  356.   begin
  357.     EBitmapOperationError.Create('Only 24 bit bitmaps can be operated.');
  358.   end;
  359.   for i := 0 to Pic1.Height-1 do
  360.   begin
  361.     P1 := Pic1.Scanline[i];
  362.     P2 := Pic2.Scanline[i];
  363.     for j := 0 to Pic1.Width-1 do
  364.     begin
  365.       P1[j] := IntToRGB(MergeColorExt(RGBToInt(P1[j]), RGBToInt(P2[j]) ,Grade));
  366.     end;
  367.   end;
  368. end;
  369.  
  370. procedure SoftenBMP(Src : TBitmap);
  371. var
  372.   SumR, SumG, SumB, i, j, k, l : Integer;
  373.   P, G, G1: PRGBArray;
  374. begin
  375.   for i := 1 to Src.Height-2 do
  376.   begin
  377.     P := Src.Scanline[i];
  378.     G := Src.Scanline[i+1];
  379.     G1 := Src.Scanline[i-1];
  380.     for j := 1 to Src.Width-2 do
  381.     begin
  382.       SumR := P[j][2] + P[j+1][2] + P[j-1][2] + G[j][2] + G1[j][2];
  383.       SumG := P[j][1] + P[j+1][1] + P[j-1][1] + G[j][1] + G1[j][1];
  384.       SumB := P[j][0] + P[j+1][0] + P[j-1][0] + G[j][0] + G1[j][0];
  385.       P[j] := IntToRGB(ERGB(SumR/5, SumG/5, SumB/5));
  386.     end;
  387.   end;
  388. end;
  389.  
  390. procedure ColoriseImage(Bmp : TBitmap; BaseColor : TColor);
  391. var
  392.   i, j : Integer;
  393.   p: PRGBArray;
  394. begin
  395.   if Bmp.PixelFormat <> pf24Bit then
  396.   begin
  397.     EBitmapOperationError.Create('Only 24 bit bitmaps can be operated.');
  398.   end;
  399.   for i := 0 to Bmp.Height-1 do
  400.   begin
  401.     P := Bmp.Scanline[i];
  402.     for j := 0 to Bmp.Width-1 do
  403.     begin
  404.       P[j] := IntToRGB(Colorise(RGBToInt(P[j]), BaseColor));
  405.     end;
  406.   end;
  407. end;
  408.  
  409. initialization
  410.   TmpMem := TBitmap.Create;
  411.  
  412. finalization
  413.   TmpMem.Free;
  414.  
  415.  
  416. end.
  417.  
  418.  
  419.  

I also written another unit which is required by the above unit (grafman.pas), it contains all useful function for tile bitmaps, apply a mask to a bitmap, draw a 3D text, etc

Show Code | Download DrawMan.pas

  1.  
  2. { ---------------------------------------------------
  3.     Drawing Manager  Copyright (r) by DreamFactory
  4.     Version : 1.75   Author : William Yang
  5.     Last Update 10 - Sep - 97
  6.   --------------------------------------------------- }
  7.  
  8. unit DrawMan;
  9.  
  10. interface
  11.  
  12. { ------------------------------------------------------------------------
  13.  
  14.   HOW TO Draw a transparent image
  15.   1. Create a mask first.
  16.     * Draw a Black & White image with black as the non-transparent area.
  17.   2. Create a Storage bitmap.
  18.      For store the background image.
  19.      1 Copy the background with the size of the transparent image.
  20.      2 Paint the Transparent Image on to the Storage Bitmap.
  21.        Use CopyMode of cmSrcInvert.
  22.        All the colors will be Inverted.
  23.      3 Paint the mask on to the storage bitmap.
  24.        Use CopyMode of cmSrcAnd.
  25.        This will only paint the black area on to the bitmap.
  26.      4 Agian paint the Transparent Image on to the Storage Bitmap.
  27.        Use CopyMode of cmSrcInvert.
  28.        The black area will be painted with the Image.
  29.        and the other parts will restore to orignal color.
  30.   3. Paint the Storage bitmap on to the Destination Canvas.
  31.  
  32.   See PaintOnMask, PaintOnText.
  33. -------------------------------------------------------------------------}
  34.  
  35. uses Windows, Classes, Controls ,Graphics, ColorMan, ExtCtrls,
  36.   NumMan, SysUtils;
  37.  
  38. {$I DFDefin.inc}
  39.  
  40. {Draw a rounded button}
  41. procedure RoundButton(Canvas : TCanvas; Size : TRect;
  42.   ButtonColor, SeatColor : TColor; SWidth : Integer );
  43.  
  44. {Draw a 3D rectangle which the colours are fit the given "Color"}
  45. {Style: 1:Raise, 2:Sunk, 3:Frame}
  46. procedure Draw3D(Dest : TCanvas; Area : TRect; Color : TColor;
  47.   Style, Width : Integer);
  48. {Like Frame3D but this is for text}
  49. procedure Draw3DText(Dest : TCanvas; Text: String; X, Y : Integer; HighEdge, LowEdge: TColor);
  50.  
  51. {Paint Tiled "Src" in "Dest"
  52. Area indicates the painting rectangle }
  53. procedure MultiPaint(Dest : TCanvas; Src : TGraphic; Area : TRect);
  54.  
  55. {Paint transparent "Bmp" on the "Dest"}
  56. procedure TransparentBlt (Dest : TCanvas; Bmp : TBitmap;
  57.   destX, destY : Integer; TransColor : TColor);
  58. {One parameter ignored, TransColor is the first pixel of your bitmap}
  59. procedure TransBlt(Dest : TCanvas; Bmp : TBitmap;
  60.   destX, destY : Integer);
  61.  
  62. {Draw text with shadow}
  63. procedure DrawShadowText(Dest: TCanvas; X, Y : Integer; Text: String);
  64.  
  65. {Draw the given text with shadow and more options}
  66. {SC : Outline Colour}
  67. procedure DrawShadowTextExt(Dest: TCanvas; X, Y : Integer; Text: String; SC: TColor;
  68.   SX, SY: Integer);
  69. //Create a mask for the source bitmap.
  70. function CreateMask(Src: TBitmap; TransColor: TColor): HBitmap;
  71. {Draw the given text and the outlines}
  72. {SC : Outline Colour}
  73. procedure DrawOutlinedText(Dest: TCanvas; X, Y : Integer; Text: String; SC: TColor);
  74. {Draw only the outlines of the given text}
  75. procedure DrawTextOutline(Dest: TCanvas; X, Y : Integer; Text: String; SC: TColor);
  76.  
  77. {Like multipaint but this can work out the Clipping area
  78. so you dont need to refresh the whole area when repaint,
  79. simply by send Canvas.ClipRect. }
  80. procedure MultiClipPaint(Dest : TCanvas; Src : TBitmap; Area, Clip : TRect);
  81.  
  82. {This one for paint big picture, it will chop it into small pieces
  83. and paint them on to the dest. (if you have few ram )}
  84. procedure BytesPaint(Dest : TCanvas; Area: TRect; Src : TBitmap);
  85.  
  86. {This function will give the rect measure in screen mode}
  87. {ClientToScreen only give Point of its parent control }
  88. function GetCtrlRect(const Ctrl: TControl): TRect;
  89. function GetCtrlPoint(const Ctrl: TControl): TPoint;
  90. {Merge rectangles to one piece}
  91. function MergeRect(R : array of TRect): TRect;
  92.  
  93.  
  94. {Paint bitmaps on the mask.
  95. the mask must be monochrome.}
  96.  
  97. procedure StretchPaintOnMask(Dest: TCanvas; X,Y : Integer; XMask, Bmp: TBitmap);
  98. procedure PaintOnMask(Dest: TCanvas; X,Y : Integer; XMask, Bmp: TBitmap);
  99.  
  100. { Some functions that will make you a nice text }
  101. { Paint bitmaps on text
  102.   Font can be modified before send the Canvas.
  103. }
  104. procedure PaintOnText(Dest: TCanvas; X,Y : Integer; Text: String; Bmp: TBitmap);
  105. // Stretch the bitmap to fit on the text.
  106. procedure StretchPaintOnText(Dest: TCanvas; X,Y : Integer; Text: String; Bmp: TBitmap);
  107.  
  108. //Set the size of bitmap rather than Width :=, Height :=.
  109. procedure SetSize(Bitmap: TBItmap; W, H: Integer);
  110. //Check if bitmap is Empty.
  111. function BmpIsNil(Bitmap: TBitmap): Boolean;
  112.  
  113. procedure TextSmooth(Canvas: TCanvas; X, Y: Integer; Text: String);
  114. procedure SmoothBlt(Canvas: TCanvas; X, Y: Integer; Bmp: TBitmap; Trans: TColor);
  115. function TransColor(Bmp: TBitmap): TColor;
  116. procedure DrawTextAnglo(Canvas: TCanvas; X, Y: Integer; Text: String; Anglo: Integer);
  117.  
  118. //Read Text Pixels
  119. type
  120.   TReadPixelProcs = procedure (Color: TColor);
  121.  
  122. procedure ReadPixels(Src: TBitmap; ReadProcs: TReadPixelProcs);
  123. //Use canvas so you send the font together.
  124. procedure ReadText(Canvas: TCanvas; Text: String; ReadProcs: TReadPixelProcs);
  125.  
  126. procedure ChopInto(Bmp: TBitmap; ImageList: TImageList);
  127.  
  128. implementation
  129.  
  130.  
  131. procedure ChopInto(Bmp: TBitmap; ImageList: TImageList);
  132. var
  133.   Chop, Mask: TBitmap;
  134.   i, Count: Integer;
  135.   S, R: TRect;
  136. begin
  137.   Chop := TBitmap.Create;
  138.   Chop.Width := Bmp.Height;
  139.   Count := Bmp.Width div Chop.Width;
  140.   Chop.Height := Bmp.Height;
  141.   R := Rect(0, 0, Chop.Width, Chop.Height);
  142.   S := R;
  143.   Mask := TBitmap.Create;
  144.   Mask.Width := Chop.Width; Mask.Height := Chop.Height;
  145.   for i := 1 to Count do
  146.   begin
  147.     Chop.Canvas.CopyRect(R, Bmp.Canvas, S);
  148.     Mask.Handle := CreateMask(Chop, Chop.TransparentColor);
  149.     ImageList.Add(Chop, Mask);
  150.     OffsetRect(S, Chop.Width, 0);
  151.   end;
  152.   Chop.Free;
  153.   Mask.Free;
  154. end;
  155.  
  156.  
  157. function TransColor(Bmp: TBitmap): TColor;
  158. begin
  159.   Result := Bmp.Canvas.Pixels[0, 0];
  160. end;
  161.  
  162. procedure SSetPixel(Canvas: TCanvas; X, Y: Integer; Color: TColor);
  163. begin
  164.   Canvas.Pixels[X, Y] := MergeColorExt(Color, Canvas.Pixels[X, Y], 30);
  165. end;
  166.  
  167. procedure SmoothBlt(Canvas: TCanvas; X, Y: Integer; Bmp: TBitmap; Trans: TColor);
  168. var
  169.   Back: TBitmap;
  170.   i,j : Integer;
  171.  
  172.   procedure SmoothPixel(ix, iy, Color: Integer);
  173.   begin
  174.     Back.Canvas.Pixels[ix, iy] := MergeColorExt(Back.Canvas.Pixels[ix, iy],
  175.       Color, 20);
  176.   end;
  177.  
  178. begin
  179.   if Trans < 0 then Trans := TransColor(Bmp);
  180.   Back := TBitmap.Create;
  181.   //the background picture will be slidely larger than the smooth image.
  182.   Back.Width := Bmp.Width + 2;   //**
  183.   Back.Height := Bmp.Height + 2; //**
  184.   //Create a background picture make it as small as possible.
  185.   Back.Canvas.CopyRect(Rect(0, 0, Back.Width, Back.Width), Canvas,
  186.     Bounds(x-1, y-1, Back.Width, Back.Width));
  187.   //Paint the image to back picture
  188.   TransparentBlt(Back.Canvas, Bmp, 1, 1, Trans);
  189.   //Only process the image area.  (see **)
  190.   for i := 1 to Back.Width-2 do
  191.     for j := 1 to Back.Height-2 do
  192.     begin
  193.       //Not in Image area, becase the size
  194.       if Bmp.Canvas.Pixels[i-1, j-1] <> Trans then
  195.       begin
  196.         if (Bmp.Canvas.Pixels[i-2, j-1] = Trans) then SmoothPixel(i-1, j, Bmp.Canvas.Pixels[i-1, j-1]);
  197.         if (Bmp.Canvas.Pixels[i-1, j-2] = Trans) then SmoothPixel(i, j-1, Bmp.Canvas.Pixels[i-1, j-1]);
  198.         if (Bmp.Canvas.Pixels[i, j-1] = Trans) then SmoothPixel(i+1, j, Bmp.Canvas.Pixels[i-1, j-1]);
  199.         if (Bmp.Canvas.Pixels[i-1, j] = Trans) then SmoothPixel(i, j+1, Bmp.Canvas.Pixels[i-1, j-1]);
  200.       end;
  201.     end;
  202.   Canvas.Draw(x-1, y-1, Back);
  203.   Back.Free;
  204. end;
  205.  
  206. procedure TextSmooth(Canvas: TCanvas; X, Y: Integer; Text: String);
  207. var
  208.   Tb, Tmp: TBitmap;
  209.   i, j: Integer;
  210.   Count, R, G, B: Integer;
  211.  
  212.   procedure AddPixel(row, col: Integer);
  213.   var
  214.     Color: TColor;
  215.   begin
  216.     Color := Tb.Canvas.Pixels[row, col];
  217.     if Color = $FFFFFF then
  218.     begin
  219.       Color := (Tmp.Canvas.Pixels[row+1, col+1]);
  220.     Inc(R, MulDiv(GetRValue(Color), 2, 3));
  221.      Inc(G, MulDiv(GetGValue(Color), 2, 3));
  222.      Inc(B, MulDiv(GetBValue(Color), 2, 3));
  223.       Inc(Count);
  224.     end;
  225.   end;
  226.  
  227. begin
  228.   //Paint text to BW bitmap first.
  229.   Tb := TBitmap.Create;
  230.   Tb.Width := Canvas.TextWidth(Text);
  231.   Tb.Height := Canvas.TextHeight(Text);
  232.   Tb.Monochrome := True;
  233.   Tb.Canvas.Brush.Color := clWhite;
  234.   Tb.Canvas.Font.Assign(Canvas.Font);
  235.   Tb.Canvas.Font.Color := clBlack;
  236.   Tb.Canvas.Textout(0, 0, Text);
  237.   Tmp := TBitmap.Create;
  238.   Tmp.Width := Tb.Width + 2;
  239.   Tmp.Height := Tb.Height + 2;
  240.   Tmp.PixelFormat := pf24Bit;
  241.   Tmp.Canvas.CopyRect(Rect(0, 0, Tmp.Width, Tmp.Height), Canvas,
  242.     Bounds(x-1, y-1, Tmp.Width, Tmp.Height));
  243.   for i := 0 to Tb.Width-1 do
  244.     for j := 0 to Tb.Height-1 do
  245.     begin
  246.       if tb.Canvas.Pixels[i, j] = clBlack then
  247.       begin
  248.         Count := 1;
  249.         //get all colors around the pixel
  250.         r := 0; g := 0; b := 0;
  251.         r := GetRValue(ColorToRGB(Canvas.Font.Color));
  252.         g := GetGValue(ColorToRGB(Canvas.Font.Color));
  253.         b := GetBValue(ColorToRGB(Canvas.Font.Color));
  254.         AddPixel(i-1, j);
  255.         AddPixel(i, j-1);
  256.         AddPixel(i, j+1);
  257.         AddPixel(i+1, j);
  258.         Tmp.Canvas.Pixels[i+1, j+1] := RGB(r div Count, g div Count, b div Count);
  259.       end;
  260.     end;
  261.   Canvas.Draw(x, y, Tmp);
  262.   Tmp.Free;
  263.   Tb.Free;
  264. end;
  265.  
  266. procedure DrawTextAnglo(Canvas: TCanvas; X, Y: Integer; Text: String; Anglo: Integer);
  267. var
  268.   hFont: Integer;
  269.   Weight: Integer;
  270.   Italic: Integer;
  271.   Under: Integer;
  272.   Strike: Integer;
  273.   Fontname: array[1..32] of Char;
  274. begin
  275.   if fsBold in Canvas.Font.Style then Weight := 700 else Weight := 400;
  276.   if fsItalic in Canvas.Font.Style then Italic := 1  else Italic := 0;
  277.   if fsUnderline in Canvas.Font.Style then Under := 1 else Under := 0;
  278.   if fsStrikeout in Canvas.Font.Style then Strike := 1 else Strike := 0;
  279.   StrPCopy(@Fontname, Canvas.Font.Name);
  280.   hFont := CreateFont(Abs(Canvas.Font.Height), 0, 0, Anglo, Weight,
  281.     Italic, Under, Strike, 0, 0, PROOF_QUALITY, DEFAULT_PITCH, 0, @Fontname);
  282.  
  283.   Canvas.Textout(x, y, Text);
  284.   DeleteObject(hfont);
  285. end;
  286.  
  287. procedure ReadPixels(Src: TBitmap; ReadProcs: TReadPixelProcs);
  288. var
  289.   i, j : Integer;
  290. begin
  291.   for i := 0 to Src.Width do
  292.     for j := 0 to Src.Height do
  293.     begin
  294.       ReadProcs(GetPixel(Src.Canvas.Handle, i, j));
  295.     end;
  296. end;
  297.  
  298. function BmpIsNil(Bitmap: TBitmap): Boolean;
  299. begin
  300.   Result := False;
  301.   if Bitmap = nil then
  302.   begin
  303.     Result := True;
  304.     Exit;
  305.   end;
  306.   if (Bitmap.Width = 0) or (Bitmap.Height = 0) then
  307.   begin
  308.     Result := True;
  309.     Exit;
  310.   end;
  311. end;
  312.  
  313. procedure SetSize(Bitmap: TBItmap; W, H: Integer);
  314. begin
  315.   Bitmap.Width := W;
  316.   Bitmap.Height := H;
  317. end;
  318.  
  319. procedure ReadText(Canvas: TCanvas; Text: String; ReadProcs: TReadPixelProcs);
  320. var
  321.   BWText: TBitmap;
  322. begin
  323.   BWText := TBitmap.Create;
  324.   BWText.Monochrome := True;
  325.   BWText.Width := Canvas.TextWidth(Text);
  326.   BWText.Height := Canvas.TextHeight(Text);
  327.   //ensure that font.color is Black.
  328.   Canvas.Font.Color := clBlack;
  329.   BWText.Canvas.Textout(0, 0, Text);
  330.   ReadPixels(BWText, ReadProcs);
  331.   BWText.Free;
  332. end;
  333.  
  334. function MergeRect(R: array of TRect): TRect;
  335. var
  336.   i: Integer;
  337. begin
  338.   //Get the first one, so we compare it to the others
  339.   Result := R[Low(R)];
  340.   for i := Low(R) + 1 to High(R) do
  341.   begin
  342.     //Compare the Top/Left point keep the small ones.
  343.     Result.Left := Min(Result.Left, R[i].Left);
  344.     Result.Top := Min(Result.Top, R[i].Top);
  345.     //Compare the Right/Bottom kepp the Big ones
  346.     Result.Right := Max(Result.Right, R[i].Right);
  347.     Result.Bottom := Max(Result.Bottom, R[i].Bottom);
  348.   end;
  349. end;
  350.  
  351. function GetCtrlRect(const Ctrl: TControl): TRect;
  352. var
  353.   FParent : TControl;
  354. begin
  355.   FParent := Ctrl;
  356.   Result := FParent.ClientRect;
  357.   while FParent.HasParent do
  358.   begin
  359.     if not FParent.Parent.HasParent then Exit;
  360.     FParent := FParent.Parent;
  361.     OffsetRect(Result, FParent.Left, FParent.Top);
  362.   end;
  363. end;
  364.  
  365. function GetCtrlPoint(const Ctrl: TControl): TPoint;
  366. var
  367.   FParent : TControl;
  368. begin
  369.   FParent := Ctrl;
  370.   with Result do
  371.   begin
  372.     Result.X := 0; Result.Y := 0;
  373.     Result.X := Result.X + Ctrl.Left;
  374.     Result.Y := Result.Y + Ctrl.Top;
  375.     while FParent.HasParent do
  376.     begin
  377.       FParent := FParent.Parent;
  378.       Result.X := Result.X + FParent.Left;
  379.       Result.Y := Result.Y + FParent.Top;
  380.     end;
  381.   end;
  382. end;
  383.  
  384.  
  385. procedure DrawOutlinedText(Dest: TCanvas; X, Y : Integer; Text: String; SC: TColor);
  386. var</