Main.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. {
  2. Vampyre Imaging Library Demo
  3. VCL Image Browser (ObjectPascal, high level/component sets/canvas, Win32)
  4. tested in Delphi 7/11/12
  5. written by Marek Mauder
  6. This simple viewer application shows usage of high level class interface
  7. to Imaging library and also drawing images onto standard VCL TCanvas.
  8. TImagingCanvas class is also used here.
  9. In the left part of the window is shell tree view component. Here you can
  10. select files located in your computer. If the selected file is in one of the
  11. supported formats (JPG, BMP, TGA, DDS, PNG, MNG, JNG) it is displayed in the viewer
  12. area and some information about the file is displayed in the info area.
  13. If image file contains subimages you can view them too. Select active subimage
  14. by clicking on buttons with arrows (Previous/Next).
  15. When supported file is selected in shell tree view it is loaded to
  16. TMultiImage and converted to ifA8R8G8B8
  17. data format. Active subimage is then drawn TPainBox component's
  18. client area using DisplayImage procedure (direct bit copy, no need to
  19. convert Imaging's data to TGraphic).
  20. You need ShellCtrls unit and its components installed in Delphi for this demo.
  21. In BDS 2006 you can find them in Demos\DelphiWin32\VCLWin32\ShellControls
  22. directory. In some other versions of Delphi it is installed by default during
  23. IDE installation.
  24. }
  25. unit Main;
  26. {$I ImagingOptions.inc}
  27. {$IF not Defined(COMPONENT_SET_VCL) or not Defined(DELPHI)}
  28. {$MESSAGE ERROR 'This program requires Delphi with VCL'}
  29. {$IFEND}
  30. interface
  31. uses
  32. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  33. Dialogs, ComCtrls, ShellCtrls, ExtCtrls, StdCtrls, Buttons, ExtDlgs,
  34. ImagingTypes,
  35. Imaging,
  36. ImagingClasses,
  37. ImagingComponents,
  38. ImagingCanvases,
  39. ImagingFormats,
  40. ImagingUtility;
  41. type
  42. TMainForm = class(TForm)
  43. LeftPanel: TPanel;
  44. RightPanel: TPanel;
  45. InfoPanel: TPanel;
  46. LabDataFormat: TLabel;
  47. LabFileFormat: TLabel;
  48. LabDim: TLabel;
  49. LabFileName: TLabel;
  50. Label3: TLabel;
  51. Label2: TLabel;
  52. Label1: TLabel;
  53. Lab1: TLabel;
  54. ViewPanel: TPanel;
  55. PaintBox: TPaintBox;
  56. Tree: TShellTreeView;
  57. Splitter1: TSplitter;
  58. Label4: TLabel;
  59. LabActImage: TLabel;
  60. StatusBar: TStatusBar;
  61. BtnPrev: TSpeedButton;
  62. BtnNext: TSpeedButton;
  63. BtnFirst: TSpeedButton;
  64. BtnLast: TSpeedButton;
  65. BtnSave: TButton;
  66. SaveDialog: TSavePictureDialog;
  67. CheckFilter: TCheckBox;
  68. procedure PaintBoxPaint(Sender: TObject);
  69. procedure FormCreate(Sender: TObject);
  70. procedure FormDestroy(Sender: TObject);
  71. procedure TreeChange(Sender: TObject; Node: TTreeNode);
  72. procedure BtnPrevClick(Sender: TObject);
  73. procedure BtnNextClick(Sender: TObject);
  74. procedure TreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  75. procedure BtnFirstClick(Sender: TObject);
  76. procedure BtnLastClick(Sender: TObject);
  77. procedure BtnSaveClick(Sender: TObject);
  78. procedure ViewPanelResize(Sender: TObject);
  79. procedure CheckFilterClick(Sender: TObject);
  80. private
  81. // Class that holds multiple images (loaded from MNG or DDS files for instance)
  82. FImage: ImagingClasses.TMultiImage;
  83. // Canvas for drawing on loaded images
  84. FImageCanvas: ImagingCanvases.TImagingCanvas;
  85. // Image background
  86. FBack: ImagingClasses.TSingleImage;
  87. // Canvas for background image
  88. FBackCanvas: ImagingCanvases.TImagingCanvas;
  89. FFileName: string;
  90. FLastTime: LongInt;
  91. FOriginalFormats: array of TImageFormat;
  92. FSupported: Boolean;
  93. public
  94. procedure SetSupported;
  95. procedure SetUnsupported;
  96. procedure LoadFile;
  97. procedure FillDefault;
  98. end;
  99. const
  100. FillColor = $FFA6FFFF;
  101. CheckersDensity = 8;
  102. SUnsupportedFormat = 'Selected item format not supported';
  103. var
  104. MainForm: TMainForm;
  105. implementation
  106. {$R *.dfm}
  107. {$IF CompilerVersion >= 15.0}
  108. uses
  109. XPMan;
  110. {$IFEND}
  111. procedure TMainForm.LoadFile;
  112. var
  113. I: LongInt;
  114. T: Int64;
  115. begin
  116. try
  117. // DetermineFileFormat reads file header and returns image
  118. // file format identifier (like 'jpg', 'tga') if file is valid,
  119. // otherwise empty string is returned
  120. if Imaging.DetermineFileFormat(FFileName) <> '' then
  121. try
  122. // Load all subimages in file
  123. T := ImagingUtility.GetTimeMicroseconds;
  124. FImage.LoadMultiFromFile(FFileName);
  125. if not FImage.AllImagesValid then
  126. begin
  127. SetUnsupported;
  128. Exit;
  129. end;
  130. FLastTime := (ImagingUtility.GetTimeMicroseconds - T) div 1000;
  131. StatusBar.SimpleText := Format('Last image loaded in: %.0n ms', [FLastTime * 1.0]);
  132. // Store original data formats for later use
  133. SetLength(FOriginalFormats, FImage.ImageCount);
  134. for I := 0 to FImage.ImageCount - 1 do
  135. begin
  136. FImage.ActiveImage := I;
  137. FOriginalFormats[I] := FImage.Format;
  138. // Convert image to 32bit ARGB format if current format is not supported
  139. // by canvas class
  140. if not (FImage.Format in TImagingCanvas.GetSupportedFormats) then
  141. FImage.Format := ifA8R8G8B8;
  142. end;
  143. // Activate first image and update UI
  144. FImage.ActiveImage := 0;
  145. SetSupported;
  146. PaintBox.Repaint;
  147. except
  148. SetUnsupported;
  149. raise;
  150. end
  151. else
  152. SetUnsupported;
  153. except
  154. SetUnsupported;
  155. end;
  156. end;
  157. procedure TMainForm.SetSupported;
  158. begin
  159. // Update image info and enable previous/next buttons
  160. LabDim.Caption := Format('%dx%d pixels', [FImage.Width, FImage.Height]);
  161. LabFileFormat.Caption := Imaging.FindImageFileFormatByName(FFileName).Name;
  162. LabDataFormat.Caption := Imaging.GetFormatName(FOriginalFormats[FImage.ActiveImage]);
  163. LabActImage.Caption := Format('%d/%d', [FImage.ActiveImage + 1, FImage.ImageCount]);
  164. BtnPrev.Enabled := True;
  165. BtnNext.Enabled := True;
  166. BtnFirst.Enabled := True;
  167. BtnLast.Enabled := True;
  168. BtnSave.Enabled := True;
  169. CheckFilter.Enabled := True;
  170. FSupported := True;
  171. end;
  172. procedure TMainForm.SetUnsupported;
  173. var
  174. X, Y, Step: LongInt;
  175. begin
  176. // Set info texts to 'unsupported' and create default image to show
  177. LabDim.Caption := SUnsupportedFormat;
  178. LabFileFormat.Caption := SUnsupportedFormat;
  179. LabDataFormat.Caption := SUnsupportedFormat;
  180. LabActImage.Caption := '0/0';
  181. StatusBar.SimpleText := 'No image loaded';
  182. BtnPrev.Enabled := False;
  183. BtnNext.Enabled := False;
  184. BtnFirst.Enabled := False;
  185. BtnLast.Enabled := False;
  186. BtnSave.Enabled := False;
  187. CheckFilter.Enabled := False;
  188. FSupported := False;
  189. if Assigned(FImage) then
  190. begin
  191. FImage.CreateFromParams(CheckersDensity, CheckersDensity, ifA8R8G8B8, 1);
  192. FImageCanvas.CreateForImage(FImage);
  193. Step := FImage.Width div CheckersDensity;
  194. for Y := 0 to CheckersDensity - 1 do
  195. for X := 0 to CheckersDensity - 1 do
  196. begin
  197. FImageCanvas.FillColor32 := IffUnsigned((Odd(X) and not Odd(Y)) or (not Odd(X) and Odd(Y)),
  198. pcWhite, pcBlack);
  199. FImageCanvas.FillRect(Rect(X * Step, Y * Step, (X + 1) * Step, (Y + 1) * Step));
  200. end;
  201. end;
  202. // Paint current image
  203. PaintBox.Repaint;
  204. end;
  205. procedure TMainForm.BtnPrevClick(Sender: TObject);
  206. begin
  207. FImage.ActiveImage := FImage.ActiveImage - 1;
  208. SetSupported;
  209. PaintBox.Repaint;
  210. end;
  211. procedure TMainForm.BtnSaveClick(Sender: TObject);
  212. var
  213. CopyPath: string;
  214. begin
  215. SaveDialog.Filter := Imaging.GetImageFileFormatsFilter(False);
  216. SaveDialog.FileName := ChangeFileExt(ExtractFileName(FFileName), '');
  217. SaveDialog.FilterIndex := Imaging.GetFileNameFilterIndex(FFileName, False);
  218. if SaveDialog.Execute then
  219. begin
  220. CopyPath := ChangeFileExt(SaveDialog.FileName, '.' +
  221. Imaging.GetFilterIndexExtension(SaveDialog.FilterIndex, False));
  222. FImage.SaveMultiToFile(CopyPath);
  223. end;
  224. end;
  225. procedure TMainForm.CheckFilterClick(Sender: TObject);
  226. begin
  227. PaintBox.Repaint;
  228. end;
  229. procedure TMainForm.BtnFirstClick(Sender: TObject);
  230. begin
  231. FImage.ActiveImage := 0;
  232. SetSupported;
  233. PaintBox.Repaint;
  234. end;
  235. procedure TMainForm.BtnLastClick(Sender: TObject);
  236. begin
  237. FImage.ActiveImage := FImage.ImageCount - 1;
  238. SetSupported;
  239. PaintBox.Repaint;
  240. end;
  241. procedure TMainForm.BtnNextClick(Sender: TObject);
  242. begin
  243. FImage.ActiveImage := FImage.ActiveImage + 1;
  244. SetSupported;
  245. PaintBox.Repaint;
  246. end;
  247. procedure TMainForm.TreeChange(Sender: TObject; Node: TTreeNode);
  248. begin
  249. // Selected item in the shell tree view has been changed
  250. // we check whether the selected item is valid file in one of the
  251. // supported formats
  252. FFileName := Tree.Path;
  253. LabFileName.Caption := ExtractFileName(FFileName);
  254. if FileExists(FFileName) and Assigned(Imaging.FindImageFileFormatByName(FFileName)) then
  255. LoadFile
  256. else
  257. SetUnsupported;
  258. end;
  259. procedure TMainForm.TreeKeyDown(Sender: TObject; var Key: Word;
  260. Shift: TShiftState);
  261. begin
  262. if FImage.ImageCount > 1 then
  263. begin
  264. if Key = VK_SPACE then
  265. BtnNextClick(Self);
  266. end;
  267. end;
  268. procedure TMainForm.ViewPanelResize(Sender: TObject);
  269. begin
  270. // Resize background image to fit the paint box
  271. FBack.Resize(PaintBox.ClientWidth, PaintBox.ClientHeight, rfNearest);
  272. // Update back canvas state after resizing of associated image
  273. FBackCanvas.UpdateCanvasState;
  274. end;
  275. procedure TMainForm.FormDestroy(Sender: TObject);
  276. begin
  277. FImage.Free;
  278. FImageCanvas.Free;
  279. FBack.Free;
  280. FBackCanvas.Free;
  281. end;
  282. procedure TMainForm.FormCreate(Sender: TObject);
  283. begin
  284. Caption := Caption + ' version ' + Imaging.GetVersionStr;
  285. FImage := TMultiImage.Create;
  286. FImageCanvas := TImagingCanvas.Create;
  287. FBack := TSingleImage.CreateFromParams(128, 128, ifA8R8G8B8);
  288. FBackCanvas := TImagingCanvas.CreateForImage(FBack);
  289. SetUnsupported;
  290. end;
  291. procedure TMainForm.PaintBoxPaint(Sender: TObject);
  292. var
  293. R: TRect;
  294. Filter: TResizeFilter;
  295. begin
  296. // Fill background with default color
  297. FillDefault;
  298. // Determine which stretching filter to use
  299. if FSupported and CheckFilter.Checked then
  300. Filter := rfBicubic
  301. else
  302. Filter := rfNearest;
  303. // Scale image to fit the paint box
  304. R := ImagingUtility.ScaleRectToRect(FImage.BoundsRect, PaintBox.ClientRect);
  305. // Create canvas for current image frame
  306. FImageCanvas.CreateForImage(FImage);
  307. // Stretch image over background canvas
  308. FImageCanvas.StretchDrawAlpha(FImage.BoundsRect, FBackCanvas, R, Filter);
  309. // Draw image to canvas (without conversion) using OS drawing functions.
  310. // Note that DisplayImage only supports images in ifA8R8G8B8 format so
  311. // if you have image in different format you must convert it or
  312. // create standard TBitmap by calling ImagingComponents.ConvertImageToBitmap
  313. ImagingComponents.DisplayImage(PaintBox.Canvas, PaintBox.BoundsRect, FBack);
  314. end;
  315. procedure TMainForm.FillDefault;
  316. begin
  317. // Fill background canvas with default color
  318. FBackCanvas.FillColor32 := FillColor;
  319. FBackCanvas.FillRect(Rect(0, 0, FBack.Width, FBack.Height));
  320. end;
  321. {
  322. File Notes:
  323. -- TODOS ----------------------------------------------------
  324. - nothing now
  325. -- 0.25.0 Changes/Bug Fixes ---------------------------------
  326. - Added alpha blended drawing with optional filtered stretching.
  327. -- 0.21 Changes/Bug Fixes -----------------------------------
  328. - Added Save Image Copy button and related stuff.
  329. - Added XP controls manifest (no TXPManifest since its not
  330. in older Delphis).
  331. - Wrong active image index was shown sometimes after several
  332. clicks on Prev/Next buttons.
  333. - Added First/Last subimage buttons.
  334. - Original data format of subimages at index >1 is displayed right now
  335. (was always A8R8G8B8)
  336. - Space key now shows next subimage if multi-images is loaded.
  337. -- 0.19 Changes/Bug Fixes -----------------------------------
  338. - added canvas usage too
  339. - added support for viewing multiimages (like MNG)
  340. - change drawing to use stuff from ImagingComponents unit instead of
  341. converting to TBitmap
  342. - changed demo to use high level interface instead of low level
  343. }
  344. end.