MainUnit.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  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 Nested Sampling Example
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Mattias Andersson <[email protected]>
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2005
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. * Michael Hansen <[email protected]>
  32. * Andre Beckedorf <[email protected]>
  33. *
  34. * ***** END LICENSE BLOCK ***** *)
  35. interface
  36. {$I GR32.inc}
  37. uses
  38. {$IFNDEF FPC} Windows, {$ELSE} LResources, {$ENDIF}
  39. SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,
  40. TypInfo, SimplePropEdit, ComCtrls, Menus, ToolWin, ImgList, Buttons, ExtDlgs,
  41. GR32, GR32_Blend, GR32_Image, GR32_Math, GR32_Rasterizers, GR32_Resamplers,
  42. GR32_Transforms, GR32_Containers, GR32_ExtImage, System.ImageList;
  43. type
  44. TMainForm = class(TForm)
  45. btnRasterize: TSpeedButton;
  46. chkClear: TMenuItem;
  47. chkReset: TMenuItem;
  48. DisabledImages: TImageList;
  49. EnabledImages: TImageList;
  50. HotImages: TImageList;
  51. ImgView: TImgView32;
  52. LeftPanel: TPanel;
  53. lvSamplers: TListView;
  54. MainMenu: TMainMenu;
  55. miAdaptiveSuperSampler: TMenuItem;
  56. miAntialiasing: TMenuItem;
  57. miBloat: TMenuItem;
  58. miContour: TMenuItem;
  59. miContracter: TMenuItem;
  60. miConvolver: TMenuItem;
  61. miDilater: TMenuItem;
  62. miDisturbance: TMenuItem;
  63. miDraft: TMenuItem;
  64. miEdit: TMenuItem;
  65. miEroder: TMenuItem;
  66. miExit: TMenuItem;
  67. miExpander: TMenuItem;
  68. miFile: TMenuItem;
  69. miFisheye: TMenuItem;
  70. miJitteredPattern: TMenuItem;
  71. miKernel: TMenuItem;
  72. miLanczos: TMenuItem;
  73. miLinear: TMenuItem;
  74. miNearest: TMenuItem;
  75. miOpen: TMenuItem;
  76. miOptions: TMenuItem;
  77. miProgressive: TMenuItem;
  78. miProjective: TMenuItem;
  79. miRasterizer: TMenuItem;
  80. miRegular: TMenuItem;
  81. miResampler: TMenuItem;
  82. miRGBNoise: TMenuItem;
  83. miRotation: TMenuItem;
  84. miSaveImage: TMenuItem;
  85. miScale: TMenuItem;
  86. miSelectiveConvolver: TMenuItem;
  87. miSinsh: TMenuItem;
  88. miSkew: TMenuItem;
  89. miSpline: TMenuItem;
  90. miSupersampler: TMenuItem;
  91. miSwizzling: TMenuItem;
  92. miTesseral: TMenuItem;
  93. miTransformer: TMenuItem;
  94. miTranslation: TMenuItem;
  95. miTwirl: TMenuItem;
  96. N1: TMenuItem;
  97. N2: TMenuItem;
  98. N4: TMenuItem;
  99. N5: TMenuItem;
  100. N6: TMenuItem;
  101. N7: TMenuItem;
  102. NewItemMenu: TPopupMenu;
  103. OpenPictureDialog: TOpenPictureDialog;
  104. Panel1: TPanel;
  105. SavePictureDialog: TSavePictureDialog;
  106. Splitter1: TSplitter;
  107. stObjectInspector: TStaticText;
  108. stRasterizer: TStaticText;
  109. stSamplerManager: TStaticText;
  110. tbCopy: TToolButton;
  111. tbCut: TToolButton;
  112. tbDelete: TToolButton;
  113. tbDown: TToolButton;
  114. tbManager: TToolBar;
  115. tbNew: TToolButton;
  116. tbPaste: TToolButton;
  117. tbSplitter1: TToolButton;
  118. tbSplitter2: TToolButton;
  119. tbUp: TToolButton;
  120. procedure FormCreate(Sender: TObject);
  121. procedure FormDestroy(Sender: TObject);
  122. procedure AntialiasClick(Sender: TObject);
  123. procedure btnRasterizeClick(Sender: TObject);
  124. procedure Button2Click(Sender: TObject);
  125. procedure Button3Click(Sender: TObject);
  126. procedure Copy2Click(Sender: TObject);
  127. procedure Cut1Click(Sender: TObject);
  128. procedure KernelClick(Sender: TObject);
  129. procedure lvSamplersSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
  130. procedure miContourClick(Sender: TObject);
  131. procedure miEdit2Click(Sender: TObject);
  132. procedure miEditClick(Sender: TObject);
  133. procedure miExitClick(Sender: TObject);
  134. procedure miLinearClick(Sender: TObject);
  135. procedure miNearestClick(Sender: TObject);
  136. procedure miOpenClick(Sender: TObject);
  137. procedure miProgressiveClick(Sender: TObject);
  138. procedure miRegularClick(Sender: TObject);
  139. procedure miRGBNoiseClick(Sender: TObject);
  140. procedure miSaveImageClick(Sender: TObject);
  141. procedure miSwizzlingClick(Sender: TObject);
  142. procedure miTesseralClick(Sender: TObject);
  143. procedure Paste1Click(Sender: TObject);
  144. procedure SelectKernel(Sender: TObject);
  145. procedure tbDeleteClick(Sender: TObject);
  146. procedure tbUpDownClick(Sender: TObject);
  147. procedure TransformationClick(Sender: TObject);
  148. private
  149. procedure SetSourceResampler(const Value: TCustomResampler);
  150. function GetSourceResampler: TCustomResampler;
  151. procedure UpdateTransformations;
  152. function NewInstanceName(Sampler: TNestedSampler): string;
  153. public
  154. Source: TBitmap32;
  155. Source2: TBitmap32;
  156. Rasterizer: TRasterizer;
  157. Samplers: TList;
  158. PropertyEditor: TSimplePropertyEditor;
  159. RenderThread: TRenderThread;
  160. ClearBitmap: Boolean;
  161. IsRasterizing: Boolean;
  162. ClipBoardItem: TNestedSampler;
  163. ObjectName: string;
  164. property SourceResampler: TCustomResampler read GetSourceResampler write SetSourceResampler;
  165. procedure ThreadTerminated(Sender: TObject);
  166. procedure SetResampler(ResamplerClass: TCustomResamplerClass);
  167. procedure StopThread;
  168. function LastSampler: TCustomSampler;
  169. function SelectedSampler: TNestedSampler;
  170. function SelectedIndex: Integer;
  171. function ValidSelection: Boolean;
  172. procedure AddSampler(Sampler: TNestedSampler);
  173. procedure InsertSampler(Index: Integer; ObjName: string; Sampler: TNestedSampler);
  174. procedure DeleteSampler(Index: Integer; FreeItem: Boolean = True);
  175. end;
  176. { Simple implementation of a nested sampler }
  177. TNoiseSampler = class(TNestedSampler)
  178. public
  179. FRed, FGreen, FBlue: Integer;
  180. FRedNoise, FGreenNoise, FBlueNoise: Integer;
  181. function GetSampleFixed(X, Y: TFixed): TColor32; override;
  182. published
  183. property Red: Integer read FRed write FRed;
  184. property Green: Integer read FGreen write FGreen;
  185. property Blue: Integer read FBlue write FBlue;
  186. property RedNoise: Integer read FRedNoise write FRedNoise;
  187. property GreenNoise: Integer read FGreenNoise write FGreenNoise;
  188. property BlueNoise: Integer read FBlueNoise write FBlueNoise;
  189. end;
  190. var
  191. MainForm: TMainForm;
  192. implementation
  193. {$IFDEF FPC}
  194. {$R *.lfm}
  195. {$ELSE}
  196. {$R *.dfm}
  197. {$ENDIF}
  198. uses
  199. Types, Math,
  200. {$IFDEF DARWIN}
  201. MacOSAll,
  202. {$ENDIF}
  203. {$IFNDEF FPC}
  204. JPEG,
  205. {$ELSE}
  206. LazJPG,
  207. {$ENDIF}
  208. GR32_OrdinalMaps, GR32_LowLevel;
  209. procedure SetupToolBar(ToolBar: TToolBar);
  210. var
  211. I: Integer;
  212. begin
  213. with ToolBar do
  214. begin
  215. ShowCaptions := False;
  216. for I := 0 to ButtonCount - 1 do
  217. with Buttons[I] do
  218. begin
  219. if MenuItem.Count > 0 then
  220. Style := tbsDropDown
  221. else if Caption = '|' then
  222. Style := tbsSeparator
  223. else
  224. Style := tbsButton;
  225. AutoSize := False;
  226. Width := 0;
  227. Height := 0;
  228. end;
  229. end;
  230. end;
  231. { TMainForm }
  232. procedure TMainForm.FormCreate(Sender: TObject);
  233. var
  234. ResStream: TResourceStream;
  235. JPEG: TJPEGImage;
  236. begin
  237. // load example image
  238. Source := TBitmap32.Create;
  239. JPEG := TJPEGImage.Create;
  240. try
  241. ResStream := TResourceStream.Create(HInstance, 'Stoneweed', RT_RCDATA);
  242. try
  243. JPEG.LoadFromStream(ResStream);
  244. finally
  245. ResStream.Free;
  246. end;
  247. Source.Assign(JPEG);
  248. finally
  249. JPEG.Free;
  250. end;
  251. ImgView.Bitmap.SetSizeFrom(Source);
  252. Rasterizer := TRegularRasterizer.Create;
  253. TRegularRasterizer(Rasterizer).UpdateRowCount := 16;
  254. Rasterizer.Sampler := Source.Resampler;
  255. Samplers := TList.Create;
  256. PropertyEditor := TSimplePropertyEditor.Create(Self);
  257. PropertyEditor.Parent := LeftPanel;
  258. PropertyEditor.Align := alClient;
  259. with PropertyEditor do
  260. begin
  261. RegisterClassPropertyRange(TNoiseSampler, 'Red', -255, 255);
  262. RegisterClassPropertyRange(TNoiseSampler, 'Green', -255, 255);
  263. RegisterClassPropertyRange(TNoiseSampler, 'Blue', -255, 255);
  264. RegisterClassPropertyRange(TNoiseSampler, 'RedNoise', 0, 255);
  265. RegisterClassPropertyRange(TNoiseSampler, 'GreenNoise', 0, 255);
  266. RegisterClassPropertyRange(TNoiseSampler, 'BlueNoise', 0, 255);
  267. RegisterClassPropertyRange(TSuperSampler, 'SamplingX', 1, 8);
  268. RegisterClassPropertyRange(TSuperSampler, 'SamplingY', 1, 8);
  269. RegisterClassPropertyRange(TAdaptiveSuperSampler, 'Level', 0, 8);
  270. RegisterClassPropertyRange(TAdaptiveSuperSampler, 'Tolerance', 0, 255);
  271. RegisterClassPropertyRange(TKernelSampler, 'CenterX', 0, 4);
  272. RegisterClassPropertyRange(TKernelSampler, 'CenterY', 0, 4);
  273. RegisterClassPropertyRange(TSelectiveConvolver, 'Delta', 0, 255);
  274. RegisterClassPropertyRange(TTwirlTransformation, 'Twirl', 0, 0.1);
  275. RegisterClassPropertyRange(TBloatTransformation, 'BloatPower', 0, 1);
  276. RegisterClassPropertyRange(TWindowedSincKernel, 'Width', 0, 5);
  277. RegisterClassPropertyRange(TSinshKernel, 'Width', 0, 5);
  278. RegisterClassPropertyRange(TSinshKernel, 'Coeff', 0, 1);
  279. RegisterClassPropertyRange(TCubicKernel, 'Coeff', -1.5, 1.5);
  280. end;
  281. btnRasterizeClick(nil);
  282. end;
  283. procedure TMainForm.FormDestroy(Sender: TObject);
  284. var
  285. I: Integer; C: TCustomSampler;
  286. begin
  287. for I := 0 to Samplers.Count - 1 do begin
  288. C := Samplers[I];
  289. if C is TTransformer then
  290. (C as TTransformer).Transformation.Free;
  291. C.Free;
  292. end;
  293. Samplers.Clear;
  294. Samplers.Free;
  295. FreeAndNil(RenderThread);
  296. FreeAndNil(Rasterizer);
  297. FreeAndNil(Source);
  298. end;
  299. procedure TMainForm.lvSamplersSelectItem(Sender: TObject; Item: TListItem;
  300. Selected: Boolean);
  301. begin
  302. if Selected and (Item.Index >= 0) and (Item.Index < Samplers.Count) then
  303. PropertyEditor.SelectObject(Item.Caption, Samplers[Item.Index]);
  304. end;
  305. procedure TMainForm.SetResampler(ResamplerClass: TCustomResamplerClass);
  306. begin
  307. end;
  308. procedure TMainForm.btnRasterizeClick(Sender: TObject);
  309. begin
  310. if IsRasterizing then
  311. begin
  312. StopThread;
  313. end
  314. else
  315. begin
  316. miFile.Enabled := False;
  317. miResampler.Enabled := False;
  318. miRasterizer.Enabled := False;
  319. tbManager.Enabled := False;
  320. btnRasterize.Caption := 'Stop Rasterization';
  321. with ImgView do
  322. begin
  323. StopThread;
  324. if Assigned(RenderThread) then RenderThread.Free;
  325. if chkReset.Checked then
  326. SourceResampler := Source.Resampler
  327. else
  328. begin
  329. Source2 := TBitmap32.Create;
  330. Source2.Assign(Bitmap);
  331. SourceResampler := Source2.Resampler;
  332. end;
  333. if chkClear.Checked then Bitmap.Clear;
  334. RenderThread := TRenderThread.Create(Rasterizer, Bitmap, Bitmap.BoundsRect, False);
  335. RenderThread.OnTerminate := ThreadTerminated;
  336. end;
  337. IsRasterizing := True;
  338. end;
  339. end;
  340. procedure TMainForm.Button2Click(Sender: TObject);
  341. begin
  342. PropertyEditor.SelectObject('Resampler', Source.Resampler);
  343. end;
  344. procedure TMainForm.Button3Click(Sender: TObject);
  345. begin
  346. PropertyEditor.SelectObject('Rasterizer', Rasterizer);
  347. end;
  348. procedure TMainForm.tbDeleteClick(Sender: TObject);
  349. begin
  350. if ValidSelection then
  351. DeleteSampler(SelectedIndex);
  352. end;
  353. procedure TMainForm.miOpenClick(Sender: TObject);
  354. begin
  355. if OpenPictureDialog.Execute then
  356. begin
  357. Source.LoadFromFile(OpenPictureDialog.FileName);
  358. UpdateTransformations;
  359. ImgView.Bitmap.SetSizeFrom(Source);
  360. btnRasterizeClick(nil);
  361. end;
  362. end;
  363. procedure TMainForm.miSaveImageClick(Sender: TObject);
  364. begin
  365. if SavePictureDialog.Execute then
  366. Source.SaveToFile(OpenPictureDialog.FileName);
  367. end;
  368. procedure TMainForm.miExitClick(Sender: TObject);
  369. begin
  370. Close;
  371. end;
  372. procedure TMainForm.miNearestClick(Sender: TObject);
  373. begin
  374. SourceResampler := TNearestResampler.Create(Source);
  375. end;
  376. procedure TMainForm.miLinearClick(Sender: TObject);
  377. begin
  378. SourceResampler := TLinearResampler.Create(Source);
  379. end;
  380. procedure TMainForm.SelectKernel(Sender: TObject);
  381. var
  382. R: TKernelResampler;
  383. const
  384. KERNELS: array[0..3] of TCustomKernelClass =
  385. (TCubicKernel, TSplineKernel, TLanczosKernel, TSinshKernel);
  386. begin
  387. R := TKernelResampler.Create(Source);
  388. R.Kernel := KERNELS[TComponent(Sender).Tag].Create;
  389. R.KernelMode := kmTableLinear;
  390. SourceResampler := R;
  391. end;
  392. procedure TMainForm.StopThread;
  393. begin
  394. if Assigned(RenderThread) then
  395. begin
  396. RenderThread.Terminate;
  397. RenderThread.WaitFor;
  398. end;
  399. end;
  400. function TMainForm.LastSampler: TCustomSampler;
  401. begin
  402. if Samplers.Count > 0 then
  403. Result := TCustomSampler(Samplers.Last)
  404. else
  405. Result := Source.Resampler;
  406. end;
  407. procedure TMainForm.miProgressiveClick(Sender: TObject);
  408. begin
  409. Rasterizer.Free;
  410. Rasterizer := TProgressiveRasterizer.Create;
  411. Rasterizer.Sampler := LastSampler;
  412. end;
  413. procedure TMainForm.miRegularClick(Sender: TObject);
  414. begin
  415. Rasterizer.Free;
  416. Rasterizer := TRegularRasterizer.Create;
  417. TRegularRasterizer(Rasterizer).UpdateRowCount := 16;
  418. Rasterizer.Sampler := LastSampler;
  419. end;
  420. procedure TMainForm.miSwizzlingClick(Sender: TObject);
  421. begin
  422. Rasterizer.Free;
  423. Rasterizer := TSwizzlingRasterizer.Create;
  424. Rasterizer.Sampler := LastSampler;
  425. end;
  426. procedure TMainForm.miTesseralClick(Sender: TObject);
  427. begin
  428. Rasterizer.Free;
  429. Rasterizer := TTesseralRasterizer.Create;
  430. Rasterizer.Sampler := LastSampler;
  431. end;
  432. procedure TMainForm.miEditClick(Sender: TObject);
  433. begin
  434. PropertyEditor.SelectObject('Resampler', Source.Resampler);
  435. end;
  436. procedure TMainForm.miEdit2Click(Sender: TObject);
  437. begin
  438. PropertyEditor.SelectObject('Rasterizer', Rasterizer);
  439. end;
  440. procedure TMainForm.ThreadTerminated(Sender: TObject);
  441. begin
  442. if Assigned(Source2) then FreeAndNil(Source2);
  443. tbManager.Enabled := True;
  444. miFile.Enabled := True;
  445. miResampler.Enabled := True;
  446. miRasterizer.Enabled := True;
  447. btnRasterize.Caption := 'Rasterize Image';
  448. IsRasterizing := False;
  449. end;
  450. procedure TMainForm.KernelClick(Sender: TObject);
  451. type
  452. TKernelSamplerClass = class of TKernelSampler;
  453. const
  454. Classes: array[0..5] of TKernelSamplerClass =
  455. (TConvolver, TDilater, TEroder, TExpander, TContracter, TSelectiveConvolver);
  456. var
  457. Index, I, J: Integer;
  458. S: TKernelSampler;
  459. begin
  460. Index := TComponent(Sender).Tag;
  461. S := Classes[Index].Create(LastSampler);
  462. S.CenterX := 2;
  463. S.CenterY := 2;
  464. S.Kernel.SetSize(5, 5);
  465. // initialize default kernels
  466. case Index of
  467. 0: // convolver
  468. begin
  469. S.Kernel[2, 2] := 5 * 256;
  470. S.Kernel[2, 1] := -256;
  471. S.Kernel[2, 3] := -256;
  472. S.Kernel[1, 2] := -256;
  473. S.Kernel[3, 2] := -256;
  474. end;
  475. 1, 2: // dilater, eroder
  476. for I := 0 to 4 do
  477. for J := 0 to 4 do
  478. S.Kernel[I, J] := Round(-128 + 128 * Sqrt(1/6*Max(6 - Sqr(I - 2) - Sqr(J - 2), 0)));
  479. 3, 4, 5: // expander, contracter
  480. for I := 0 to 4 do
  481. for J := 0 to 4 do
  482. S.Kernel[I, J] := Round(256 * Sqrt(1/6*Max(6 - Sqr(I - 2) - Sqr(J - 2), 0)));
  483. end;
  484. AddSampler(S);
  485. end;
  486. procedure TMainForm.TransformationClick(Sender: TObject);
  487. type
  488. TTransformationClass = class of TTransformation;
  489. const
  490. Classes: array[0..8] of TTransformationClass =
  491. (nil, nil, nil, nil, TProjectiveTransformation, TTwirlTransformation,
  492. TBloatTransformation, TDisturbanceTransformation, TFishEyeTransformation);
  493. var
  494. S: TTransformer;
  495. T: TTransformation;
  496. begin
  497. if Classes[TComponent(Sender).Tag] = nil then Exit;
  498. T := Classes[TComponent(Sender).Tag].Create;
  499. T.SrcRect := FloatRect(Source.BoundsRect);
  500. S := TTransformer.Create(LastSampler, T);
  501. AddSampler(S);
  502. end;
  503. procedure TMainForm.AntialiasClick(Sender: TObject);
  504. type
  505. TNestedSamplerClass = class of TNestedSampler;
  506. const
  507. Classes: array[0..2] of TNestedSamplerClass =
  508. (TSuperSampler, TAdaptiveSuperSampler, TPatternSampler);
  509. begin
  510. AddSampler(Classes[TComponent(Sender).Tag].Create(LastSampler));
  511. end;
  512. procedure TMainForm.miContourClick(Sender: TObject);
  513. begin
  514. Rasterizer.Free;
  515. Rasterizer := TContourRasterizer.Create;
  516. Rasterizer.Sampler := LastSampler;
  517. end;
  518. procedure TMainForm.SetSourceResampler(const Value: TCustomResampler);
  519. begin
  520. if Samplers.Count > 0 then
  521. TNestedSampler(Samplers[0]).Sampler := Value
  522. else
  523. Rasterizer.Sampler := Value;
  524. end;
  525. function TMainForm.GetSourceResampler: TCustomResampler;
  526. begin
  527. Result := Source.Resampler;
  528. end;
  529. function TMainForm.SelectedSampler: TNestedSampler;
  530. begin
  531. Result := nil;
  532. if Assigned(lvSamplers.Selected) then
  533. Result := TNestedSampler(lvSamplers.Selected.Data);
  534. end;
  535. function TMainForm.SelectedIndex: Integer;
  536. begin
  537. Result := -1;
  538. if Assigned(lvSamplers.Selected) then
  539. Result := lvSamplers.Selected.Index;
  540. end;
  541. function TMainForm.ValidSelection: Boolean;
  542. begin
  543. Result := Assigned(lvSamplers.Selected);
  544. end;
  545. procedure TMainForm.Copy2Click(Sender: TObject);
  546. begin
  547. if ValidSelection then
  548. begin
  549. ClipBoardItem := SelectedSampler;
  550. ObjectName := lvSamplers.Selected.Caption;
  551. end;
  552. end;
  553. procedure TMainForm.Cut1Click(Sender: TObject);
  554. begin
  555. if ValidSelection then
  556. begin
  557. ClipBoardItem := SelectedSampler;
  558. ObjectName := lvSamplers.Selected.Caption;
  559. DeleteSampler(SelectedIndex, False);
  560. end;
  561. end;
  562. procedure TMainForm.Paste1Click(Sender: TObject);
  563. begin
  564. if Assigned(ClipBoardItem) then
  565. if ValidSelection then
  566. InsertSampler(SelectedIndex, ObjectName, ClipBoardItem)
  567. else
  568. InsertSampler(MaxInt, ObjectName, ClipBoardItem);
  569. end;
  570. procedure TMainForm.tbUpDownClick(Sender: TObject);
  571. var
  572. Index: Integer;
  573. S: TNestedSampler;
  574. ObjName: string;
  575. begin
  576. if ValidSelection then
  577. begin
  578. Index := SelectedIndex;
  579. S := SelectedSampler;
  580. ObjName := lvSamplers.Selected.Caption;
  581. DeleteSampler(Index, False);
  582. InsertSampler(Index + TComponent(Sender).Tag, ObjName, S);
  583. end;
  584. end;
  585. procedure TMainForm.AddSampler(Sampler: TNestedSampler);
  586. var
  587. NewItem: TListItem;
  588. begin
  589. if Sampler is TPatternSampler then
  590. with Sampler as TPatternSampler do
  591. Pattern := CreateJitteredPattern(10, 10, 3, 3);
  592. Samplers.Add(Sampler);
  593. Rasterizer.Sampler := Sampler;
  594. NewItem := lvSamplers.Items.Add;
  595. NewItem.Caption := NewInstanceName(Sampler);
  596. NewItem.SubItems.Add(Sampler.ClassName);
  597. NewItem.Data := Sampler;
  598. end;
  599. procedure TMainForm.InsertSampler(Index: Integer; ObjName: string; Sampler: TNestedSampler);
  600. var
  601. NewItem: TListItem;
  602. begin
  603. Index := Constrain(Index, 0, lvSamplers.Items.Count);
  604. if Index = lvSamplers.Items.Count then
  605. begin
  606. Samplers.Add(Sampler);
  607. Sampler.Sampler := LastSampler;
  608. Rasterizer.Sampler := Sampler;
  609. end
  610. else if Index >= 0 then
  611. begin
  612. TNestedSampler(Samplers[Index]).Sampler := Sampler;
  613. if Index = 0 then
  614. Sampler.Sampler := Source.Resampler
  615. else
  616. Sampler.Sampler := Samplers[Index - 1];
  617. Samplers.Insert(Index, Sampler);
  618. end;
  619. NewItem := lvSamplers.Items.Insert(Index);
  620. NewItem.Caption := ObjName;
  621. NewItem.SubItems.Add(Sampler.ClassName);
  622. NewItem.Data := Sampler;
  623. lvSamplers.Selected := NewItem;
  624. lvSamplers.Selected.Focused := True;
  625. end;
  626. procedure TMainForm.DeleteSampler(Index: Integer; FreeItem: Boolean);
  627. var
  628. S: TNestedSampler;
  629. begin
  630. if Index >= 0 then
  631. begin
  632. S := Samplers[Index];
  633. if Index < Samplers.Count - 1 then
  634. TNestedSampler(Samplers[Index + 1]).Sampler := S.Sampler
  635. else
  636. Rasterizer.Sampler := S.Sampler;
  637. Samplers.Delete(Index);
  638. if FreeItem and (Samplers.IndexOf(S) = -1) then
  639. S.Free;
  640. lvSamplers.Selected.Delete;
  641. PropertyEditor.SelectObject('', nil);
  642. end;
  643. end;
  644. procedure TMainForm.miRGBNoiseClick(Sender: TObject);
  645. begin
  646. AddSampler(TNoiseSampler.Create(LastSampler));
  647. end;
  648. procedure TMainForm.UpdateTransformations;
  649. var
  650. I: Integer;
  651. SrcRect: TRect;
  652. begin
  653. SrcRect := Source.BoundsRect;
  654. for I := 0 to Samplers.Count - 1 do
  655. if TPersistent(Samplers[I]) is TTransformer then
  656. TTransformer(Samplers[I]).Transformation.SrcRect := FloatRect(SrcRect);
  657. end;
  658. { TNoiseSampler }
  659. function TNoiseSampler.GetSampleFixed(X, Y: TFixed): TColor32;
  660. begin
  661. Result := Sampler.GetSampleFixed(X, Y);
  662. with TColor32Entry(Result) do
  663. begin
  664. R := Constrain(R + FRed + Random(FRedNoise), 0, 255);
  665. G := Constrain(G + FGreen + Random(FGreenNoise), 0, 255);
  666. B := Constrain(B + FBlue + Random(FBlueNoise), 0, 255);
  667. end;
  668. end;
  669. function TMainForm.NewInstanceName(Sampler: TNestedSampler): string;
  670. var
  671. S: string;
  672. I: Integer;
  673. begin
  674. S := Sampler.ClassName;
  675. S := Copy(S, 2, Length(S) - 1);
  676. for I := 1 to MaxInt do
  677. begin
  678. Result := S + IntToStr(I);
  679. if lvSamplers.FindCaption(0, Result, False, True, False) = nil then
  680. Exit;
  681. end;
  682. end;
  683. end.