/src/FreeImage/Source/Utilities.h

https://bitbucket.org/cabalistic/ogredeps/ · C Header · 484 lines · 253 code · 75 blank · 156 comment · 27 complexity · d6aead212ee89668d950811ff104a310 MD5 · raw file

  1. // ==========================================================
  2. // Utility functions
  3. //
  4. // Design and implementation by
  5. // - Floris van den Berg (flvdberg@wxs.nl)
  6. // - Hervé Drolon <drolon@infonie.fr>
  7. // - Ryan Rubley (ryan@lostreality.org)
  8. //
  9. // This file is part of FreeImage 3
  10. //
  11. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  12. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  13. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  14. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  15. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  16. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  17. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  18. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  19. // THIS DISCLAIMER.
  20. //
  21. // Use at your own risk!
  22. // ==========================================================
  23. #ifndef UTILITIES_H
  24. #define UTILITIES_H
  25. // ==========================================================
  26. // Standard includes used by the library
  27. // ==========================================================
  28. #include <math.h>
  29. #include <stdlib.h>
  30. #include <memory.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <stdarg.h>
  34. #include <ctype.h>
  35. #include <assert.h>
  36. #include <errno.h>
  37. #include <float.h>
  38. #include <limits.h>
  39. #include <string>
  40. #include <list>
  41. #include <map>
  42. #include <set>
  43. #include <vector>
  44. #include <stack>
  45. #include <sstream>
  46. #include <algorithm>
  47. #include <limits>
  48. #include <memory>
  49. // ==========================================================
  50. // Bitmap palette and pixels alignment
  51. // ==========================================================
  52. #define FIBITMAP_ALIGNMENT 16 // We will use a 16 bytes alignment boundary
  53. // Memory allocation on a specified alignment boundary
  54. // defined in BitmapAccess.cpp
  55. void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment);
  56. void FreeImage_Aligned_Free(void* mem);
  57. #if defined(__cplusplus)
  58. extern "C" {
  59. #endif
  60. /**
  61. Allocate a FIBITMAP with possibly no pixel data
  62. (i.e. only header data and some or all metadata)
  63. @param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP
  64. @param type Image type
  65. @param width
  66. @param height
  67. @param bpp
  68. @param red_mask
  69. @param green_mask
  70. @param blue_mask
  71. @see FreeImage_AllocateT
  72. */
  73. DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int height, int bpp FI_DEFAULT(8), unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0));
  74. /**
  75. Allocate a FIBITMAP of type FIT_BITMAP, with possibly no pixel data
  76. (i.e. only header data and some or all metadata)
  77. @param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP
  78. @param width
  79. @param height
  80. @param bpp
  81. @param red_mask
  82. @param green_mask
  83. @param blue_mask
  84. @see FreeImage_Allocate
  85. */
  86. DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0));
  87. #if defined(__cplusplus)
  88. }
  89. #endif
  90. // ==========================================================
  91. // File I/O structs
  92. // ==========================================================
  93. // these structs are for file I/O and should not be confused with similar
  94. // structs in FreeImage.h which are for in-memory bitmap handling
  95. #ifdef _WIN32
  96. #pragma pack(push, 1)
  97. #else
  98. #pragma pack(1)
  99. #endif // _WIN32
  100. typedef struct tagFILE_RGBA {
  101. unsigned char r,g,b,a;
  102. } FILE_RGBA;
  103. typedef struct tagFILE_BGRA {
  104. unsigned char b,g,r,a;
  105. } FILE_BGRA;
  106. typedef struct tagFILE_RGB {
  107. unsigned char r,g,b;
  108. } FILE_RGB;
  109. typedef struct tagFILE_BGR {
  110. unsigned char b,g,r;
  111. } FILE_BGR;
  112. #ifdef _WIN32
  113. #pragma pack(pop)
  114. #else
  115. #pragma pack()
  116. #endif // _WIN32
  117. // ==========================================================
  118. // Template utility functions
  119. // ==========================================================
  120. /// Max function
  121. template <class T> T MAX(const T &a, const T &b) {
  122. return (a > b) ? a: b;
  123. }
  124. /// Min function
  125. template <class T> T MIN(const T &a, const T &b) {
  126. return (a < b) ? a: b;
  127. }
  128. /// INPLACESWAP adopted from codeguru.com
  129. template <class T> void INPLACESWAP(T& a, T& b) {
  130. a ^= b; b ^= a; a ^= b;
  131. }
  132. /// Clamp function
  133. template <class T> T CLAMP(const T &value, const T &min_value, const T &max_value) {
  134. return ((value < min_value) ? min_value : (value > max_value) ? max_value : value);
  135. }
  136. /** This procedure computes minimum min and maximum max
  137. of n numbers using only (3n/2) - 2 comparisons.
  138. min = L[i1] and max = L[i2].
  139. ref: Aho A.V., Hopcroft J.E., Ullman J.D.,
  140. The design and analysis of computer algorithms,
  141. Addison-Wesley, Reading, 1974.
  142. */
  143. template <class T> void
  144. MAXMIN(const T* L, long n, T& max, T& min) {
  145. long i1, i2, i, j;
  146. T x1, x2;
  147. long k1, k2;
  148. i1 = 0; i2 = 0; min = L[0]; max = L[0]; j = 0;
  149. if((n % 2) != 0) j = 1;
  150. for(i = j; i < n; i+= 2) {
  151. k1 = i; k2 = i+1;
  152. x1 = L[k1]; x2 = L[k2];
  153. if(x1 > x2) {
  154. k1 = k2; k2 = i;
  155. x1 = x2; x2 = L[k2];
  156. }
  157. if(x1 < min) {
  158. min = x1; i1 = k1;
  159. }
  160. if(x2 > max) {
  161. max = x2; i2 = k2;
  162. }
  163. }
  164. }
  165. // ==========================================================
  166. // Utility functions
  167. // ==========================================================
  168. #ifndef _WIN32
  169. inline char*
  170. i2a(unsigned i, char *a, unsigned r) {
  171. if (i/r > 0) a = i2a(i/r,a,r);
  172. *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
  173. return a+1;
  174. }
  175. /**
  176. Transforms integer i into an ascii string and stores the result in a;
  177. string is encoded in the base indicated by r.
  178. @param i Number to be converted
  179. @param a String result
  180. @param r Base of value; must be in the range 2 - 36
  181. @return Returns a
  182. */
  183. inline char *
  184. _itoa(int i, char *a, int r) {
  185. r = ((r < 2) || (r > 36)) ? 10 : r;
  186. if(i < 0) {
  187. *a = '-';
  188. *i2a(-i, a+1, r) = 0;
  189. }
  190. else *i2a(i, a, r) = 0;
  191. return a;
  192. }
  193. #endif // !_WIN32
  194. inline unsigned char
  195. HINIBBLE (unsigned char byte) {
  196. return byte & 0xF0;
  197. }
  198. inline unsigned char
  199. LOWNIBBLE (unsigned char byte) {
  200. return byte & 0x0F;
  201. }
  202. inline int
  203. CalculateUsedBits(int bits) {
  204. int bit_count = 0;
  205. unsigned bit = 1;
  206. for (unsigned i = 0; i < 32; i++) {
  207. if ((bits & bit) == bit) {
  208. bit_count++;
  209. }
  210. bit <<= 1;
  211. }
  212. return bit_count;
  213. }
  214. inline unsigned
  215. CalculateLine(unsigned width, unsigned bitdepth) {
  216. return (unsigned)( ((unsigned long long)width * bitdepth + 7) / 8 );
  217. }
  218. inline unsigned
  219. CalculatePitch(unsigned line) {
  220. return line + 3 & ~3;
  221. }
  222. inline unsigned
  223. CalculateUsedPaletteEntries(unsigned bit_count) {
  224. if ((bit_count >= 1) && (bit_count <= 8))
  225. return 1 << bit_count;
  226. return 0;
  227. }
  228. inline unsigned char *
  229. CalculateScanLine(unsigned char *bits, unsigned pitch, int scanline) {
  230. return (bits + (pitch * scanline));
  231. }
  232. // ----------------------------------------------------------
  233. /**
  234. Fast generic assign (faster than for loop)
  235. @param dst Destination pixel
  236. @param src Source pixel
  237. @param bytesperpixel # of bytes per pixel
  238. */
  239. inline void
  240. AssignPixel(BYTE* dst, const BYTE* src, unsigned bytesperpixel) {
  241. switch (bytesperpixel) {
  242. case 1: // FIT_BITMAP (8-bit)
  243. *dst = *src;
  244. break;
  245. case 2: // FIT_UINT16 / FIT_INT16 / 16-bit
  246. *(reinterpret_cast<WORD*>(dst)) = *(reinterpret_cast<const WORD*> (src));
  247. break;
  248. case 3: // FIT_BITMAP (24-bit)
  249. *(reinterpret_cast<WORD*>(dst)) = *(reinterpret_cast<const WORD*> (src));
  250. dst[2] = src[2];
  251. break;
  252. case 4: // FIT_BITMAP (32-bit) / FIT_UINT32 / FIT_INT32 / FIT_FLOAT
  253. *(reinterpret_cast<DWORD*>(dst)) = *(reinterpret_cast<const DWORD*> (src));
  254. break;
  255. case 6: // FIT_RGB16 (3 x 16-bit)
  256. *(reinterpret_cast<DWORD*>(dst)) = *(reinterpret_cast<const DWORD*> (src));
  257. *(reinterpret_cast<WORD*>(dst + 4)) = *(reinterpret_cast<const WORD*> (src + 4));
  258. break;
  259. // the rest can be speeded up with int64
  260. case 8: // FIT_RGBA16 (4 x 16-bit)
  261. *(reinterpret_cast<DWORD*>(dst)) = *(reinterpret_cast<const DWORD*> (src));
  262. *(reinterpret_cast<DWORD*>(dst + 4)) = *(reinterpret_cast<const DWORD*> (src + 4));
  263. break;
  264. case 12: // FIT_RGBF (3 x 32-bit IEEE floating point)
  265. *(reinterpret_cast<float*>(dst)) = *(reinterpret_cast<const float*> (src));
  266. *(reinterpret_cast<float*>(dst + 4)) = *(reinterpret_cast<const float*> (src + 4));
  267. *(reinterpret_cast<float*>(dst + 8)) = *(reinterpret_cast<const float*> (src + 8));
  268. break;
  269. case 16: // FIT_RGBAF (4 x 32-bit IEEE floating point)
  270. *(reinterpret_cast<float*>(dst)) = *(reinterpret_cast<const float*> (src));
  271. *(reinterpret_cast<float*>(dst + 4)) = *(reinterpret_cast<const float*> (src + 4));
  272. *(reinterpret_cast<float*>(dst + 8)) = *(reinterpret_cast<const float*> (src + 8));
  273. *(reinterpret_cast<float*>(dst + 12)) = *(reinterpret_cast<const float*> (src + 12));
  274. break;
  275. default:
  276. assert(FALSE);
  277. }
  278. }
  279. /**
  280. Swap red and blue channels in a 24- or 32-bit dib.
  281. @return Returns TRUE if successful, returns FALSE otherwise
  282. @see See definition in Conversion.cpp
  283. */
  284. BOOL SwapRedBlue32(FIBITMAP* dib);
  285. /**
  286. Inplace convert CMYK to RGBA.(8- and 16-bit).
  287. Alpha is filled with the first extra channel if any or white otherwise.
  288. @return Returns TRUE if successful, returns FALSE otherwise
  289. @see See definition in Conversion.cpp
  290. */
  291. BOOL ConvertCMYKtoRGBA(FIBITMAP* dib);
  292. /**
  293. Inplace convert CIELab to RGBA (8- and 16-bit).
  294. @return Returns TRUE if successful, returns FALSE otherwise
  295. @see See definition in Conversion.cpp
  296. */
  297. BOOL ConvertLABtoRGB(FIBITMAP* dib);
  298. /**
  299. RGBA to RGB conversion
  300. @see See definition in Conversion.cpp
  301. */
  302. FIBITMAP* RemoveAlphaChannel(FIBITMAP* dib);
  303. // ==========================================================
  304. // Big Endian / Little Endian utility functions
  305. // ==========================================================
  306. inline WORD
  307. __SwapUInt16(WORD arg) {
  308. #if defined(_MSC_VER) && _MSC_VER >= 1310
  309. return _byteswap_ushort(arg);
  310. #elif defined(__i386__) && defined(__GNUC__)
  311. __asm__("xchgb %b0, %h0" : "+q" (arg));
  312. return arg;
  313. #elif defined(__ppc__) && defined(__GNUC__)
  314. WORD result;
  315. __asm__("lhbrx %0,0,%1" : "=r" (result) : "r" (&arg), "m" (arg));
  316. return result;
  317. #else
  318. // swap bytes
  319. WORD result;
  320. result = ((arg << 8) & 0xFF00) | ((arg >> 8) & 0x00FF);
  321. return result;
  322. #endif
  323. }
  324. inline DWORD
  325. __SwapUInt32(DWORD arg) {
  326. #if defined(_MSC_VER) && _MSC_VER >= 1310
  327. return _byteswap_ulong(arg);
  328. #elif defined(__i386__) && defined(__GNUC__)
  329. __asm__("bswap %0" : "+r" (arg));
  330. return arg;
  331. #elif defined(__ppc__) && defined(__GNUC__)
  332. DWORD result;
  333. __asm__("lwbrx %0,0,%1" : "=r" (result) : "r" (&arg), "m" (arg));
  334. return result;
  335. #else
  336. // swap words then bytes
  337. DWORD result;
  338. result = ((arg & 0x000000FF) << 24) | ((arg & 0x0000FF00) << 8) | ((arg >> 8) & 0x0000FF00) | ((arg >> 24) & 0x000000FF);
  339. return result;
  340. #endif
  341. }
  342. /**
  343. for later use ...
  344. inline uint64_t
  345. SwapInt64(uint64_t arg) {
  346. #if defined(_MSC_VER) && _MSC_VER >= 1310
  347. return _byteswap_uint64(arg);
  348. #else
  349. union Swap {
  350. uint64_t sv;
  351. uint32_t ul[2];
  352. } tmp, result;
  353. tmp.sv = arg;
  354. result.ul[0] = SwapInt32(tmp.ul[1]);
  355. result.ul[1] = SwapInt32(tmp.ul[0]);
  356. return result.sv;
  357. #endif
  358. }
  359. */
  360. inline void
  361. SwapShort(WORD *sp) {
  362. *sp = __SwapUInt16(*sp);
  363. }
  364. inline void
  365. SwapLong(DWORD *lp) {
  366. *lp = __SwapUInt32(*lp);
  367. }
  368. // ==========================================================
  369. // Greyscale and color conversion
  370. // ==========================================================
  371. /**
  372. Extract the luminance channel L from a RGBF image.
  373. Luminance is calculated from the sRGB model using a D65 white point, using the Rec.709 formula :
  374. L = ( 0.2126 * r ) + ( 0.7152 * g ) + ( 0.0722 * b )
  375. Reference :
  376. A Standard Default Color Space for the Internet - sRGB.
  377. [online] http://www.w3.org/Graphics/Color/sRGB
  378. */
  379. #define LUMA_REC709(r, g, b) (0.2126F * r + 0.7152F * g + 0.0722F * b)
  380. #define GREY(r, g, b) (BYTE)LUMA_REC709(r, g, b)
  381. /*
  382. #define GREY(r, g, b) (BYTE)(((WORD)r * 77 + (WORD)g * 150 + (WORD)b * 29) >> 8) // .299R + .587G + .114B
  383. */
  384. /*
  385. #define GREY(r, g, b) (BYTE)(((WORD)r * 169 + (WORD)g * 256 + (WORD)b * 87) >> 9) // .33R + 0.5G + .17B
  386. */
  387. #define RGB565(b, g, r) ((((b) >> 3) << FI16_565_BLUE_SHIFT) | (((g) >> 2) << FI16_565_GREEN_SHIFT) | (((r) >> 3) << FI16_565_RED_SHIFT))
  388. #define RGB555(b, g, r) ((((b) >> 3) << FI16_555_BLUE_SHIFT) | (((g) >> 3) << FI16_555_GREEN_SHIFT) | (((r) >> 3) << FI16_555_RED_SHIFT))
  389. #define FORMAT_RGB565(dib) ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) &&(FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) &&(FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK))
  390. #define RGBQUAD_TO_WORD(dib, color) (FORMAT_RGB565(dib) ? RGB565((color)->rgbBlue, (color)->rgbGreen, (color)->rgbRed) : RGB555((color)->rgbBlue, (color)->rgbGreen, (color)->rgbRed))
  391. #define CREATE_GREYSCALE_PALETTE(palette, entries) \
  392. for (unsigned i = 0, v = 0; i < entries; i++, v += 0x00FFFFFF / (entries - 1)) { \
  393. ((unsigned *)palette)[i] = v; \
  394. }
  395. #define CREATE_GREYSCALE_PALETTE_REVERSE(palette, entries) \
  396. for (unsigned i = 0, v = 0x00FFFFFF; i < entries; i++, v -= (0x00FFFFFF / (entries - 1))) { \
  397. ((unsigned *)palette)[i] = v; \
  398. }
  399. // ==========================================================
  400. // Generic error messages
  401. // ==========================================================
  402. static const char *FI_MSG_ERROR_MEMORY = "Memory allocation failed";
  403. static const char *FI_MSG_ERROR_DIB_MEMORY = "DIB allocation failed, maybe caused by an invalid image size or by a lack of memory";
  404. static const char *FI_MSG_ERROR_PARSING = "Parsing error";
  405. static const char *FI_MSG_ERROR_MAGIC_NUMBER = "Invalid magic number";
  406. static const char *FI_MSG_ERROR_UNSUPPORTED_FORMAT = "Unsupported format";
  407. static const char *FI_MSG_ERROR_UNSUPPORTED_COMPRESSION = "Unsupported compression type";
  408. static const char *FI_MSG_WARNING_INVALID_THUMBNAIL = "Warning: attached thumbnail cannot be written to output file (invalid format) - Thumbnail saving aborted";
  409. #endif // UTILITIES_H