Bench.dpr 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. {
  2. Vampyre Imaging Library Demo
  3. Benchmark (ObjectPascal, low level, Win32/Linux/DOS)
  4. tested in Delphi 7/10, Kylix 3, Free Pascal 2.0.4 (Win32/Linux/DOS)
  5. written by Marek Mauder
  6. Simple program which measures time taken by the main Imaging functions
  7. (loading, manipulation, saving) in microsecond resolution.
  8. You can use it to compare the speeds of executables created by the supported
  9. compilers (you can find results for my machine somewhere in Demos directory).
  10. Important:
  11. 1) During the test large amounts of memory can be allocated by
  12. the program (e.g. conversion from 3000x3000x64 bit image to 128 bit requires
  13. over 200 MB of memory).
  14. 2) Program's executable must be located in Demos,
  15. Demos\SomeDir or Demos\SomeDir1\SomeDir2 to be able to find used data
  16. files.
  17. }
  18. program Bench;
  19. {$I ImagingOptions.inc}
  20. { Define this to write results to log file or undef it to
  21. display them on screen.}
  22. {$DEFINE LOG_TO_FILE}
  23. { Define this to write images created in saving test on disk.
  24. They are saved only to memory when testing.}
  25. { $DEFINE SAVE_IMAGES_TO_FILES}
  26. {$APPTYPE CONSOLE}
  27. uses
  28. SysUtils,
  29. Classes,
  30. ImagingTypes,
  31. Imaging,
  32. ImagingUtility,
  33. DemoUtils;
  34. type
  35. TManipulation = (maResize3k, maResize1k, maFlip, maMirror, maSwapChannels,
  36. maConvARGB64, maConvARGBF, maConvARGB16, maConvRGB24, maConvARGB32,
  37. maCompressDXT, maDecompressDXT, maReduceColors, maClone, maMipMaps,
  38. maCopyRect, maMapImage, maFill, maSplit, maMakePal, maReplace,
  39. maRotate180, maRotate90, maStretchRect);
  40. const
  41. SDataDir = 'Data';
  42. SLoadImageJpg = 'Tigers.jpg';
  43. SLoadImageBmp = 'Tigers.bmp';
  44. SLoadImagePng = 'Tigers.png';
  45. SLoadImageDds = 'Tigers.dds';
  46. SLoadImageTga = 'Tigers.tga';
  47. SLoadImageMng = 'Drake.mng';
  48. SLoadImageJng = 'Tigers.jng';
  49. SSaveImage = '_out';
  50. var
  51. Time: Int64;
  52. Img: TImageData;
  53. {$IFDEF LOG_TO_FILE}
  54. Output: TextFile;
  55. {$ENDIF}
  56. procedure WriteTimeDiff(const Msg: string; const OldTime: Int64);
  57. begin
  58. WriteLn(Output, Format('%-60s %16.0n us', [Msg, GetTimeMicroseconds - OldTime * 1.0]));
  59. end;
  60. procedure LoadImage(const Name: string);
  61. var
  62. Mem: TMemoryStream;
  63. begin
  64. Mem := TMemoryStream.Create;
  65. WriteLn(Output, 'Loading image: ' + Name);
  66. Mem.LoadFromFile(GetDataDir + PathDelim + Name);
  67. Time := GetTimeMicroseconds;
  68. // we are loading from memory stream so there is no file system
  69. // overhead measured
  70. Imaging.LoadImageFromStream(Mem, Img);
  71. WriteTimeDiff('Image loaded in:', Time);
  72. Mem.Free;
  73. end;
  74. procedure SaveImage(const Ext: string);
  75. var
  76. Mem: TMemoryStream;
  77. begin
  78. Mem := TMemoryStream.Create;
  79. WriteLn(Output, 'Saving image to format: ' + Ext);
  80. Time := GetTimeMicroseconds;
  81. // we are saving to memory stream so there is no file system
  82. // overhead measured
  83. Imaging.SaveImageToStream(Ext, Mem, Img);
  84. WriteTimeDiff('Image saved in:', Time);
  85. {$IFDEF SAVE_IMAGES_TO_FILES}
  86. Mem.SaveToFile(GetAppDir + PathDelim + sSaveImage + '.' + Ext);
  87. {$ENDIF}
  88. Mem.Free;
  89. end;
  90. var
  91. ImgClone: TImageData;
  92. Subs: TDynImageDataArray;
  93. FillColor: TColor32Rec = (Color: $FFFF0000);
  94. NewColor: TColor32Rec = (Color: $FF00CCFF);
  95. XCount, YCount: LongInt;
  96. Pal: PPalette32;
  97. procedure ManipulateImage(Man: TManipulation);
  98. begin
  99. // According to the enum value image manipulation functions are
  100. // called and measured.
  101. case Man of
  102. maResize3k:
  103. begin
  104. WriteLn(Output, 'Resizing image to 3000x3000 (bilinear) ... ');
  105. Time := GetTimeMicroseconds;
  106. Imaging.ResizeImage(Img, 3000, 3000, rfBilinear);
  107. WriteTimeDiff('Image resized in: ', Time);
  108. end;
  109. maResize1k:
  110. begin
  111. WriteLn(Output, 'Resizing image to 1000x1000 (bicubic) ... ');
  112. Time := GetTimeMicroseconds;
  113. Imaging.ResizeImage(Img, 1000, 1000, rfBicubic);
  114. WriteTimeDiff('Image resized in: ', Time);
  115. end;
  116. maFlip:
  117. begin
  118. WriteLn(Output, 'Flipping image ... ');
  119. Time := GetTimeMicroseconds;
  120. Imaging.FlipImage(Img);
  121. WriteTimeDiff('Image flipped in: ', Time);
  122. end;
  123. maMirror:
  124. begin
  125. WriteLn(Output, 'Mirroring image ... ');
  126. Time := GetTimeMicroseconds;
  127. Imaging.MirrorImage(Img);
  128. WriteTimeDiff('Image mirrored in:', Time);
  129. end;
  130. maSwapChannels:
  131. begin
  132. WriteLn(Output, 'Swapping channels of image ... ');
  133. Time := GetTimeMicroseconds;
  134. Imaging.SwapChannels(Img, ChannelRed, ChannelGreen);
  135. WriteTimeDiff('Channels swapped in: ', Time);
  136. end;
  137. maConvARGB64:
  138. begin
  139. WriteLn(Output, 'Converting image to A16R16G16B16 64bit format ... ');
  140. Time := GetTimeMicroseconds;
  141. Imaging.ConvertImage(Img, ifA16R16G16B16);
  142. WriteTimeDiff('Image converted in: ', Time);
  143. end;
  144. maConvARGBF:
  145. begin
  146. WriteLn(Output, 'Converting image to A32B32G32R32F 128bit floating ' +
  147. 'point format... ');
  148. Time := GetTimeMicroseconds;
  149. Imaging.ConvertImage(Img, ifA32B32G32R32F);
  150. WriteTimeDiff('Image converted in: ', Time);
  151. end;
  152. maConvARGB16:
  153. begin
  154. WriteLn(Output, 'Converting image to A4R4G4B4 16bit format... ');
  155. Time := GetTimeMicroseconds;
  156. Imaging.ConvertImage(Img, ifA4R4G4B4);
  157. WriteTimeDiff('Image converted in: ', Time);
  158. end;
  159. maConvRGB24:
  160. begin
  161. WriteLn(Output, 'Converting image to R8G8B8 24bit format... ');
  162. Time := GetTimeMicroseconds;
  163. Imaging.ConvertImage(Img, ifR8G8B8);
  164. WriteTimeDiff('Image converted in: ', Time);
  165. end;
  166. maConvARGB32:
  167. begin
  168. WriteLn(Output, 'Converting image to A8R8G8B8 32bit format... ');
  169. Time := GetTimeMicroseconds;
  170. Imaging.ConvertImage(Img, ifA8R8G8B8);
  171. WriteTimeDiff('Image converted in: ', Time);
  172. end;
  173. maCompressDXT:
  174. begin
  175. WriteLn(Output, 'Compressing image to DXT1 format... ');
  176. Time := GetTimeMicroseconds;
  177. Imaging.ConvertImage(Img, ifDXT1);
  178. WriteTimeDiff('Image compressed in: ', Time);
  179. end;
  180. maDecompressDXT:
  181. begin
  182. WriteLn(Output, 'Decompressing image from DXT1 format... ');
  183. Time := GetTimeMicroseconds;
  184. Imaging.ConvertImage(Img, ifA8R8G8B8);
  185. WriteTimeDiff('Image decompressed in: ', Time);
  186. end;
  187. maReduceColors:
  188. begin
  189. WriteLn(Output, 'Reducing colors count to 1024... ');
  190. Time := GetTimeMicroseconds;
  191. Imaging.ReduceColors(Img, 1024);
  192. WriteTimeDiff('Colors reduced in: ', Time);
  193. end;
  194. maMipMaps:
  195. begin
  196. WriteLn(Output, 'Creating mipmaps ... ');
  197. SetLength(Subs, 0);
  198. Time := GetTimeMicroseconds;
  199. Imaging.GenerateMipMaps(Img, 0, Subs);
  200. WriteTimeDiff('Mipmaps created in: ', Time);
  201. Imaging.FreeImagesInArray(Subs);
  202. end;
  203. maClone:
  204. begin
  205. WriteLn(Output, 'Cloning image ... ');
  206. Imaging.InitImage(ImgClone);
  207. Time := GetTimeMicroseconds;
  208. Imaging.CloneImage(Img, ImgClone);
  209. WriteTimeDiff('Image cloned in: ', Time);
  210. end;
  211. maCopyRect:
  212. begin
  213. WriteLn(Output, 'Copying rectangle ... ');
  214. Time := GetTimeMicroseconds;
  215. Imaging.CopyRect(ImgClone, 0, 1500, 1500, 1500, Img, 0, 0);
  216. WriteTimeDiff('Rectangle copied in: ', Time);
  217. end;
  218. maStretchRect:
  219. begin
  220. WriteLn(Output, 'Stretching rectangle (bicubic) ... ');
  221. Time := GetTimeMicroseconds;
  222. Imaging.StretchRect(ImgClone, 0, 1500, 1500, 1500, Img, 500, 500, 2000, 2000, rfBicubic);
  223. WriteTimeDiff('Rectangle stretched in: ', Time);
  224. Imaging.FreeImage(ImgClone);
  225. end;
  226. maMapImage:
  227. begin
  228. WriteLn(Output, 'Mapping image to existing palette ... ');
  229. Time := GetTimeMicroseconds;
  230. Imaging.MapImageToPalette(Img, Pal, 256);
  231. WriteTimeDiff('Image mapped in: ', Time);
  232. Imaging.FreePalette(Pal);
  233. end;
  234. maFill:
  235. begin
  236. WriteLn(Output, 'Filling rectangle ... ');
  237. Time := GetTimeMicroseconds;
  238. Imaging.FillRect(Img, 1500, 0, 1500, 1500, @FillColor);
  239. WriteTimeDiff('Rectangle filled in: ', Time);
  240. end;
  241. maReplace:
  242. begin
  243. WriteLn(Output, 'Replacing colors in rectangle ... ');
  244. Time := GetTimeMicroseconds;
  245. Imaging.ReplaceColor(Img, 0, 0, Img.Width, Img.Height, @FillColor, @NewColor);
  246. WriteTimeDiff('Colors replaced in: ', Time);
  247. end;
  248. maSplit:
  249. begin
  250. WriteLn(Output, 'Splitting image ... ');
  251. SetLength(Subs, 0);
  252. Time := GetTimeMicroseconds;
  253. Imaging.SplitImage(Img, Subs, 300, 300, XCount, YCount, True, @FillColor);
  254. WriteTimeDiff('Image split in: ', Time);
  255. Imaging.FreeImagesInArray(Subs);
  256. end;
  257. maMakePal:
  258. begin
  259. WriteLn(Output, 'Making palette for images ... ');
  260. Imaging.NewPalette(256, Pal);
  261. SetLength(Subs, 1);
  262. Subs[0] := Img;
  263. Time := GetTimeMicroseconds;
  264. Imaging.MakePaletteForImages(Subs, Pal, 256, False);
  265. WriteTimeDiff('Palette made in: ', Time);
  266. Img := Subs[0];
  267. end;
  268. maRotate180:
  269. begin
  270. WriteLn(Output, 'Rotating image 180 degrees CCW ... ');
  271. Time := GetTimeMicroseconds;
  272. Imaging.RotateImage(Img, 180);
  273. WriteTimeDiff('Image rotated in: ', Time);
  274. end;
  275. maRotate90:
  276. begin
  277. WriteLn(Output, 'Rotating image 90 degrees CCW ... ');
  278. Time := GetTimeMicroseconds;
  279. Imaging.RotateImage(Img, 90);
  280. WriteTimeDiff('Image rotated in: ', Time);
  281. end;
  282. end;
  283. end;
  284. begin
  285. {$IFDEF LOG_TO_FILE}
  286. // if logging to file is defined new output file is created
  287. // and all messages are written into it
  288. AssignFile(Output, GetAppDir + PathDelim + 'ResultsPas.log');
  289. Rewrite(Output);
  290. WriteLn('Benchmarking ...');
  291. {$ELSE}
  292. // else standard System.Output file is used
  293. {$ENDIF}
  294. WriteLn(Output, 'Vampyre Imaging Library Benchmark Demo version ',
  295. Imaging.GetVersionStr);
  296. WriteLn(Output);
  297. SysUtils.ThousandSeparator := ' ';
  298. if not DirectoryExists(GetDataDir) then
  299. begin
  300. // if required testing data is not found, program halts
  301. WriteLn(Output, 'Error!' + sLineBreak + '"Data" directory with ' +
  302. 'required "Tigers.*" images not found.');
  303. WriteLn;
  304. WriteLn('Press RETURN key to exit');
  305. ReadLn;
  306. Halt(1);
  307. end;
  308. // call this before any manipulation with TImageData record
  309. Imaging.InitImage(Img);
  310. try
  311. // test image loading functions for all supported image file formats
  312. // note that image loaded in one LoadImage is automaticaly
  313. // freed in then next LoadImage call
  314. WriteLn(Output, '------------- Loading Images -------------');
  315. LoadImage(SLoadImageJpg);
  316. LoadImage(SLoadImageBmp);
  317. LoadImage(SLoadImagePng);
  318. LoadImage(SLoadImageTga);
  319. LoadImage(SLoadImageMng);
  320. LoadImage(SLoadImageJng);
  321. LoadImage(SLoadImageDds);
  322. // test image manipulation functions like conversions, resizing and other
  323. WriteLn(Output, sLineBreak + '----------- Image Manipulation -----------');
  324. ManipulateImage(maDecompressDXT);
  325. ManipulateImage(maResize3k);
  326. ManipulateImage(maConvARGB64);
  327. ManipulateImage(maFlip);
  328. ManipulateImage(maMirror);
  329. ManipulateImage(maSwapChannels);
  330. ManipulateImage(maConvARGBF);
  331. ManipulateImage(maConvARGB16);
  332. ManipulateImage(maConvARGB32);
  333. ManipulateImage(maClone);
  334. ManipulateImage(maCopyRect);
  335. ManipulateImage(maFill);
  336. ManipulateImage(maStretchRect);
  337. ManipulateImage(maReplace);
  338. ManipulateImage(maMipMaps);
  339. ManipulateImage(maSplit);
  340. ManipulateImage(maResize1k);
  341. ManipulateImage(maRotate180);
  342. ManipulateImage(maRotate90);
  343. ManipulateImage(maReduceColors);
  344. ManipulateImage(maMakePal);
  345. ManipulateImage(maMapImage);
  346. ManipulateImage(maCompressDXT);
  347. // test image saving functions. Image is converted to R8G8B8 after DDS file
  348. // saving, otherwise image would have to be decompressed from DXT1 by
  349. // the other image savers every time.
  350. WriteLn(Output, sLineBreak + '------------- Saving Images --------------');
  351. SaveImage('dds');
  352. ManipulateImage(maConvRGB24);
  353. SaveImage('jpg');
  354. SaveImage('bmp');
  355. SaveImage('png');
  356. SaveImage('tga');
  357. SaveImage('mng');
  358. SaveImage('jng');
  359. except
  360. on E: Exception do
  361. begin
  362. WriteLn('Exception Raised!');
  363. WriteLn(E.Message);
  364. end;
  365. end;
  366. // image must be freed in the end
  367. Imaging.FreeImage(Img);
  368. {$IFDEF LOG_TO_FILE}
  369. CloseFile(Output);
  370. WriteLn('Results written to "ResultsPas.log" file.');
  371. {$ENDIF}
  372. WriteLn;
  373. WriteLn('Press RETURN key to exit');
  374. ReadLn;
  375. {
  376. File Notes:
  377. -- 0.19 Changes/Bug Fixes -----------------------------------
  378. - added thousand separators to output times
  379. -- 0.17 Changes/Bug Fixes -----------------------------------
  380. - added filtered image resizing and rectangle stretching
  381. - added MNG and JNG file saving and loading and exception catcher
  382. }
  383. end.