Main.pas 10 KB

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