RealICQColors.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. {
  2. 文件名:RealICQColors.pas
  3. 功 能:此单元定义了进行颜色变换,绘图等功能所必须的方法、过程。
  4. 建 立:尹进
  5. 历 史:
  6. 2005.12.23:补文件说明信息(尹进)
  7. }
  8. unit RealICQColors;
  9. interface
  10. uses
  11. Windows, Graphics, SysUtils, Math, Forms, Classes, pngimage;
  12. const
  13. MaxPixelCount = 65536;
  14. type
  15. PRGBTripleArray = ^TRGBTripleArray;
  16. TRGBTripleArray = array[0..MaxPixelCount - 1] of TRGBTriple;
  17. TIconButtonState = (ibDown, ibUp, ibClear);
  18. procedure Grayscale(Const Bitmap:TBitmap);
  19. procedure PrintBitmap(aCanvas : TCanvas; Dest : TRect; Bitmap : TBitmap);
  20. function ConvertBitmapToRTF(const Bitmap: TBitmap): string;
  21. procedure HSLtoRGB(H, S, L: Double; var R, G, B: Integer);
  22. procedure RGBtoHSL(R, G, B: Integer; var H, S, L: Double);
  23. procedure ConvertBitmapToColor(DestBitmap:TBitmap;DestColor:TColor);
  24. procedure ConvertBitmapToLighter(DestBitmap:TBitmap;FLightAdd:Integer);
  25. procedure ConvertBitmapToSaturation(DestBitmap:TBitmap;FSaturationAdd:Integer);
  26. function ConvertColorToColor(SourceColor: TColor; DestColor: TColor): TColor;
  27. function ConvertColorToLighter(SourceColor: TColor; FLightAdd:Integer): TColor;
  28. //平均模糊
  29. procedure SmoothAverage(SrcBitmap: TBitmap; TargetBitmap: TBitmap; iBlockLen: Integer);
  30. //从位图获取路径
  31. function GetRegionFromBitmap(StartX, StartY: Integer; DestBitmap:TBitmap; TransparentColor: TColor): HRGN;
  32. //拉幕方式显示位置
  33. procedure AnimateShowBitmap(SrcBMP: TBitmap; DestBMP: TBitmap);
  34. //对图片进行大小变换
  35. function GetSamllBitmap(AFileName: String; ANewWidth, ANewHeight: Integer; AKeepScale: Boolean = False): TBitmap;
  36. //绘制按钮的边框
  37. procedure DrawIconButton(ACanvas: TCanvas; ADefaultColor, ALightColor, AShadownColor: TColor;
  38. ARect: TRect; AIconButtonState: TIconButtonState; ABaseTop: Integer = 0);
  39. implementation
  40. {改变Bitmap的亮度}
  41. procedure ConvertBitmapToLighter(DestBitmap:TBitmap;FLightAdd:Integer);
  42. var
  43. x, y, ScanlineBytes: integer;
  44. p: prgbtriplearray;
  45. RVALUE, bvalue, gvalue: integer;
  46. hVALUE, sVALUE, lVALUE: Double;
  47. begin
  48. if not DestBitmap.Empty then
  49. begin
  50. DestBitmap.PixelFormat:=pf24bit;
  51. p := DestBitmap.ScanLine[0];
  52. ScanlineBytes := integer(DestBitmap.ScanLine[1]) - integer(DestBitmap.ScanLine[0]);
  53. for y := 0 to DestBitmap.Height - 1 do
  54. begin
  55. for x := 0 to DestBitmap.Width - 1 do
  56. begin
  57. RVALUE := p[x].rgbtRed;
  58. gVALUE := p[x].rgbtGreen;
  59. bVALUE := p[x].rgbtBlue;
  60. RGBtoHSL(RVALUE, gVALUE, bVALUE, hVALUE, sVALUE, lVALUE);
  61. lVALUE := min(100, lVALUE + FLightAdd);
  62. HSLtorgb(hVALUE, sVALUE, lVALUE, rVALUE, gVALUE, bVALUE);
  63. p[x].rgbtRed := RVALUE;
  64. p[x].rgbtGreen := gVALUE;
  65. p[x].rgbtBlue := bVALUE;
  66. end;
  67. inc(integer(p), ScanlineBytes);
  68. end;
  69. end;
  70. end;
  71. //------------------------------------------------------------------------------
  72. {改变Color的亮度}
  73. function ConvertColorToLighter(SourceColor: TColor; FLightAdd:Integer): TColor;
  74. var
  75. RVALUE, bvalue, gvalue: integer;
  76. hVALUE, sVALUE, lVALUE: Double;
  77. begin
  78. rVALUE := StrToInt('$'+Copy(IntToHex(SourceColor,6),5,2));
  79. gVALUE := StrToInt('$'+Copy(IntToHex(SourceColor,6),3,2));
  80. bVALUE := StrToInt('$'+Copy(IntToHex(SourceColor,6),1,2));
  81. RGBtoHSL(rVALUE, gVALUE, bVALUE, hVALUE, sVALUE, lVALUE);
  82. HSLtoRGB(hVALUE, sVALUE, Max(0, Min(100, lVALUE + FLightAdd)), rVALUE, gVALUE, bVALUE);
  83. Result := TColor( StrToInt('$' + IntToHex(bVALUE,2) + IntToHex(gVALUE,2) + IntToHex(rVALUE,2)) );
  84. end;
  85. //------------------------------------------------------------------------------
  86. procedure DrawIconButton(ACanvas: TCanvas; ADefaultColor, ALightColor, AShadownColor: TColor;
  87. ARect: TRect; AIconButtonState: TIconButtonState; ABaseTop: Integer = 0);
  88. begin
  89. ARect.Top := ARect.Top + ABaseTop;
  90. ARect.Bottom := ARect.Bottom + ABaseTop;
  91. //------------------
  92. if AIconButtonState = ibClear then
  93. ACanvas.Pen.Color := ADefaultColor
  94. else if AIconButtonState = ibDown then
  95. ACanvas.Pen.Color := AShadownColor
  96. else
  97. ACanvas.Pen.Color := ALightColor;
  98. ACanvas.MoveTo(ARect.Left, ARect.Top + 1);
  99. ACanvas.LineTo(ARect.Left, ARect.Bottom - 1);
  100. ACanvas.MoveTo(ARect.Left + 1, ARect.Top);
  101. ACanvas.LineTo(ARect.Right - 1, ARect.Top);
  102. //------------------
  103. //------------------
  104. if AIconButtonState = ibClear then
  105. ACanvas.Pen.Color := ADefaultColor
  106. else if AIconButtonState = ibDown then
  107. ACanvas.Pen.Color := ALightColor
  108. else
  109. ACanvas.Pen.Color := AShadownColor;
  110. ACanvas.MoveTo(ARect.Right - 1, ARect.Top + 1);
  111. ACanvas.LineTo(ARect.Right - 1, ARect.Bottom - 1);
  112. ACanvas.MoveTo(ARect.Right - 2, ARect.Bottom - 1);
  113. ACanvas.LineTo(ARect.Left, ARect.Bottom - 1);
  114. end;
  115. //------------------------------------------------------------------------------
  116. function GetSamllBitmap(AFileName: String; ANewWidth, ANewHeight: Integer; AKeepScale: Boolean = False): TBitmap;
  117. var
  118. Picture: TPicture;
  119. Bitmap1,
  120. Bitmap2: TBitmap;
  121. Rect2: TRect;
  122. PngObject: TPngObject;
  123. BMP: TBitmap;
  124. begin
  125. Result := nil;
  126. Picture := TPicture.Create;
  127. Bitmap1 := TBitmap.Create;
  128. Bitmap2 := TBitmap.Create;
  129. Bitmap2.SetSize(ANewWidth, ANewHeight);
  130. if not FileExists(AFileName) then
  131. begin
  132. Result := TBitmap.Create;
  133. Exit;
  134. end;
  135. try
  136. try
  137. if AnsiSameText(ExtractFileExt(AFileName), '.png') then
  138. begin
  139. PngObject := TPngObject.Create;
  140. try
  141. PngObject.LoadFromFile(AFileName);
  142. Bitmap1.Assign(PngObject);
  143. finally
  144. PngObject.Free;
  145. end;
  146. end
  147. else
  148. begin
  149. Picture.LoadFromFile(AFileName);
  150. Bitmap1.Assign(Picture.Graphic);
  151. end;
  152. if (Bitmap1.Width < ANewWidth) and (Bitmap1.Height < ANewHeight) and (AKeepScale) then
  153. begin
  154. Bitmap2.Assign(Bitmap1);
  155. Result := Bitmap2;
  156. Exit;
  157. end;
  158. except
  159. exit;
  160. end;
  161. if not AKeepScale then
  162. begin
  163. Rect2.Left := 0;
  164. Rect2.Top := 0;
  165. Rect2.Right := ANewWidth;
  166. Rect2.Bottom := ANewHeight;
  167. end
  168. else
  169. begin
  170. if Bitmap1.Width > Bitmap1.Height then
  171. begin
  172. Rect2.Left := 0;
  173. Rect2.Right := ANewWidth;
  174. Rect2.Bottom := Round(ANewWidth * (Bitmap1.Height / Bitmap1.Width));
  175. Rect2.Top := (ANewHeight - Rect2.Bottom) div 2;
  176. Rect2.Bottom := Rect2.Bottom + Rect2.Top;
  177. end
  178. else
  179. begin
  180. Rect2.Top := 0;
  181. Rect2.Bottom := ANewHeight;
  182. Rect2.Right := Round(ANewHeight * (Bitmap1.Width / Bitmap1.Height));
  183. Rect2.Left := (ANewWidth - Rect2.Right) div 2;
  184. Rect2.Right := Rect2.Right + Rect2.Left;
  185. end
  186. end;
  187. Bitmap2.Canvas.FillRect(Rect2);
  188. Bitmap2.Canvas.StretchDraw(Rect2, Bitmap1);
  189. Result := Bitmap2;
  190. finally
  191. if Result = nil then Bitmap2.Free;
  192. Bitmap1.Free;
  193. Picture.Free;
  194. end;
  195. end;
  196. //------------------------------------------------------------------------------
  197. procedure AnimateShowBitmap(SrcBMP: TBitmap; DestBMP: TBitmap);
  198. var
  199. iLoop: Integer;
  200. TempBitmap1,
  201. TempBitmap2: TBitmap;
  202. begin
  203. TempBitmap1 := TBitmap.Create;
  204. TempBitmap2 := TBitmap.Create;
  205. try
  206. TempBitmap1.Assign(SrcBMP);
  207. TempBitmap2.SetSize(DestBMP.Width, DestBMP.Height);
  208. TempBitmap2.Canvas.StretchDraw(Rect(0, 0, DestBMP.Width, DestBMP.Height),
  209. TempBitmap1);
  210. for iLoop := 0 to TempBitmap2.Height - 1 do
  211. begin
  212. if (DestBMP = nil) or (SrcBMP = nil) then Exit;
  213. DestBMP.Canvas.CopyRect(Rect(0, iLoop, TempBitmap2.Width, iLoop + 1),
  214. TempBitmap2.Canvas,
  215. Rect(0, iLoop, TempBitmap2.Width, iLoop + 1));
  216. Sleep(5);
  217. end;
  218. finally
  219. TempBitmap2.free;
  220. TempBitmap1.free;
  221. end;
  222. end;
  223. //------------------------------------------------------------------------------
  224. function GetRegionFromBitmap(StartX, StartY: Integer; DestBitmap:TBitmap; TransparentColor: TColor): HRGN;
  225. var
  226. Region1,
  227. Region2 :HRGN;
  228. X, Y, ScanlineBytes: Integer;
  229. P: PRGBTripleArray;
  230. begin
  231. Region1 := CreateRectRgn(StartX, StartY, StartX, StartY);
  232. if not DestBitmap.Empty then
  233. begin
  234. P := DestBitmap.ScanLine[0];
  235. ScanlineBytes := Integer(DestBitmap.ScanLine[1]) - Integer(DestBitmap.ScanLine[0]);
  236. for Y := 0 to DestBitmap.Height - 1 do
  237. begin
  238. for X := 0 to DestBitmap.Width - 1 do
  239. begin
  240. if TransparentColor = p[X].rgbtBlue * 256 * 256 + p[X].rgbtGreen * 256 + p[X].rgbtBlue then continue;
  241. Region2 := CreateRectRgn(StartX + X, StartY + Y, StartX + X + 1, StartY + Y + 1);
  242. CombineRgn(Region1, Region1, Region2, RGN_OR);
  243. DeleteObject(Region2);
  244. end;
  245. Inc(Integer(P), ScanlineBytes);
  246. end;
  247. end;
  248. Result := Region1;
  249. end;
  250. //------------------------------------------------------------------------------
  251. {将Bitmap转换为RTF格式}
  252. function ConvertBitmapToRTF(const Bitmap: TBitmap): string;
  253. var
  254. bi, bb: string;
  255. bis, bbs: Cardinal;
  256. achar: string[2];
  257. Buffer: string;
  258. I: Integer;
  259. type
  260. PWord = ^Word;
  261. begin
  262. GetDIBSizes(Bitmap.Handle, bis, bbs);
  263. SetLength(bi, bis);
  264. SetLength(bb, bbs);
  265. GetDIB(Bitmap.Handle, Bitmap.Palette, PChar(bi)^, PChar(bb)^);
  266. SetLength(Buffer, (Length(bb) + Length(bi)) * 2);
  267. i := 1;
  268. for bis := 1 to Length(bi) do
  269. begin
  270. achar := IntToHex(Integer(bi[bis]), 2);
  271. PWord(@Buffer[i])^ := PWord(@achar[1])^;
  272. inc(i, 2);
  273. end;
  274. for bbs := 1 to Length(bb) do
  275. begin
  276. achar := IntToHex(Integer(bb[bbs]), 2);
  277. PWord(@Buffer[i])^ := PWord(@achar[1])^;
  278. inc(i, 2);
  279. end;
  280. Result := '{\rtf1 {\pict\dibitmap ' + Buffer + ' }}';
  281. end;
  282. //------------------------------------------------------------------------------
  283. {改变Bitmap的饱和度}
  284. procedure ConvertBitmapToSaturation(DestBitmap:TBitmap;FSaturationAdd:Integer);
  285. var
  286. x, y, ScanlineBytes: integer;
  287. p: prgbtriplearray;
  288. RVALUE, bvalue, gvalue: integer;
  289. hVALUE, sVALUE, lVALUE: Double;
  290. begin
  291. if not DestBitmap.Empty then
  292. begin
  293. DestBitmap.PixelFormat:=pf24bit;
  294. p := DestBitmap.ScanLine[0];
  295. ScanlineBytes := integer(DestBitmap.ScanLine[1]) - integer(DestBitmap.ScanLine[0]);
  296. for y := 0 to DestBitmap.Height - 1 do
  297. begin
  298. for x := 0 to DestBitmap.Width - 1 do
  299. begin
  300. RVALUE := p[x].rgbtRed;
  301. gVALUE := p[x].rgbtGreen;
  302. bVALUE := p[x].rgbtBlue;
  303. RGBtoHSL(RVALUE, gVALUE, bVALUE, hVALUE, sVALUE, lVALUE);
  304. sVALUE := min(100, sVALUE + FSaturationAdd);
  305. HSLtorgb(hVALUE, sVALUE, lVALUE, rVALUE, gVALUE, bVALUE);
  306. p[x].rgbtRed := RVALUE;
  307. p[x].rgbtGreen := gVALUE;
  308. p[x].rgbtBlue := bVALUE;
  309. end;
  310. inc(integer(p), ScanlineBytes);
  311. end;
  312. end;
  313. end;
  314. //------------------------------------------------------------------------------
  315. {改变Bitmap的色调}
  316. procedure ConvertBitmapToColor(DestBitmap:TBitmap;DestColor:TColor);
  317. var
  318. hexString:String;
  319. x, y, ScanlineBytes: integer;
  320. p: prgbtriplearray;
  321. RVALUE, bvalue, gvalue: integer;
  322. hVALUE, sVALUE, lVALUE: Double;
  323. hNewVALUE, sNewVALUE, lNewVALUE : Double;
  324. begin
  325. if not DestBitmap.Empty then
  326. begin
  327. hexString:=IntToHex(DestColor,6);
  328. RGBtoHSL(StrToInt('$'+Copy(hexString,5,2)), StrToInt('$'+Copy(hexString,3,2)), StrToInt('$'+Copy(hexString,1,2)), hNewVALUE, sNewVALUE, lNewVALUE);
  329. DestBitmap.PixelFormat:=pf24bit;
  330. p := DestBitmap.ScanLine[0];
  331. ScanlineBytes := integer(DestBitmap.ScanLine[1]) - integer(DestBitmap.ScanLine[0]);
  332. for y := 0 to DestBitmap.Height - 1 do
  333. begin
  334. for x := 0 to DestBitmap.Width - 1 do
  335. begin
  336. RVALUE := p[x].rgbtRed;
  337. gVALUE := p[x].rgbtGreen;
  338. bVALUE := p[x].rgbtBlue;
  339. RGBtoHSL(RVALUE, gVALUE, bVALUE, hVALUE, sVALUE, lVALUE);
  340. HSLtoRGB(hNewVALUE, sNewVALUE, lVALUE, rVALUE, gVALUE, bVALUE);
  341. p[x].rgbtRed := RVALUE;
  342. p[x].rgbtGreen := gVALUE;
  343. p[x].rgbtBlue := bVALUE;
  344. end;
  345. inc(integer(p), ScanlineBytes);
  346. end;
  347. end;
  348. end;
  349. //------------------------------------------------------------------------------
  350. {改变Color的色调}
  351. function ConvertColorToColor(SourceColor: TColor; DestColor: TColor): TColor;
  352. var
  353. hexString:String;
  354. hNewVALUE, sNewVALUE, lNewVALUE : Double;
  355. RVALUE, bvalue, gvalue: integer;
  356. hVALUE, sVALUE, lVALUE: Double;
  357. begin
  358. hexString:=IntToHex(DestColor,6);
  359. RGBtoHSL(StrToInt('$'+Copy(hexString,5,2)), StrToInt('$'+Copy(hexString,3,2)), StrToInt('$'+Copy(hexString,1,2)), hNewVALUE, sNewVALUE, lNewVALUE);
  360. rVALUE := StrToInt('$'+Copy(IntToHex(SourceColor,6),5,2));
  361. gVALUE := StrToInt('$'+Copy(IntToHex(SourceColor,6),3,2));
  362. bVALUE := StrToInt('$'+Copy(IntToHex(SourceColor,6),1,2));
  363. RGBtoHSL(rVALUE, gVALUE, bVALUE, hVALUE, sVALUE, lVALUE);
  364. HSLtoRGB(hNewVALUE, sNewVALUE, lVALUE, rVALUE, gVALUE, bVALUE);
  365. Result := TColor( StrToInt('$' + IntToHex(bVALUE,2) + IntToHex(gVALUE,2) + IntToHex(rVALUE,2)) );
  366. end;
  367. //------------------------------------------------------------------------------
  368. {hsl颜色空间到rgb空间的转换}
  369. procedure HSLtoRGB(H, S, L: Double; var R, G, B: Integer);
  370. var //类似于返回多个值的函数
  371. Sat, Lum: Double;
  372. begin
  373. R := 0;
  374. G := 0;
  375. B := 0;
  376. if (H < 360) and (H >= 0) and (S <= 100) and (S >= 0) and (L <= 100) and (L
  377. >=
  378. 0) then
  379. begin
  380. if H <= 60 then
  381. begin
  382. R := 255;
  383. G := Round((255 / 60) * H);
  384. B := 0;
  385. end
  386. else if H <= 120 then
  387. begin
  388. R := Round(255 - (255 / 60) * (H - 60));
  389. G := 255;
  390. B := 0;
  391. end
  392. else if H <= 180 then
  393. begin
  394. R := 0;
  395. G := 255;
  396. B := Round((255 / 60) * (H - 120));
  397. end
  398. else if H <= 240 then
  399. begin
  400. R := 0;
  401. G := Round(255 - (255 / 60) * (H - 180));
  402. B := 255;
  403. end
  404. else if H <= 300 then
  405. begin
  406. R := Round((255 / 60) * (H - 240));
  407. G := 0;
  408. B := 255;
  409. end
  410. else if H < 360 then
  411. begin
  412. R := 255;
  413. G := 0;
  414. B := Round(255 - (255 / 60) * (H - 300));
  415. end;
  416. Sat := Abs((S - 100) / 100);
  417. R := Round(R - ((R - 128) * Sat));
  418. G := Round(G - ((G - 128) * Sat));
  419. B := Round(B - ((B - 128) * Sat));
  420. Lum := (L - 50) / 50;
  421. if Lum > 0 then
  422. begin
  423. R := Round(R + ((255 - R) * Lum));
  424. G := Round(G + ((255 - G) * Lum));
  425. B := Round(B + ((255 - B) * Lum));
  426. end
  427. else if Lum < 0 then
  428. begin
  429. R := Round(R + (R * Lum));
  430. G := Round(G + (G * Lum));
  431. B := Round(B + (B * Lum));
  432. end;
  433. end;
  434. end;
  435. //------------------------------------------------------------------------------
  436. {RGB空间到HSL空间的转换}
  437. procedure RGBtoHSL(R, G, B: Integer; var H, S, L: Double);
  438. var
  439. Delta: Double;
  440. CMax, CMin: Double;
  441. Red, Green, Blue, Hue, Sat, Lum: Double;
  442. begin
  443. Red := R / 255;
  444. Green := G / 255;
  445. Blue := B / 255;
  446. CMax := Max(Red, Max(Green, Blue));
  447. CMin := Min(Red, Min(Green, Blue));
  448. Lum := (CMax + CMin) / 2;
  449. if CMax = CMin then
  450. begin
  451. Sat := 0;
  452. Hue := 0;
  453. end
  454. else
  455. begin
  456. if Lum < 0.5 then
  457. Sat := (CMax - CMin) / (CMax + CMin)
  458. else
  459. Sat := (cmax - cmin) / (2 - cmax - cmin);
  460. delta := CMax - CMin;
  461. if Red = CMax then
  462. Hue := (Green - Blue) / Delta
  463. else if Green = CMax then
  464. Hue := 2 + (Blue - Red) / Delta
  465. else
  466. Hue := 4.0 + (Red - Green) / Delta;
  467. Hue := Hue / 6;
  468. if Hue < 0 then
  469. Hue := Hue + 1;
  470. end;
  471. H := (Hue * 360);
  472. S := (Sat * 100);
  473. L := (Lum * 100);
  474. end;
  475. //------------------------------------------------------------------------------
  476. procedure Grayscale(Const Bitmap:TBitmap);
  477. var
  478. X: Integer;
  479. Y: Integer;
  480. PRGB: pRGBTriple;
  481. Gray: Byte;
  482. begin
  483. Bitmap.HandleType:=bmDIB;
  484. Bitmap.PixelFormat:=pf24bit;
  485. for Y := 0 to (Bitmap.Height - 1) do
  486. begin
  487. PRGB := Bitmap.ScanLine[Y];
  488. for X := 0 to (Bitmap.Width - 1) do
  489. begin
  490. Gray := (77 * PRGB^.rgbtRed + 151 * PRGB^.rgbtGreen + 28 * PRGB^.rgbtBlue) shr 8;
  491. PRGB^.rgbtRed:=Gray;
  492. PRGB^.rgbtGreen:=Gray;
  493. PRGB^.rgbtBlue:=Gray;
  494. Inc(PRGB);
  495. end;
  496. end;
  497. end;
  498. //------------------------------------------------------------------------------
  499. procedure PrintBitmap(ACanvas: TCanvas; Dest: TRect; Bitmap: TBitmap);
  500. var
  501. Info : PBitmapInfo;
  502. InfoSize : DWORD;
  503. Image : Pointer;
  504. {$ifdef ver80}
  505. ImageSize : Longint;
  506. {$else}
  507. ImageSize : DWord;
  508. {$endif}
  509. begin
  510. with Bitmap do
  511. begin
  512. GetDIBSizes(Handle, InfoSize, ImageSize);
  513. Info := AllocMem(InfoSize);
  514. try
  515. Image := AllocMem(ImageSize);
  516. try
  517. GetDIB(Handle, Palette, Info^, Image^);
  518. if not Monochrome then
  519. SetStretchBltMode(ACanvas.Handle, STRETCH_DELETESCANS);
  520. with Info^.bmiHeader do
  521. StretchDIBits(aCanvas.Handle, Dest.Left, Dest.Top,
  522. Dest.RIght - Dest.Left, Dest.Bottom - Dest.Top,
  523. 0, 0, biWidth, biHeight, Image, Info^, DIB_RGB_COLORS, SRCCOPY);
  524. finally
  525. FreeMem(Image, ImageSize);
  526. end;
  527. finally
  528. FreeMem(Info, InfoSize);
  529. end;
  530. end;
  531. end;
  532. //------------------------------------------------------------------------------
  533. procedure SmoothAverage(SrcBitmap: TBitmap; TargetBitmap: TBitmap; iBlockLen: Integer);
  534. var
  535. iXStart,
  536. iYStart,
  537. iXEnd,
  538. iYEnd,
  539. iNum,
  540. iFirstR,
  541. iFirstG,
  542. iFirstB,
  543. iCurrR,
  544. iCurrG,
  545. iCurrB,
  546. x,
  547. y,
  548. ny,
  549. nx,
  550. iy,
  551. ix: Integer;
  552. pPixel,
  553. pUp,
  554. pDown,
  555. pWrite,
  556. pLeftRight: PRGBTripleArray;
  557. OldBitmap: TBitmap;
  558. DestBitmap: TBitmap;
  559. R,SR: TRect;
  560. StartTicket: Cardinal;
  561. begin
  562. DestBitmap := TBitmap.Create;
  563. DestBitmap.PixelFormat:=pf24bit;
  564. DestBitmap.Width := SrcBitmap.Width + iBlockLen * 2;
  565. DestBitmap.Height := SrcBitmap.Height + iBlockLen * 2;
  566. OldBitmap := TBitmap.Create;
  567. OldBitmap.PixelFormat:=pf24bit;
  568. OldBitmap.Width := SrcBitmap.Width + iBlockLen * 2;
  569. OldBitmap.Height := SrcBitmap.Height + iBlockLen * 2;
  570. SR.Left := 0;
  571. SR.Top := 0;
  572. SR.Right := SrcBitmap.Width;
  573. SR.Bottom := SrcBitmap.Height;
  574. R.Left := iBlockLen;
  575. R.Top := iBlockLen;
  576. R.Right := OldBitmap.Width - iBlockLen;
  577. R.Bottom := OldBitmap.Height - iBlockLen;
  578. OldBitmap.Canvas.CopyRect(R, SrcBitmap.Canvas, SR);
  579. iNum := iBlockLen * iBlockLen;
  580. iXStart := iBlockLen div 2; // 左上角的起始位置
  581. iYStart := iXStart;
  582. iXEnd := DestBitmap.Width - iBlockLen ; // X结束位置
  583. iYEnd := DestBitmap.Height - iBlockLen ; // Y结束位置
  584. iFirstR := 0;
  585. iFirstG := 0;
  586. iFirstB := 0; // 每行第一子块RGB和
  587. for y := 0 to iYEnd do
  588. begin
  589. if (y = 0) then // 计算第一个块 (左上角)
  590. begin
  591. for ny := 0 to iBlockLen - 1 do
  592. begin
  593. pPixel := OldBitmap.ScanLine[ny];
  594. for nx := 0 to iBlockLen - 1 do
  595. begin
  596. Inc(iFirstB, pPixel[nx].rgbtBlue);
  597. Inc(iFirstG, pPixel[nx].rgbtGreen);
  598. Inc(iFirstR, pPixel[nx].rgbtRed);
  599. end;
  600. end;
  601. end
  602. else // y方向下移块
  603. begin
  604. pUp := OldBitmap.ScanLine[y - 1];
  605. pDown := OldBitmap.ScanLine[y - 1 + iBlockLen];
  606. for nx := 0 to iBlockLen - 1 do
  607. begin
  608. iFirstB := iFirstB - pUp[nx].rgbtBlue + pDown[nx].rgbtBlue;
  609. iFirstG := iFirstG - pUp[nx].rgbtGreen + pDown[nx].rgbtGreen ;
  610. iFirstR := iFirstR - pUp[nx].rgbtRed + pDown[nx].rgbtRed;
  611. end;
  612. end;
  613. // 设置每行第一个象素
  614. pWrite := DestBitmap.ScanLine[y + iYStart];
  615. ix := iXStart;
  616. pWrite[ix].rgbtBlue := Round(iFirstB / iNum);
  617. pWrite[ix].rgbtGreen := Round(iFirstG / iNum);
  618. pWrite[ix].rgbtRed := Round(iFirstR / iNum);
  619. Inc(ix);
  620. // x方向推移块
  621. iCurrR := iFirstR;
  622. iCurrG := iFirstG;
  623. iCurrB := iFirstB;
  624. for x := 1 to iXEnd do
  625. begin
  626. // 减左列加右列
  627. for iy := 0 to iBlockLen - 1 do
  628. begin
  629. pLeftRight := OldBitmap.ScanLine[y + iy];
  630. iCurrB := iCurrB - pLeftRight[x - 1].rgbtBlue + pLeftRight[x + iBlockLen - 1].rgbtBlue;
  631. iCurrG := iCurrG - pLeftRight[x - 1].rgbtGreen + pLeftRight[x + iBlockLen - 1].rgbtGreen;
  632. iCurrR := iCurrR - pLeftRight[x - 1].rgbtRed + pLeftRight[x + iBlockLen - 1].rgbtRed;
  633. end;
  634. // 设置象素值
  635. pWrite[ix].rgbtBlue := Round(iCurrB / iNum);
  636. pWrite[ix].rgbtGreen := Round(iCurrG / iNum);
  637. pWrite[ix].rgbtRed := Round(iCurrR / iNum);
  638. Inc(ix);
  639. end;
  640. end;
  641. SR.Left := 0;
  642. SR.Top := 0;
  643. SR.Right := SrcBitmap.Width;
  644. SR.Bottom := SrcBitmap.Height;
  645. R.Left := iBlockLen;
  646. R.Top := iBlockLen;
  647. R.Right := OldBitmap.Width - iBlockLen;
  648. R.Bottom := OldBitmap.Height - iBlockLen;
  649. TargetBitmap.Canvas.CopyRect(SR, DestBitmap.Canvas, R);
  650. end;
  651. end.