mainunit.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. {
  2. Vampyre Imaging Library Demo
  3. LCL Imager (ObjectPascal, high level/component sets/canvas, Win32/Linux)
  4. tested in Lazarus 0.9.18
  5. written by Marek Mauder
  6. Simple image manipulator program which shows usage of Imaging VCL/CLX/LCL
  7. classes (TImagingGraphic and its descendants) to display images on form.
  8. It also uses high level image classes and some low level functions.
  9. Demo uses TMultiImage class to store images (loaded from one file - MNG, DDS)
  10. which can be modified by user. After each modification image
  11. is assigned to TImagingBitmap class which provides visualization
  12. on the app form (using standard TImage component). Demo also uses new
  13. TImagingCanvas class to do some effects.
  14. In File menu you can open new image and save the current one. Items in
  15. View menu provide information about the current image and controls
  16. how it is displayed. You can also select next and previous subimage if loaded file
  17. contains more than one image. Format menu allows you to convert image
  18. to different image data formats supported by Imaging. Manipulate
  19. menu allows you to enlarge/shrink/flip/mirror/swap channels/other
  20. of the current image. Effects menu allows you to apply various effects to the
  21. image (provided by TImagingCanvas).
  22. }
  23. unit MainUnit;
  24. {$I ImagingOptions.inc}
  25. interface
  26. uses
  27. Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
  28. Menus, ExtCtrls, ExtDlgs, DemoUtils, AboutUnit, ActnList,
  29. ImagingTypes,
  30. Imaging,
  31. ImagingClasses,
  32. ImagingComponents,
  33. ImagingCanvases,
  34. ImagingUtility;
  35. type
  36. { TMainForm }
  37. TMainForm = class(TForm)
  38. ActViewInfo: TAction;
  39. ActViewFitToWindow: TAction;
  40. ActViewRealSize: TAction;
  41. ActionList1: TActionList;
  42. Image: TImage;
  43. MainMenu: TMainMenu;
  44. MenuItem1: TMenuItem;
  45. MenuItem10: TMenuItem;
  46. MenuItem11: TMenuItem;
  47. MenuItem12: TMenuItem;
  48. MenuItem13: TMenuItem;
  49. MenuItem14: TMenuItem;
  50. MenuItem15: TMenuItem;
  51. MenuItem16: TMenuItem;
  52. MenuItem17: TMenuItem;
  53. FormatItem: TMenuItem;
  54. MenuItem18: TMenuItem;
  55. MenuItem19: TMenuItem;
  56. MenuItem2: TMenuItem;
  57. MenuItem20: TMenuItem;
  58. MenuItem21: TMenuItem;
  59. MenuItem22: TMenuItem;
  60. MenuItem23: TMenuItem;
  61. MenuItem24: TMenuItem;
  62. MenuItem25: TMenuItem;
  63. MenuItem26: TMenuItem;
  64. MenuItem27: TMenuItem;
  65. MenuItem28: TMenuItem;
  66. MenuItem29: TMenuItem;
  67. MenuItem3: TMenuItem;
  68. MenuItem30: TMenuItem;
  69. MenuItem31: TMenuItem;
  70. MenuItem32: TMenuItem;
  71. MenuItem33: TMenuItem;
  72. MenuItem36: TMenuItem;
  73. MenuItem37: TMenuItem;
  74. MenuItem38: TMenuItem;
  75. MenuItem39: TMenuItem;
  76. MenuItem40: TMenuItem;
  77. MenuItem41: TMenuItem;
  78. MenuItem42: TMenuItem;
  79. MenuItem43: TMenuItem;
  80. MenuItem44: TMenuItem;
  81. MenuItem45: TMenuItem;
  82. MenuItem46: TMenuItem;
  83. MenuItem47: TMenuItem;
  84. MenuItem48: TMenuItem;
  85. MenuItem49: TMenuItem;
  86. MenuItem50: TMenuItem;
  87. MenuItem51: TMenuItem;
  88. MenuItem52: TMenuItem;
  89. MenuItem53: TMenuItem;
  90. MenuItem54: TMenuItem;
  91. MenuItemActSubImage: TMenuItem;
  92. MenuItem34: TMenuItem;
  93. MenuItem35: TMenuItem;
  94. MenuItem4: TMenuItem;
  95. MenuItem5: TMenuItem;
  96. MenuItem6: TMenuItem;
  97. MenuItem7: TMenuItem;
  98. MenuItem8: TMenuItem;
  99. MenuItem9: TMenuItem;
  100. OpenD: TOpenPictureDialog;
  101. SaveD: TSavePictureDialog;
  102. procedure ActViewFitToWindowExecute(Sender: TObject);
  103. procedure ActViewInfoExecute(Sender: TObject);
  104. procedure ActViewRealSizeExecute(Sender: TObject);
  105. procedure FormCreate(Sender: TObject);
  106. procedure FormDestroy(Sender: TObject);
  107. procedure ImageClick(Sender: TObject);
  108. procedure MenuItem10Click(Sender: TObject);
  109. procedure MenuItem12Click(Sender: TObject);
  110. procedure MenuItem13Click(Sender: TObject);
  111. procedure MenuItem14Click(Sender: TObject);
  112. procedure MenuItem15Click(Sender: TObject);
  113. procedure MenuItem18Click(Sender: TObject);
  114. procedure MenuItem19Click(Sender: TObject);
  115. procedure MenuItem20Click(Sender: TObject);
  116. procedure MenuItem23Click(Sender: TObject);
  117. procedure MenuItem24Click(Sender: TObject);
  118. procedure MenuItem26Click(Sender: TObject);
  119. procedure MenuItem27Click(Sender: TObject);
  120. procedure MenuItem28Click(Sender: TObject);
  121. procedure MenuItem29Click(Sender: TObject);
  122. procedure MenuItem2Click(Sender: TObject);
  123. procedure MenuItem30Click(Sender: TObject);
  124. procedure MenuItem31Click(Sender: TObject);
  125. procedure MenuItem33Click(Sender: TObject);
  126. procedure MenuItem34Click(Sender: TObject);
  127. procedure MenuItem35Click(Sender: TObject);
  128. procedure MenuItem37Click(Sender: TObject);
  129. procedure MenuItem38Click(Sender: TObject);
  130. procedure MenuItem39Click(Sender: TObject);
  131. procedure MenuItem3Click(Sender: TObject);
  132. procedure MenuItem40Click(Sender: TObject);
  133. procedure MenuItem41Click(Sender: TObject);
  134. procedure MenuItem42Click(Sender: TObject);
  135. procedure MenuItem43Click(Sender: TObject);
  136. procedure MenuItem44Click(Sender: TObject);
  137. procedure MenuItem45Click(Sender: TObject);
  138. procedure MenuItem46Click(Sender: TObject);
  139. procedure MenuItem47Click(Sender: TObject);
  140. procedure MenuItem48Click(Sender: TObject);
  141. procedure MenuItem4Click(Sender: TObject);
  142. procedure MenuItem50Click(Sender: TObject);
  143. procedure MenuItem51Click(Sender: TObject);
  144. procedure MenuItem53Click(Sender: TObject);
  145. procedure MenuItem54Click(Sender: TObject);
  146. procedure MenuItem5Click(Sender: TObject);
  147. procedure MenuItem7Click(Sender: TObject);
  148. procedure FormatChangeClick(Sender: TObject);
  149. private
  150. FBitmap: TImagingBitmap;
  151. FImage: TMultiImage;
  152. FImageCanvas: TImagingCanvas;
  153. FFileName: string;
  154. procedure OpenFile(const FileName: string);
  155. procedure SaveFile(const FileName: string);
  156. procedure SelectSubimage(Index: LongInt);
  157. procedure UpdateView;
  158. function CheckCanvasFormat: Boolean;
  159. procedure ApplyConvolution(Kernel: Pointer; Size: LongInt; NeedsBlur: Boolean);
  160. public
  161. end;
  162. const
  163. SWindowTitle = 'LCL Imager - Vampyre Imaging Library %s Demo';
  164. var
  165. MainForm: TMainForm;
  166. implementation
  167. { TMainForm }
  168. procedure TMainForm.MenuItem10Click(Sender: TObject);
  169. begin
  170. AboutForm.ShowModal;
  171. end;
  172. procedure TMainForm.MenuItem12Click(Sender: TObject);
  173. begin
  174. SwapChannels(FImage.ImageDataPointer^, ChannelRed, ChannelBlue);
  175. UpdateView;
  176. end;
  177. procedure TMainForm.MenuItem13Click(Sender: TObject);
  178. begin
  179. SwapChannels(FImage.ImageDataPointer^, ChannelRed, ChannelGreen);
  180. UpdateView;
  181. end;
  182. procedure TMainForm.MenuItem14Click(Sender: TObject);
  183. begin
  184. SwapChannels(FImage.ImageDataPointer^, ChannelGreen, ChannelBlue);
  185. UpdateView;
  186. end;
  187. procedure TMainForm.MenuItem15Click(Sender: TObject);
  188. begin
  189. ReduceColors(FImage.ImageDataPointer^, 1024);
  190. UpdateView;
  191. end;
  192. procedure TMainForm.MenuItem18Click(Sender: TObject);
  193. begin
  194. ReduceColors(FImage.ImageDataPointer^, 256);
  195. UpdateView;
  196. end;
  197. procedure TMainForm.MenuItem19Click(Sender: TObject);
  198. begin
  199. ReduceColors(FImage.ImageDataPointer^, 64);
  200. UpdateView;
  201. end;
  202. procedure TMainForm.MenuItem20Click(Sender: TObject);
  203. begin
  204. ReduceColors(FImage.ImageDataPointer^, 16);
  205. UpdateView;
  206. end;
  207. procedure TMainForm.MenuItem23Click(Sender: TObject);
  208. begin
  209. FImage.Rotate(-90);
  210. UpdateView;
  211. end;
  212. procedure TMainForm.MenuItem24Click(Sender: TObject);
  213. begin
  214. FImage.Rotate(90);
  215. UpdateView;
  216. end;
  217. procedure TMainForm.MenuItem26Click(Sender: TObject);
  218. begin
  219. FImage.Resize(FImage.Width div 2, FImage.Height div 2, rfNearest);
  220. UpdateView;
  221. end;
  222. procedure TMainForm.MenuItem27Click(Sender: TObject);
  223. begin
  224. FImage.Resize(FImage.Width div 2, FImage.Height div 2, rfBilinear);
  225. UpdateView;
  226. end;
  227. procedure TMainForm.MenuItem28Click(Sender: TObject);
  228. begin
  229. FImage.Resize(FImage.Width div 2, FImage.Height div 2, rfBicubic);
  230. UpdateView;
  231. end;
  232. procedure TMainForm.MenuItem29Click(Sender: TObject);
  233. begin
  234. FImage.Resize(FImage.Width * 2, FImage.Height * 2, rfNearest);
  235. UpdateView;
  236. end;
  237. procedure TMainForm.MenuItem2Click(Sender: TObject);
  238. begin
  239. FImage.Flip;;
  240. UpdateView;
  241. end;
  242. procedure TMainForm.MenuItem30Click(Sender: TObject);
  243. begin
  244. FImage.Resize(FImage.Width * 2, FImage.Height * 2, rfBilinear);
  245. UpdateView;
  246. end;
  247. procedure TMainForm.MenuItem31Click(Sender: TObject);
  248. begin
  249. FImage.Resize(FImage.Width * 2, FImage.Height * 2, rfBicubic);
  250. UpdateView;
  251. end;
  252. procedure TMainForm.MenuItem33Click(Sender: TObject);
  253. begin
  254. ReduceColors(FImage.ImageDataPointer^, 2);
  255. UpdateView;
  256. end;
  257. procedure TMainForm.MenuItem34Click(Sender: TObject);
  258. begin
  259. SelectSubimage(FImage.ActiveImage + 1);
  260. end;
  261. procedure TMainForm.MenuItem35Click(Sender: TObject);
  262. begin
  263. SelectSubimage(FImage.ActiveImage - 1);
  264. end;
  265. function TMainForm.CheckCanvasFormat: Boolean;
  266. begin
  267. Result := FImage.Format in FImageCanvas.GetSupportedFormats;
  268. if not Result then
  269. MessageDlg('Image is in format that is not supported by TImagingCanvas.', mtError, [mbOK], 0);
  270. end;
  271. procedure TMainForm.ApplyConvolution(Kernel: Pointer; Size: LongInt; NeedsBlur: Boolean);
  272. begin
  273. if CheckCanvasFormat then
  274. begin
  275. FImageCanvas.CreateForImage(FImage);
  276. if NeedsBlur then
  277. FImageCanvas.ApplyConvolution3x3(FilterGaussian3x3);
  278. if Size = 3 then
  279. FImageCanvas.ApplyConvolution3x3(TConvolutionFilter3x3(Kernel^))
  280. else
  281. FImageCanvas.ApplyConvolution5x5(TConvolutionFilter5x5(Kernel^));
  282. UpdateView;
  283. end;
  284. end;
  285. procedure TMainForm.MenuItem37Click(Sender: TObject);
  286. begin
  287. ApplyConvolution(@FilterGaussian3x3, 3, False);
  288. end;
  289. procedure TMainForm.MenuItem38Click(Sender: TObject);
  290. begin
  291. ApplyConvolution(@FilterGaussian5x5, 5, False);
  292. end;
  293. procedure TMainForm.MenuItem39Click(Sender: TObject);
  294. begin
  295. ApplyConvolution(@FilterSharpen3x3, 3, False);
  296. end;
  297. procedure TMainForm.FormCreate(Sender: TObject);
  298. var
  299. Item: TMenuItem;
  300. Fmt: TImageFormat;
  301. Info: TImageFormatInfo;
  302. begin
  303. Caption := Format(SWindowTitle, [Imaging.GetVersionStr]);
  304. { Source image and Image's graphic are created and
  305. default image is opened.}
  306. FImage := TMultiImage.Create;
  307. FBitmap := TImagingBitmap.Create;
  308. Image.Picture.Graphic := FBitmap;
  309. FImageCanvas := TImagingCanvas.Create;
  310. { This builds Format submenu containing all possible
  311. image data formats (it dos not start at Low(TImageFormat)
  312. because there are some helper formats). Format for each item
  313. is stored in its Tag for later use in OnClick event.}
  314. for Fmt := ifIndex8 to High(TImageFormat) do
  315. begin
  316. GetImageFormatInfo(Fmt, Info);
  317. if Info.Name <> '' then
  318. begin
  319. Item := TMenuItem.Create(MainMenu);
  320. Item.Caption := Info.Name;
  321. Item.Tag := Ord(Fmt);
  322. Item.OnClick := FormatChangeClick;
  323. FormatItem.Add(Item);
  324. end;
  325. end;
  326. if (ParamCount > 0) and FileExists(ParamStr(1)) then
  327. OpenFile(ParamStr(1))
  328. else
  329. OpenFile(GetDataDir + PathDelim + 'Tigers.jpg');
  330. end;
  331. procedure TMainForm.FormatChangeClick(Sender: TObject);
  332. begin
  333. with Sender as TMenuItem do
  334. begin
  335. FImage.Format := TImageFormat(Tag);
  336. UpdateView;
  337. end;
  338. end;
  339. procedure TMainForm.ActViewRealSizeExecute(Sender: TObject);
  340. begin
  341. ActViewRealSize.Checked := not ActViewRealSize.Checked;
  342. ActViewFitToWindow.Checked := not ActViewFitToWindow.Checked;
  343. if ActViewRealSize.Checked then
  344. begin
  345. Image.Proportional := False;
  346. Image.Stretch := False;
  347. Image.AutoSize := True;
  348. end;
  349. end;
  350. procedure TMainForm.ActViewFitToWindowExecute(Sender: TObject);
  351. begin
  352. ActViewFitToWindow.Checked := not ActViewFitToWindow.Checked;
  353. ActViewRealSize.Checked := not ActViewRealSize.Checked;
  354. if ActViewFitToWindow.Checked then
  355. begin
  356. Image.Proportional := True;
  357. Image.AutoSize := False;
  358. Image.Stretch := True;
  359. end;
  360. end;
  361. procedure TMainForm.ActViewInfoExecute(Sender: TObject);
  362. begin
  363. MessageDlg('Image Info: ' + ImageToStr(FImage.ImageDataPointer^), mtInformation, [mbOK], 0);
  364. end;
  365. procedure TMainForm.FormDestroy(Sender: TObject);
  366. begin
  367. FImageCanvas.Free;
  368. FBitmap.Free;
  369. FImage.Free;
  370. end;
  371. procedure TMainForm.ImageClick(Sender: TObject);
  372. begin
  373. ActViewInfo.Execute;
  374. end;
  375. procedure TMainForm.MenuItem3Click(Sender: TObject);
  376. begin
  377. OpenD.Filter := GetImageFileFormatsFilter(True);
  378. if OpenD.Execute then
  379. OpenFile(OpenD.FileName);
  380. end;
  381. procedure TMainForm.MenuItem40Click(Sender: TObject);
  382. begin
  383. ApplyConvolution(@FilterSharpen5x5, 5, False);
  384. end;
  385. procedure TMainForm.MenuItem41Click(Sender: TObject);
  386. begin
  387. ApplyConvolution(@FilterLaplace5x5, 5, True);
  388. end;
  389. procedure TMainForm.MenuItem42Click(Sender: TObject);
  390. begin
  391. ApplyConvolution(@FilterSobelHorz3x3, 3, True);
  392. end;
  393. procedure TMainForm.MenuItem43Click(Sender: TObject);
  394. begin
  395. ApplyConvolution(@FilterSobelVert3x3, 3, True);
  396. end;
  397. procedure TMainForm.MenuItem44Click(Sender: TObject);
  398. begin
  399. OpenFile(FFileName);
  400. end;
  401. procedure TMainForm.MenuItem45Click(Sender: TObject);
  402. begin
  403. ApplyConvolution(@FilterGlow5x5, 5, False);
  404. end;
  405. procedure TMainForm.MenuItem46Click(Sender: TObject);
  406. begin
  407. ApplyConvolution(@FilterEmboss3x3, 3, True);
  408. end;
  409. procedure TMainForm.MenuItem47Click(Sender: TObject);
  410. begin
  411. ApplyConvolution(@FilterNegative3x3, 3, False);
  412. end;
  413. procedure TMainForm.MenuItem48Click(Sender: TObject);
  414. begin
  415. ApplyConvolution(@FilterEdgeEnhance3x3, 3, False);
  416. end;
  417. procedure TMainForm.MenuItem4Click(Sender: TObject);
  418. begin
  419. FImage.Mirror;
  420. UpdateView;
  421. end;
  422. procedure TMainForm.MenuItem50Click(Sender: TObject);
  423. begin
  424. ApplyConvolution(@FilterPrewittHorz3x3, 3, True);
  425. end;
  426. procedure TMainForm.MenuItem51Click(Sender: TObject);
  427. begin
  428. ApplyConvolution(@FilterKirshHorz3x3, 3, True);
  429. end;
  430. procedure TMainForm.MenuItem53Click(Sender: TObject);
  431. begin
  432. ApplyConvolution(@FilterPrewittVert3x3, 3, True);
  433. end;
  434. procedure TMainForm.MenuItem54Click(Sender: TObject);
  435. begin
  436. ApplyConvolution(@FilterKirshVert3x3, 3, True);
  437. end;
  438. procedure TMainForm.MenuItem5Click(Sender: TObject);
  439. begin
  440. SaveD.Filter := GetImageFileFormatsFilter(False);
  441. SaveD.FileName := ChangeFileExt(ExtractFileName(FFileName), '');
  442. SaveD.FilterIndex := GetFileNameFilterIndex(FFileName, False);
  443. if SaveD.Execute then
  444. begin
  445. FFileName := ChangeFileExt(SaveD.FileName, '.' + GetFilterIndexExtension(SaveD.FilterIndex, False));
  446. SaveFile(FFileName);
  447. end;
  448. end;
  449. procedure TMainForm.MenuItem7Click(Sender: TObject);
  450. begin
  451. Close;
  452. end;
  453. procedure TMainForm.OpenFile(const FileName: string);
  454. begin
  455. FFileName := FileName;
  456. try
  457. FImage.LoadMultiFromFile(FileName);
  458. except
  459. FImage.CreateFromParams(32, 32, ifA8R8G8B8, 1);
  460. MessageDlg('Error when loading file: ' + FileName, mtError, [mbOK], 0);
  461. end;
  462. SelectSubimage(0);
  463. end;
  464. procedure TMainForm.SaveFile(const FileName: string);
  465. begin
  466. try
  467. FImage.SaveMultiToFile(FileName);
  468. except
  469. MessageDlg('Error when saving file: ' + FileName, mtError, [mbOK], 0);
  470. end;
  471. end;
  472. procedure TMainForm.SelectSubimage(Index: LongInt);
  473. begin
  474. FImage.ActiveImage := Index;
  475. MenuItemActSubImage.Caption := Format('Active Subimage: %d/%d', [FImage.ActiveImage + 1, FImage.ImageCount]);
  476. UpdateView;
  477. end;
  478. procedure TMainForm.UpdateView;
  479. begin
  480. Image.Picture.Graphic.Assign(FImage);
  481. end;
  482. initialization
  483. {$I mainunit.lrs}
  484. {
  485. File Notes:
  486. -- TODOS ----------------------------------------------------
  487. - add more canvas stuff when it will be avaiable
  488. -- 0.23 Changes/Bug Fixes -----------------------------------
  489. - Catches exceptions during file load/save.
  490. -- 0.21 Changes/Bug Fixes -----------------------------------
  491. - Save As... now saves all images levels instead of just current one.
  492. - Added XP controls manifest to resource file.
  493. - Added new filters to Effects menu.
  494. -- 0.19 Changes/Bug Fixes -----------------------------------
  495. - you can now open image in Imager from shell by passing
  496. path to image as parameter: 'LCLImager /home/myimage.jpg'
  497. - added Reload from File menu to reload image from disk
  498. (poor man's Undo)
  499. - added Effects menu with some convolution filters
  500. - added support for displaying of multi images
  501. -- 0.17 Changes/Bug Fixes -----------------------------------
  502. - added Nearest, Bilinear, and Bicubic filter options to
  503. Resize To 50/200% menu items
  504. - better handling of file exts when using save dialog
  505. - added rotations to Manipulate menu
  506. - now works well in Linux too
  507. -- 0.15 Changes/Bug Fixes -----------------------------------
  508. - created
  509. }
  510. end.