MainUnit.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. unit MainUnit;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Resamplers Example
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Michael Hansen <[email protected]>
  26. * Mattias Andersson <[email protected]>
  27. * (parts of this example were taken from the previously published example,
  28. * FineResample Example by Alex A. Denisov)
  29. *
  30. * Portions created by the Initial Developer are Copyright (C) 2000-2005
  31. * the Initial Developer. All Rights Reserved.
  32. *
  33. * Contributor(s):
  34. *
  35. * Christian Budde (added parametrisation for some kernel resamplers)
  36. *
  37. * ***** END LICENSE BLOCK ***** *)
  38. interface
  39. {$I GR32.inc}
  40. {.$DEFINE Ex}
  41. uses
  42. {$IFNDEF FPC} Windows, {$ELSE} LCLIntf, LResources, {$ENDIF}
  43. SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,
  44. ComCtrls, GR32_Image, GR32_System, GR32_RangeBars, GR32, GR32_Resamplers
  45. {$IFDEF Ex},GR32_ResamplersEx {$ENDIF};
  46. type
  47. TFrmResamplersExample = class(TForm)
  48. CurveImage: TImage32;
  49. DstImg: TImage32;
  50. EdgecheckBox: TComboBox;
  51. GbrParameter: TGaugeBar;
  52. GbrTableSize: TGaugeBar;
  53. KernelClassNamesList: TComboBox;
  54. KernelModeList: TComboBox;
  55. LblKernelClass: TLabel;
  56. LblKernelMode: TLabel;
  57. LblParameter: TLabel;
  58. LblPixelAccessMode: TLabel;
  59. LblResamplersClass: TLabel;
  60. LblTableSize: TLabel;
  61. LblWrapMode: TLabel;
  62. PageControl: TPageControl;
  63. PnlKernelProperties: TPanel;
  64. PnlKernel: TPanel;
  65. PnlResampler: TPanel;
  66. PnlResamplerProperties: TPanel;
  67. ResamplerClassNamesList: TComboBox;
  68. ResamplingPaintBox: TPaintBox32;
  69. TabResampling: TTabSheet;
  70. SidePanel: TPanel;
  71. StatusBar: TStatusBar;
  72. TabDetails: TTabSheet;
  73. TabKernel: TTabSheet;
  74. WrapBox: TComboBox;
  75. procedure FormCreate(Sender: TObject);
  76. procedure FormClose(Sender: TObject; var Action: TCloseAction);
  77. procedure CurveImagePaintStage(Sender: TObject; Buffer: TBitmap32;
  78. StageNum: Cardinal);
  79. procedure DstImgResize(Sender: TObject);
  80. procedure EdgecheckBoxChange(Sender: TObject);
  81. procedure GbrParameterChange(Sender: TObject);
  82. procedure GbrParameterMouseUp(Sender: TObject; Button: TMouseButton;
  83. Shift: TShiftState; X, Y: Integer);
  84. procedure GbrTableSizeChange(Sender: TObject);
  85. procedure KernelClassNamesListClick(Sender: TObject);
  86. procedure KernelModeListChange(Sender: TObject);
  87. procedure ResamplerClassNamesListChange(Sender: TObject);
  88. procedure ResamplingPaintBoxResize(Sender: TObject);
  89. private
  90. procedure SetKernelParameter(Kernel: TCustomKernel);
  91. protected
  92. procedure BuildTestBitmap(Bitmap: TBitmap32);
  93. public
  94. Src : TBitmap32;
  95. ResamplingSrc: TBitmap32;
  96. procedure SrcChanged(Sender: TObject);
  97. end;
  98. var
  99. FrmResamplersExample: TFrmResamplersExample;
  100. implementation
  101. {$IFDEF FPC}
  102. {$R *.lfm}
  103. {$ELSE}
  104. {$R *.dfm}
  105. {$ENDIF}
  106. uses
  107. {$IFDEF FPC}
  108. LazJPG,
  109. {$ELSE}
  110. Jpeg,
  111. {$ENDIF}
  112. GR32_LowLevel;
  113. { TfmResamplersExample }
  114. procedure TFrmResamplersExample.FormCreate(Sender: TObject);
  115. var
  116. ResStream: TResourceStream;
  117. JPEG: TJPEGImage;
  118. begin
  119. Src := TBitmap32.Create;
  120. Src.OuterColor := $FFFF7F7F;
  121. DstImg.Bitmap.OuterColor := Src.OuterColor;
  122. DstImg.SetupBitmap;
  123. Src.OnChange := SrcChanged;
  124. ResamplingSrc := TBitmap32.Create;
  125. // load example image
  126. JPEG := TJPEGImage.Create;
  127. try
  128. ResStream := TResourceStream.Create(HInstance, 'Iceland', RT_RCDATA);
  129. try
  130. JPEG.LoadFromStream(ResStream);
  131. finally
  132. ResStream.Free;
  133. end;
  134. ResamplingSrc.Assign(JPEG);
  135. finally
  136. JPEG.Free;
  137. end;
  138. ResamplerList.GetClassNames(ResamplerClassNamesList.Items);
  139. KernelList.GetClassNames(KernelClassNamesList.Items);
  140. ResamplerClassNamesList.ItemIndex := 0;
  141. KernelClassNamesList.ItemIndex := 0;
  142. // build 16 x 16 test bitmap
  143. BuildTestBitmap(Src);
  144. with CurveImage.PaintStages[0]^ do
  145. if Stage = PST_CLEAR_BACKGND then Stage := PST_CUSTOM;
  146. ResamplingPaintBox.BufferOversize := 0;
  147. end;
  148. procedure TFrmResamplersExample.FormClose(Sender: TObject; var Action: TCloseAction);
  149. begin
  150. Src.Free;
  151. ResamplingSrc.Free;
  152. end;
  153. procedure TFrmResamplersExample.BuildTestBitmap(Bitmap: TBitmap32);
  154. var
  155. I, J: Integer;
  156. Clr: TColor32;
  157. const
  158. CBlackWhite32: array [0..1] of TColor32 = (clBlack32, clWhite32);
  159. begin
  160. with Bitmap do
  161. begin
  162. SetSize(16, 16);
  163. for I := 0 to 15 do
  164. for J := 0 to 15 do
  165. Pixel[I, J] := CBlackWhite32[(I + J) mod 2];
  166. for I := 0 to 15 do
  167. begin
  168. Clr := Gray32(I * 255 div 15);
  169. PixelX[Fixed(I), Fixed( 9)] := Clr;
  170. PixelX[Fixed(I), Fixed(10)] := Clr;
  171. end;
  172. for I := 0 to 7 do
  173. begin
  174. Clr := Gray32(I * 255 div 7);
  175. Pixel[I * 2, 11] := Clr;
  176. Pixel[I * 2 + 1, 11] := Clr;
  177. Pixel[I * 2, 12] := Clr;
  178. Pixel[I * 2 + 1, 12] := Clr;
  179. Pixel[I * 2, 13] := Clr;
  180. Pixel[I * 2 + 1, 13] := Clr;
  181. end;
  182. for I := 1 to 4 do
  183. for J := 1 to 4 do
  184. Pixel[I, J] := $FF5F5F5F;
  185. for I := 2 to 3 do
  186. for J := 2 to 3 do
  187. Pixel[I, J] := $FFAFAFAF;
  188. end;
  189. end;
  190. procedure TFrmResamplersExample.KernelClassNamesListClick(Sender: TObject);
  191. var
  192. Index: Integer;
  193. begin
  194. Index := KernelClassNamesList.ItemIndex;
  195. if Src.Resampler is TKernelResampler then
  196. with TKernelResampler(Src.Resampler) do
  197. begin
  198. Kernel := TCustomKernelClass(KernelList[Index]).Create;
  199. LblParameter.Visible := (Kernel is TAlbrechtKernel) or
  200. {$IFDEF Ex}
  201. (Kernel is TGaussianKernel) or
  202. (Kernel is TKaiserBesselKernel) or
  203. (Kernel is TNutallKernel) or
  204. (Kernel is TBurgessKernel) or
  205. (Kernel is TBlackmanHarrisKernel) or
  206. (Kernel is TLawreyKernel) or
  207. {$ENDIF}
  208. (Kernel is TSinshKernel);
  209. GbrParameter.Visible := LblParameter.Visible;
  210. SetKernelParameter(Kernel);
  211. CurveImage.Repaint;
  212. end;
  213. end;
  214. procedure TFrmResamplersExample.ResamplerClassNamesListChange(Sender: TObject);
  215. var
  216. R: TCustomResampler;
  217. begin
  218. with ResamplerClassNamesList do
  219. if ItemIndex >= 0 then
  220. begin
  221. Src.BeginUpdate;
  222. R := TCustomResamplerClass(ResamplerList[ItemIndex]).Create(Src);
  223. KernelClassNamesListClick(nil);
  224. Src.EndUpdate;
  225. Src.Changed;
  226. pnlKernel.Visible := R is TKernelResampler;
  227. tabKernel.TabVisible := R is TKernelResampler;
  228. end;
  229. end;
  230. procedure TFrmResamplersExample.DstImgResize(Sender: TObject);
  231. begin
  232. DstImg.SetupBitmap;
  233. SrcChanged(Self);
  234. end;
  235. procedure TFrmResamplersExample.SrcChanged(Sender: TObject);
  236. var
  237. I, J: Integer;
  238. sw, sh: Single;
  239. begin
  240. with DstImg.Bitmap do
  241. begin
  242. sw := Src.Width / DstImg.Bitmap.Width;
  243. sh := Src.Height / DstImg.Bitmap.Height;
  244. GlobalPerfTimer.Start;
  245. if TabResampling.Visible then
  246. ResamplingPaintBoxResize(Self)
  247. else if Src.WrapMode in [wmClamp, wmRepeat, wmMirror] then
  248. begin
  249. // manual resampling
  250. Src.Resampler.PrepareSampling;
  251. for J := 0 to Height - 1 do
  252. for I := 0 to Width - 1 do
  253. Pixel[I, J] := Src.Resampler.GetSampleFloat(I * sw - 0.5, J * sh - 0.5);
  254. Src.Resampler.FinalizeSampling;
  255. end;
  256. StatusBar.Panels[0].Text := GlobalPerfTimer.ReadMilliseconds + ' ms for rendering.';
  257. end;
  258. DstImg.Repaint;
  259. end;
  260. procedure TFrmResamplersExample.KernelModeListChange(Sender: TObject);
  261. begin
  262. with KernelModeList, Src do
  263. if (ItemIndex >= 0) and (Resampler is TKernelResampler) then
  264. begin
  265. (Resampler as TKernelResampler).KernelMode := TKernelMode(ItemIndex);
  266. KernelClassNamesListClick(Self);
  267. end;
  268. end;
  269. procedure TFrmResamplersExample.EdgecheckBoxChange(Sender: TObject);
  270. begin
  271. Src.WrapMode := TWrapMode(WrapBox.ItemIndex);
  272. TCustomResampler(Src.Resampler).PixelAccessMode := TPixelAccessMode(EdgecheckBox.ItemIndex);
  273. end;
  274. procedure TFrmResamplersExample.GbrParameterChange(Sender: TObject);
  275. begin
  276. if Src.Resampler is TKernelResampler then
  277. with TKernelResampler(Src.Resampler)
  278. do SetKernelParameter(Kernel);
  279. end;
  280. procedure TFrmResamplersExample.GbrParameterMouseUp(Sender: TObject; Button: TMouseButton;
  281. Shift: TShiftState; X, Y: Integer);
  282. begin
  283. KernelClassNamesListClick(Sender);
  284. end;
  285. procedure TFrmResamplersExample.GbrTableSizeChange(Sender: TObject);
  286. begin
  287. LblTableSize.Caption := Format('Table Size (%d/100):', [GbrTableSize.Position]);
  288. end;
  289. function Sinc(Value: TFloat): TFloat;
  290. begin
  291. if Value <> 0 then
  292. begin
  293. Value := Value * Pi;
  294. Result := Sin(Value) / Value;
  295. end
  296. else Result := 1;
  297. end;
  298. procedure TFrmResamplersExample.SetKernelParameter(Kernel : TCustomKernel);
  299. begin
  300. if Kernel is TAlbrechtKernel then
  301. TAlbrechtKernel(Kernel).Terms := Round(GbrParameter.Position * 0.1) + 1
  302. else if Kernel is TGaussianKernel then
  303. TGaussianKernel(Kernel).Sigma := GbrParameter.Position * 0.1 + 1
  304. {$IFDEF Ex}
  305. else if Kernel is TKaiserBesselKernel then
  306. TKaiserBesselKernel(Kernel).Alpha := GbrParameter.Position * 0.1 + 1
  307. else if Kernel is TNutallKernel then
  308. TNutallKernel(Kernel).ContinousDerivationType := TCDType(GbrParameter.Position > 50)
  309. else if Kernel is TBurgessKernel then
  310. TBurgessKernel(Kernel).BurgessOpt := TBurgessOpt(GbrParameter.Position > 50)
  311. else if Kernel is TBlackmanHarrisKernel then
  312. TBlackmanHarrisKernel(Kernel).Terms := Round(GbrParameter.Position * 0.1) + 1
  313. else if Kernel is TLawreyKernel then
  314. TLawreyKernel(Kernel).Terms := Round(GbrParameter.Position * 0.1) + 1
  315. {$ENDIF}
  316. else if Kernel is TSinshKernel then
  317. TSinshKernel(Kernel).Coeff := 20 / GbrParameter.Position;
  318. end;
  319. procedure TFrmResamplersExample.CurveImagePaintStage(Sender: TObject; Buffer: TBitmap32;
  320. StageNum: Cardinal);
  321. var
  322. Kernel: TCustomKernel;
  323. I, BufWidth, BufHeight: Integer;
  324. W, X, Y, Scale: Single;
  325. R: TRect;
  326. const
  327. YScale : Single = 1 / 2.2;
  328. begin
  329. if Src.Resampler is TKernelResampler then
  330. begin
  331. Kernel := TKernelResampler(Src.Resampler).Kernel;
  332. SetKernelParameter(Kernel);
  333. W := Kernel.GetWidth;
  334. R := CurveImage.GetViewPortRect;
  335. BufWidth := R.Right - R.Left;
  336. BufHeight := R.Bottom - R.Top;
  337. Buffer.Clear(clBlack32);
  338. Buffer.PenColor := clWhite32;
  339. Buffer.MoveToF(0, BufHeight * 0.5);
  340. Scale := 2 * W / BufWidth;
  341. for I := Round(-W) * 2 to Round(W) * 2 do
  342. begin
  343. X := 0.5 * (I / Scale + BufWidth);
  344. Buffer.LineFS(X, 0, X, BufHeight - 1, clGray32);
  345. end;
  346. for I := -2 to 2 do
  347. begin
  348. Y := 0.5 * BufHeight * (I * YScale + 1);
  349. Buffer.LineFS(0, Y, BufWidth - 1, Y, clGray32);
  350. end;
  351. for I := 0 to BufWidth - 1 do
  352. begin
  353. Y := (1.1 - Kernel.Filter(I * Scale - W)) * BufHeight * YScale;
  354. Buffer.LineToFS(I, Y);
  355. end;
  356. end;
  357. end;
  358. procedure TFrmResamplersExample.ResamplingPaintBoxResize(Sender: TObject);
  359. var
  360. I, W, H, C: Integer;
  361. Tmp: TBitmap32;
  362. R: TRect;
  363. ScaleRatioX, ScaleRatioY: Single;
  364. CurrentBitmaps: array [0..1] of TBitmap32;
  365. begin
  366. if not TabResampling.Visible then Exit;
  367. Tmp := TBitmap32.Create;
  368. try
  369. CurrentBitmaps[0] := Tmp;
  370. CurrentBitmaps[1] := ResamplingSrc;
  371. for I := 0 to 1 do
  372. begin
  373. TCustomResamplerClass(ResamplerList[ResamplerClassNamesList.ItemIndex]).Create(CurrentBitmaps[I]);
  374. if CurrentBitmaps[I].Resampler is TKernelResampler then
  375. with CurrentBitmaps[I].Resampler as TKernelResampler do
  376. begin
  377. Kernel := TCustomKernelClass(KernelList[KernelClassNamesList.ItemIndex]).Create;
  378. SetKernelParameter(Kernel);
  379. KernelMode := TKernelMode(KernelModeList.ItemIndex);
  380. TableSize := GbrTableSize.Position;
  381. end;
  382. end;
  383. ResamplingPaintBox.Buffer.BeginUpdate;
  384. with ResamplingPaintBox.Buffer do
  385. begin
  386. // shrink to Tmp bitmap
  387. ScaleRatioX := Width / (3 * ResamplingSrc.Width);
  388. ScaleRatioY := Height / (4 * ResamplingSrc.Height);
  389. Tmp.SetSize(Round(ResamplingSrc.Width * ScaleRatioX),
  390. Round(ResamplingSrc.Height * ScaleRatioY));
  391. Tmp.Draw(Tmp.BoundsRect, ResamplingSrc.BoundsRect, ResamplingSrc);
  392. // draw Tmp to paint box
  393. C := Width div 2;
  394. ResamplingPaintBox.Buffer.Draw(C - Tmp.Width div 2, 10, Tmp);
  395. // expand Tmp bitmap and draw to paint box
  396. ScaleRatioX := (Width - 20) / ResamplingSrc.Width;
  397. ScaleRatioY := (((Height - 20) * 0.25) * 3) / (ResamplingSrc.Height);
  398. W := Round(ResamplingSrc.Width * ScaleRatioX);
  399. H := Round(ResamplingSrc.Height * ScaleRatioY);
  400. R := Rect(C - W div 2, Tmp.Height + 20, C + W div 2, Tmp.Height + 5 + H);
  401. ResamplingPaintBox.Buffer.Draw(R, Tmp.BoundsRect, Tmp); // resampling!
  402. end;
  403. ResamplingPaintBox.Buffer.EndUpdate;
  404. finally
  405. Tmp.Free;
  406. end;
  407. ResamplingPaintBox.Repaint;
  408. end;
  409. end.