Bench.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // Vampyre Imaging Library Demo
  2. // Benchmark (C++, dll library usage, Win32)
  3. // tested in MSVC 8.0, BC++ 5.6.4
  4. // written by Marek Mauder
  5. //
  6. // This is not actually benchmark like ObjectPascal version because
  7. // all measured functions are called from external library, but it
  8. // shows how to use Imaging dll from C/C++ at least.
  9. //
  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
  13. // requires over 200 MB of memory).
  14. // 2) Program's executable must be located in Demos\Bin,
  15. // or anywhere in the subdirectories of Demos\Cpp dir to be able to find
  16. // used data files.
  17. //
  18. // Compiled Imaging library must be located somewhere on system's
  19. // search path for this sample to work (usually VampyreImaging.dll
  20. // in C:\Windows or libVampyreImaging.so in /lib).
  21. #include <iostream>
  22. #include <string>
  23. #include <fstream>
  24. #include <vector>
  25. #include <cstdio>
  26. #include "..\..\..\Source\Wrappers\Cpp\ImagingImport.h"
  27. using namespace Imaging;
  28. using namespace std;
  29. // Define this to write results to log file or undef it to
  30. // display them on screen.
  31. #define LOG_TO_FILE
  32. // Define this to write images created in saving test on disk.
  33. // They are saved only to memory when testing.
  34. #define SAVE_IMAGES_TO_FILES
  35. LARGE_INTEGER PerfFrequency;
  36. double InvPerfFrequency;
  37. const string SDataDir = "Data\\";
  38. const string SImageName = "Tigers";
  39. const string SSaveImage = "_BenchOut";
  40. const int BufSize = 8 * 1024 * 1024;
  41. enum TManipulation {maResize3k, maResize1k, maFlip, maMirror, maSwapChannels,
  42. maConvARGB64, maConvARGBF, maConvARGB16, maConvRGB24, maConvARGB32,
  43. maCompressDXT, maDecompressDXT, maReduceColors, maClone, maMipMaps,
  44. maCopyRect, maMapImage, maFill, maSplit, maMakePal, maReplace, maRotate180,
  45. maRotate90, maStretchRect};
  46. struct TFileFormatInfo
  47. {
  48. char Name[64];
  49. char Ext[16];
  50. char Masks[128];
  51. Boolean CanSave;
  52. Boolean IsMulti;
  53. };
  54. #ifdef LOG_TO_FILE
  55. fstream Out;
  56. #else
  57. // If logging to files is not defined standard cout is used
  58. ostream &Out = cout;
  59. #endif
  60. TImageData Img, ImgClone;
  61. LONGLONG Time;
  62. string Dir;
  63. char SaveBuf[BufSize];
  64. TImageDataList Subs = 0;
  65. TColor32Rec FillColor, NewColor;
  66. int I, XCount, YCount;
  67. PPalette32 Pal = NULL;
  68. vector<TFileFormatInfo> Formats;
  69. string GetAppDir(void);
  70. string GetDataDir(void);
  71. string GetImageName(const string &Ext);
  72. LONGLONG GetTimeMicroseconds(void);
  73. void LoadImage(const string &Name);
  74. void SaveImage(const string &Ext);
  75. void ManipulateImage(const TManipulation Man);
  76. int main(int argc, char ** argv)
  77. {
  78. char tmp;
  79. int Major, Minor, Patch;
  80. Dir = argv[0];
  81. FillColor.Color = 0xFFFF0000;
  82. NewColor.Color = 0xFF00CCFF;
  83. QueryPerformanceFrequency(&PerfFrequency);
  84. InvPerfFrequency = (double)1.0 / PerfFrequency.QuadPart;
  85. #ifdef LOG_TO_FILE
  86. // if logging to file is defined new output file is created
  87. // and all messages are written into it
  88. Out.open("ResultsCpp.log", ios::out);
  89. cout << "Benchmarking..." << endl;
  90. #endif
  91. // This call must be made before any atempt to use any Imaging function.
  92. // Everything is imported from dll here.
  93. ImLoadLibrary();
  94. // Call this before any manipulation with TImageData record
  95. ImInitImage(&Img);
  96. ImGetVersion(&Major, &Minor, &Patch);
  97. Out << "Vampyre Imaging Library Benchmark Demo (C++) version " <<
  98. Major << '.' << Minor << '.' << Patch << endl << endl;
  99. I = 0;
  100. Formats.resize(1);
  101. // Enumerate all supported file formats and store their properties
  102. // to dyn array. After each iteration dyn array's size is increased by one
  103. // so next call to EnumFileFormats will have free space for results.
  104. // After enumerating last array item should be deleted because its empty.
  105. while (ImEnumFileFormats(&I, Formats[I].Name, Formats[I].Ext, Formats[I].Masks, &Formats[I].CanSave, &Formats[I].IsMulti))
  106. Formats.resize(I + 1);
  107. Formats.resize(I);
  108. // Test image loading functions for all supported image file formats
  109. // note that image loaded in one LoadImage is automaticaly
  110. // freed in then next LoadImage call so no leaks (should) occurr.
  111. Out << "------------- Loading Images -------------" << endl;
  112. for (I = 0; I < (int)Formats.size(); I++)
  113. LoadImage(GetImageName(Formats[I].Ext));
  114. // Test image manipulation functions like conversions, resizing and other
  115. Out << endl << "----------- Image Manipulation -----------" << endl;
  116. ManipulateImage(maResize3k);
  117. ManipulateImage(maConvARGB64);
  118. ManipulateImage(maFlip);
  119. ManipulateImage(maMirror);
  120. ManipulateImage(maSwapChannels);
  121. ManipulateImage(maConvARGBF);
  122. ManipulateImage(maConvARGB16);
  123. ManipulateImage(maConvARGB32);
  124. ManipulateImage(maClone);
  125. ManipulateImage(maCopyRect);
  126. ManipulateImage(maFill);
  127. ManipulateImage(maStretchRect);
  128. ManipulateImage(maReplace);
  129. ManipulateImage(maMipMaps);
  130. ManipulateImage(maSplit);
  131. ManipulateImage(maResize1k);
  132. ManipulateImage(maRotate180);
  133. ManipulateImage(maRotate90);
  134. ManipulateImage(maReduceColors);
  135. ManipulateImage(maMakePal);
  136. ManipulateImage(maMapImage);
  137. ManipulateImage(maCompressDXT);
  138. ManipulateImage(maDecompressDXT);
  139. ManipulateImage(maConvRGB24);
  140. // Test image saving functions. Image is now in R8G8B8 format. Note that
  141. // some supported file formats cannot save images in R8G8B8 so their
  142. // time includes conversions.
  143. Out << endl << "------------- Saving Images --------------" << endl;
  144. for (I = 0; I < (int)Formats.size(); I++)
  145. {
  146. if (Formats[I].CanSave)
  147. SaveImage(Formats[I].Ext);
  148. }
  149. // Image must be freed in the end
  150. ImFreeImage(&Img);
  151. // Call this if you no longer need to use Imaging functions
  152. // Imaging dll is unloaded here
  153. ImFreeLibrary();
  154. #ifdef LOG_TO_FILE
  155. Out.close();
  156. cout << "Results written to 'ResultsCpp.log' file." << endl;
  157. #endif
  158. cout << "Press any key to exit" << endl;
  159. cin.get(tmp);
  160. return 0;
  161. }
  162. string GetAppDir(void)
  163. {
  164. int Idx;
  165. string Res = Dir;
  166. Idx = static_cast<int>(Res.rfind("\\"));
  167. if (Idx > 0)
  168. Res.erase(Idx + 1);
  169. return Res;
  170. }
  171. string GetDataDir(void)
  172. {
  173. int Idx;
  174. string Res = Dir;
  175. Idx = static_cast<int>(Res.find("Bin\\"));
  176. if (Idx >= 0)
  177. return Res.erase(Idx) + SDataDir;
  178. Idx = static_cast<int>(Res.find("Cpp\\"));
  179. if (Idx >= 0)
  180. return Res.erase(Idx) + SDataDir;
  181. return Res;
  182. }
  183. string GetImageName(const string &Ext)
  184. {
  185. return GetDataDir() + SImageName + '.' + Ext;
  186. }
  187. LONGLONG GetTimeMicroseconds(void)
  188. {
  189. LARGE_INTEGER Time;
  190. QueryPerformanceCounter(&Time);
  191. return static_cast<LONGLONG>(1000000 * InvPerfFrequency * Time.QuadPart);
  192. }
  193. void LoadImage(const string &Name)
  194. {
  195. FILE *File = fopen(Name.c_str(), "rb");
  196. if (File == NULL)
  197. return;
  198. else
  199. fclose(File);
  200. Out << "Loading image: " << Name << endl;
  201. Time = GetTimeMicroseconds();
  202. ImLoadImageFromFile(Name.c_str(), &Img);
  203. Out << "Image loaded in: " << GetTimeMicroseconds() - Time << " us" << endl;
  204. }
  205. void SaveImage(const string &Ext)
  206. {
  207. int Size = BufSize;
  208. Out << "Saving image to format: " << Ext << endl;
  209. Time = GetTimeMicroseconds();
  210. ImSaveImageToMemory(Ext.c_str(), (void*)SaveBuf, &Size, &Img);
  211. Out << "Image saved in: " << GetTimeMicroseconds() - Time << " us" << endl;
  212. #ifdef SAVE_IMAGES_TO_FILES
  213. ImSaveImageToFile((GetAppDir() + SSaveImage + '.' + Ext).c_str(), &Img);
  214. #endif
  215. }
  216. void ManipulateImage(const TManipulation Man)
  217. {
  218. // According to the enum value image manipulation functions are
  219. // called and measured.
  220. switch (Man)
  221. {
  222. case maResize3k:
  223. Out << "Resizing image to 3000x3000 (bilinear) ..." << endl;
  224. Time = GetTimeMicroseconds();
  225. ImResizeImage(&Img, 3000, 3000, rfBilinear);
  226. Out << "Image resized in: " << GetTimeMicroseconds() - Time << " us" << endl;
  227. break;
  228. case maResize1k:
  229. Out << "Resizing image to 1000x1000 (bicubic) ..." << endl;
  230. Time = GetTimeMicroseconds();
  231. ImResizeImage(&Img, 1000, 1000, rfBicubic);
  232. Out << "Image resized in: " << GetTimeMicroseconds() - Time << " us" << endl;
  233. break;
  234. case maFlip:
  235. Out << "Flipping image ..." << endl;
  236. Time = GetTimeMicroseconds();
  237. ImFlipImage(&Img);
  238. Out << "Image flipped in: " << GetTimeMicroseconds() - Time << " us" << endl;
  239. break;
  240. case maMirror:
  241. Out << "Mirroring image ..." << endl;
  242. Time = GetTimeMicroseconds();
  243. ImMirrorImage(&Img);
  244. Out << "Image mirrored in: " << GetTimeMicroseconds() - Time << " us" << endl;
  245. break;
  246. case maSwapChannels:
  247. Out << "Swapping channels of image ..." << endl;
  248. Time = GetTimeMicroseconds();
  249. ImSwapChannels(&Img, ChannelRed, ChannelGreen);
  250. Out << "Channels swapped in: " << GetTimeMicroseconds() - Time << " us" << endl;
  251. break;
  252. case maConvARGB64:
  253. Out << "Converting image to A16R16G16B16 64bit format ..." << endl;
  254. Time = GetTimeMicroseconds();
  255. ImConvertImage(&Img, ifA16R16G16B16);
  256. Out << "Image converted in: " << GetTimeMicroseconds() - Time << " us" << endl;
  257. break;
  258. case maConvARGBF:
  259. Out << "Converting image to A32B32G32R32F 128bit floating point format ..." << endl;
  260. Time = GetTimeMicroseconds();
  261. ImConvertImage(&Img, ifA32B32G32R32F);
  262. Out << "Image converted in: " << GetTimeMicroseconds() - Time << " us" << endl;
  263. break;
  264. case maConvARGB16:
  265. Out << "Converting image to A4R4G4B4 16bit format ..." << endl;
  266. Time = GetTimeMicroseconds();
  267. ImConvertImage(&Img, ifA4R4G4B4);
  268. Out << "Image converted in: " << GetTimeMicroseconds() - Time << " us" << endl;
  269. break;
  270. case maConvRGB24:
  271. Out << "Converting image to R8G8B8 24bit format ..." << endl;
  272. Time = GetTimeMicroseconds();
  273. ImConvertImage(&Img, ifR8G8B8);
  274. Out << "Image converted in: " << GetTimeMicroseconds() - Time << " us" << endl;
  275. break;
  276. case maConvARGB32:
  277. Out << "Converting image to A8R8G8B8 32bit format ..." << endl;
  278. Time = GetTimeMicroseconds();
  279. ImConvertImage(&Img, ifA8R8G8B8);
  280. Out << "Image converted in: " << GetTimeMicroseconds() - Time << " us" << endl;
  281. break;
  282. case maCompressDXT:
  283. Out << "Compressing image to DXT1 format ..." << endl;
  284. Time = GetTimeMicroseconds();
  285. ImConvertImage(&Img, ifDXT1);
  286. Out << "Image compressed in: " << GetTimeMicroseconds() - Time << " us" << endl;
  287. break;
  288. case maDecompressDXT:
  289. Out << "Decompressing image from DXT1 format ..." << endl;
  290. Time = GetTimeMicroseconds();
  291. ImConvertImage(&Img, ifA8R8G8B8);
  292. Out << "Image decompressed in: " << GetTimeMicroseconds() - Time << " us" << endl;
  293. break;
  294. case maReduceColors:
  295. Out << "Reducing colors count to 1024 ..." << endl;
  296. Time = GetTimeMicroseconds();
  297. ImReduceColors(&Img, 1024);
  298. Out << "Colors reduced in in: " << GetTimeMicroseconds() - Time << " us" << endl;
  299. break;
  300. case maMipMaps:
  301. Out << "Creating mipmaps ..." << endl;
  302. Time = GetTimeMicroseconds();
  303. ImGenerateMipMaps(&Img, 0, &Subs);
  304. Out << "Mipmaps created in: " << GetTimeMicroseconds() - Time << " us" << endl;
  305. ImFreeImageList(&Subs);
  306. break;
  307. case maClone:
  308. Out << "Cloning image ..." << endl;
  309. ImInitImage(&ImgClone);
  310. Time = GetTimeMicroseconds();
  311. ImCloneImage(&Img, &ImgClone);
  312. Out << "Image cloned in: " << GetTimeMicroseconds() - Time << " us" << endl;
  313. break;
  314. case maCopyRect:
  315. Out << "Copying rectangle ..." << endl;
  316. Time = GetTimeMicroseconds();
  317. ImCopyRect(&ImgClone, 0, 1500, 1500, 1500, &Img, 0, 0);
  318. Out << "Rectangle copied in: " << GetTimeMicroseconds() - Time << " us" << endl;
  319. break;
  320. case maStretchRect:
  321. Out << "Stretching rectangle (bicubic) ... " << endl;
  322. Time = GetTimeMicroseconds();
  323. ImStretchRect(&ImgClone, 0, 1500, 1500, 1500, &Img, 500, 500, 2000, 2000, rfBicubic);
  324. Out << "Rectangle stretched in: " << GetTimeMicroseconds() - Time << " us" << endl;
  325. ImFreeImage(&ImgClone);
  326. break;
  327. case maMapImage:
  328. Out << "Mapping image to existing palette ..." << endl;
  329. Time = GetTimeMicroseconds();
  330. ImMapImageToPalette(&Img, Pal, 256);
  331. Out << "Image mapped in: " << GetTimeMicroseconds() - Time << " us" << endl;
  332. ImFreePalette(&Pal);
  333. break;
  334. case maFill:
  335. Out << "Filling rectangle ..." << endl;
  336. Time = GetTimeMicroseconds();
  337. ImFillRect(&Img, 1500, 0, 1500, 1500, &FillColor);
  338. Out << "Rectangle filled in: " << GetTimeMicroseconds() - Time << " us" << endl;
  339. break;
  340. case maReplace:
  341. Out << "Replacing colors in rectagle ..." << endl;
  342. Time = GetTimeMicroseconds();
  343. ImReplaceColor(&Img, 0, 0, Img.Width, Img.Height, &FillColor, &NewColor);
  344. Out << "Colors replaced in: " << GetTimeMicroseconds() - Time << " us" << endl;
  345. break;
  346. case maSplit:
  347. Out << "Splitting image ..." << endl;
  348. Time = GetTimeMicroseconds();
  349. Subs = 0;
  350. ImSplitImage(&Img, &Subs, 300, 300, &XCount, &YCount, True, &FillColor);
  351. Out << "Image split in: " << GetTimeMicroseconds() - Time << " us" << endl;
  352. ImFreeImageList(&Subs);
  353. break;
  354. case maMakePal:
  355. Out << "Making palette for images ..." << endl;
  356. ImNewPalette(256, &Pal);
  357. ImInitImageList(1, &Subs);
  358. ImSetImageListElement(Subs, 0, &Img);
  359. Time = GetTimeMicroseconds();
  360. ImMakePaletteForImages(Subs, Pal, 256, False);
  361. Out << "Palette made in: " << GetTimeMicroseconds() - Time << " us" << endl;
  362. ImFreeImage(&Img);
  363. ImGetImageListElement(Subs, 0, &Img);
  364. ImFreeImageList(&Subs);
  365. break;
  366. case maRotate180:
  367. Out << "Rotating image 180 degrees CCW ... " << endl;
  368. Time = GetTimeMicroseconds();
  369. ImRotateImage(&Img, 180);
  370. Out << "Image rotated in: " << GetTimeMicroseconds() - Time << " us" << endl;
  371. break;
  372. case maRotate90:
  373. Out << "Rotating image 90 degrees CCW ... " << endl;
  374. Time = GetTimeMicroseconds();
  375. ImRotateImage(&Img, 90);
  376. Out << "Image rotated in: " << GetTimeMicroseconds() - Time << " us" << endl;
  377. break;
  378. }
  379. }
  380. /*
  381. Changes/Bug Fixes:
  382. -- 0.21 -----------------------------------------------------
  383. - Updated according to Object Pascal version of demo.
  384. -- 0.17 -----------------------------------------------------
  385. - made changes to be up to date with Pascal version
  386. (new tests, filtered resizing, ...)
  387. -- 0.15 -----------------------------------------------------
  388. - changed working with ImageDataList types because of change
  389. in header
  390. */