Main.pas 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. {
  2. Vampyre Imaging Library Demo
  3. VCL Image Browser (ObjectPascal, high level/component sets/canvas, Win32)
  4. tested in Delphi 7/10
  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. }
  21. unit Main;
  22. {$I ImagingOptions.inc}
  23. {$IF not Defined(COMPONENT_SET_VCL) or not Defined(DELPHI)}
  24. {$MESSAGE ERROR 'This program requires Delphi with VCL'}
  25. {$IFEND}
  26. interface
  27. uses
  28. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  29. Dialogs, ComCtrls, ShellCtrls, ExtCtrls, StdCtrls, Buttons, ExtDlgs,
  30. ImagingTypes,
  31. Imaging,
  32. ImagingClasses,
  33. ImagingComponents,
  34. ImagingCanvases,
  35. ImagingFormats,
  36. ImagingUtility;
  37. type
  38. TMainForm = class(TForm)
  39. LeftPanel: TPanel;
  40. RightPanel: TPanel;
  41. InfoPanel: TPanel;
  42. LabDataFormat: TLabel;
  43. LabFileFormat: TLabel;
  44. LabDim: TLabel;
  45. LabFileName: TLabel;
  46. Label3: TLabel;
  47. Label2: TLabel;
  48. Label1: TLabel;
  49. Lab1: TLabel;
  50. ViewPanel: TPanel;
  51. PaintBox: TPaintBox;
  52. Tree: TShellTreeView;
  53. Splitter1: TSplitter;
  54. Label4: TLabel;
  55. LabActImage: TLabel;
  56. StatusBar: TStatusBar;
  57. BtnPrev: TSpeedButton;
  58. BtnNext: TSpeedButton;
  59. BtnFirst: TSpeedButton;
  60. BtnLast: TSpeedButton;
  61. BtnSave: TButton;
  62. SaveDialog: TSavePictureDialog;
  63. procedure PaintBoxPaint(Sender: TObject);
  64. procedure FormCreate(Sender: TObject);
  65. procedure FormDestroy(Sender: TObject);
  66. procedure TreeChange(Sender: TObject; Node: TTreeNode);
  67. procedure BtnPrevClick(Sender: TObject);
  68. procedure BtnNextClick(Sender: TObject);
  69. procedure TreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  70. procedure BtnFirstClick(Sender: TObject);
  71. procedure BtnLastClick(Sender: TObject);
  72. procedure BtnSaveClick(Sender: TObject);
  73. private
  74. FImage: ImagingClasses.TMultiImage; // Class that hold multiple images (load from MNG or DDS files for instance)
  75. FFileName: string;
  76. FLastTime: LongInt;
  77. FOriginalFormats: array of TImageFormat;
  78. public
  79. procedure SetSupported;
  80. procedure SetUnsupported;
  81. procedure LoadFile;
  82. procedure FillDefault;
  83. end;
  84. const
  85. FillColor = $00FFFFA6;
  86. CheckersDensity = 8;
  87. SUnsupportedFormat = 'Selected item format not supported';
  88. var
  89. MainForm: TMainForm;
  90. implementation
  91. {$R *.dfm}
  92. {$IF CompilerVersion >= 15.0}
  93. uses
  94. XPMan;
  95. {$IFEND}
  96. procedure TMainForm.LoadFile;
  97. var
  98. I: LongInt;
  99. T: Int64;
  100. begin
  101. try
  102. // DetermineFileFormat reads file header and returns image
  103. // file format identifier (like 'jpg', 'tga') if file is valid,
  104. // otherwise empty string is returned
  105. if Imaging.DetermineFileFormat(FFileName) <> '' then
  106. try
  107. // Load all subimages in file
  108. T := ImagingUtility.GetTimeMicroseconds;
  109. FImage.LoadMultiFromFile(FFileName);
  110. FLastTime := (ImagingUtility.GetTimeMicroseconds - T) div 1000;
  111. StatusBar.SimpleText := Format('Last image loaded in: %.0n ms', [FLastTime * 1.0]);
  112. // Store original data formats for later use
  113. SetLength(FOriginalFormats, FImage.ImageCount);
  114. for I := 0 to FImage.ImageCount - 1 do
  115. FOriginalFormats[I] := FImage.Images[I].Format;
  116. // Convert images to 32bit ARGB format for easier drawing later
  117. FImage.ConvertImages(ifA8R8G8B8);
  118. SetSupported;
  119. PaintBox.Repaint;
  120. except
  121. SetUnsupported;
  122. raise;
  123. end
  124. else
  125. SetUnsupported;
  126. except
  127. SetUnsupported;
  128. end;
  129. end;
  130. procedure TMainForm.SetSupported;
  131. begin
  132. // Update image info and enable previous/next buttons
  133. LabDim.Caption := Format('%dx%d pixels', [FImage.Width, FImage.Height]);
  134. LabFileFormat.Caption := Imaging.FindImageFileFormatByName(FFileName).Name;
  135. LabDataFormat.Caption := Imaging.GetFormatName(FOriginalFormats[FImage.ActiveImage]);
  136. LabActImage.Caption := Format('%d/%d', [FImage.ActiveImage + 1, FImage.ImageCount]);
  137. BtnPrev.Enabled := True;
  138. BtnNext.Enabled := True;
  139. BtnFirst.Enabled := True;
  140. BtnLast.Enabled := True;
  141. BtnSave.Enabled := True;
  142. end;
  143. procedure TMainForm.SetUnsupported;
  144. var
  145. ImgCanvas: ImagingCanvases.TImagingCanvas;
  146. X, Y, Step: LongInt;
  147. begin
  148. // Set info texts to 'unsupported' and create default image to show
  149. LabDim.Caption := SUnsupportedFormat;
  150. LabFileFormat.Caption := SUnsupportedFormat;
  151. LabDataFormat.Caption := SUnsupportedFormat;
  152. LabActImage.Caption := '0/0';
  153. StatusBar.SimpleText := 'No image loaded';
  154. BtnPrev.Enabled := False;
  155. BtnNext.Enabled := False;
  156. BtnFirst.Enabled := False;
  157. BtnLast.Enabled := False;
  158. BtnSave.Enabled := False;
  159. if Assigned(FImage) then
  160. begin
  161. FImage.CreateFromParams(CheckersDensity, CheckersDensity, ifA8R8G8B8, 1);
  162. // Create canvas for image and draw checker board
  163. ImgCanvas := ImagingCanvases.FindBestCanvasForImage(FImage).CreateForImage(FImage);
  164. Step := FImage.Width div CheckersDensity;
  165. for Y := 0 to CheckersDensity - 1 do
  166. for X := 0 to CheckersDensity - 1 do
  167. begin
  168. ImgCanvas.FillColor32 := IffUnsigned((Odd(X) and not Odd(Y)) or (not Odd(X) and Odd(Y)),
  169. pcWhite, pcBlack);
  170. ImgCanvas.FillRect(Rect(X * Step, Y * Step, (X + 1) * Step, (Y + 1) * Step));
  171. end;
  172. ImgCanvas.Free;
  173. end;
  174. // Paint current image
  175. PaintBox.Repaint;
  176. end;
  177. procedure TMainForm.BtnPrevClick(Sender: TObject);
  178. begin
  179. FImage.ActiveImage := FImage.ActiveImage - 1;
  180. SetSupported;
  181. PaintBox.Repaint;
  182. end;
  183. procedure TMainForm.BtnSaveClick(Sender: TObject);
  184. var
  185. CopyPath: string;
  186. begin
  187. SaveDialog.Filter := Imaging.GetImageFileFormatsFilter(False);
  188. SaveDialog.FileName := ChangeFileExt(ExtractFileName(FFileName), '');
  189. SaveDialog.FilterIndex := Imaging.GetFileNameFilterIndex(FFileName, False);
  190. if SaveDialog.Execute then
  191. begin
  192. CopyPath := ChangeFileExt(SaveDialog.FileName, '.' +
  193. Imaging.GetFilterIndexExtension(SaveDialog.FilterIndex, False));
  194. FImage.SaveMultiToFile(CopyPath);
  195. end;
  196. end;
  197. procedure TMainForm.BtnFirstClick(Sender: TObject);
  198. begin
  199. FImage.ActiveImage := 0;
  200. SetSupported;
  201. PaintBox.Repaint;
  202. end;
  203. procedure TMainForm.BtnLastClick(Sender: TObject);
  204. begin
  205. FImage.ActiveImage := FImage.ImageCount - 1;
  206. SetSupported;
  207. PaintBox.Repaint;
  208. end;
  209. procedure TMainForm.BtnNextClick(Sender: TObject);
  210. begin
  211. FImage.ActiveImage := FImage.ActiveImage + 1;
  212. SetSupported;
  213. PaintBox.Repaint;
  214. end;
  215. procedure TMainForm.TreeChange(Sender: TObject; Node: TTreeNode);
  216. begin
  217. // Selected item in the shell tree view has been changed
  218. // we check whether the selected item is valid file in one of the
  219. // supported formats
  220. FFileName := Tree.Path;
  221. LabFileName.Caption := ExtractFileName(FFileName);
  222. if FileExists(FFileName) and Assigned(Imaging.FindImageFileFormatByName(FFileName)) then
  223. LoadFile
  224. else
  225. SetUnsupported;
  226. end;
  227. procedure TMainForm.TreeKeyDown(Sender: TObject; var Key: Word;
  228. Shift: TShiftState);
  229. begin
  230. if FImage.ImageCount > 1 then
  231. begin
  232. if Key = VK_SPACE then
  233. BtnNextClick(Self);
  234. end;
  235. end;
  236. procedure TMainForm.FormDestroy(Sender: TObject);
  237. begin
  238. FImage.Free;
  239. end;
  240. procedure TMainForm.FormCreate(Sender: TObject);
  241. begin
  242. Caption := Caption + ' version ' + Imaging.GetVersionStr;
  243. FImage := TMultiImage.Create;
  244. SetUnsupported;
  245. end;
  246. procedure TMainForm.PaintBoxPaint(Sender: TObject);
  247. var
  248. R: TRect;
  249. begin
  250. FillDefault;
  251. if (FImage.Width > 0) and (FImage.Height > 0) and (FImage.Format = ifA8R8G8B8) then
  252. begin
  253. // Scale image to fit the paint box
  254. R := ImagingUtility.ScaleRectToRect(FImage.BoundsRect, PaintBox.ClientRect);
  255. // Draw image to canvas (without conversion) using OS drawing functions.
  256. // Note that DisplayImage only supports images in ifA8R8G8B8 format so
  257. // if you have image in different format you must convert it or
  258. // create standard TBitmap by calling ImagingComponents.ConvertImageToBitmap
  259. ImagingComponents.DisplayImage(PaintBox.Canvas, R, FImage);
  260. end;
  261. end;
  262. procedure TMainForm.FillDefault;
  263. begin
  264. PaintBox.Canvas.Brush.Color := FillColor;
  265. PaintBox.Canvas.FillRect(PaintBox.ClientRect);
  266. end;
  267. {
  268. File Notes:
  269. -- TODOS ----------------------------------------------------
  270. - nothing now
  271. -- 0.21 Changes/Bug Fixes -----------------------------------
  272. - Added Save Image Copy button and related stuff.
  273. - Added XP controls manifest (no TXPManifest since its not
  274. in older Delphis).
  275. - Wrong active image index was shown sometimes after several
  276. clicks on Prev/Next buttons.
  277. - Added First/Last subimage buttons.
  278. - Original data format of subimages at index >1 is displayed right now
  279. (was always A8R8G8B8)
  280. - Space key now shows next subimage if multi-images is loaded.
  281. -- 0.19 Changes/Bug Fixes -----------------------------------
  282. - added canvas usage too
  283. - added support for viewing multiimages (like MNG)
  284. - change drawing to use stuff from ImagingComponents unit instead of
  285. converting to TBitmap
  286. - changed demo to use high level interface instead of low level
  287. }
  288. end.