/src/FreeImage/Source/FreeImage/BitmapAccess.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 1210 lines · 781 code · 219 blank · 210 comment · 203 complexity · e6b90437b4e27d7d138f141d3f455c09 MD5 · raw file

  1. // ==========================================================
  2. // FreeImage implementation
  3. //
  4. // Design and implementation by
  5. // - Floris van den Berg (flvdberg@wxs.nl)
  6. // - Hervé Drolon (drolon@infonie.fr)
  7. // - Detlev Vendt (detlev.vendt@brillit.de)
  8. // - Petr Supina (psup@centrum.cz)
  9. // - Carsten Klein (c.klein@datagis.com)
  10. // - Mihail Naydenov (mnaydenov@users.sourceforge.net)
  11. //
  12. // This file is part of FreeImage 3
  13. //
  14. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  15. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  16. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  17. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  18. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  19. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  20. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  21. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  22. // THIS DISCLAIMER.
  23. //
  24. // Use at your own risk!
  25. // ==========================================================
  26. #ifdef _MSC_VER
  27. #pragma warning (disable : 4786) // identifier was truncated to 'number' characters
  28. #endif
  29. #include <stdlib.h>
  30. #if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__)
  31. #include <malloc.h>
  32. #endif // _WIN32 || _WIN64 || __MINGW32__
  33. #include "FreeImage.h"
  34. #include "FreeImageIO.h"
  35. #include "Utilities.h"
  36. #include "../Metadata/FreeImageTag.h"
  37. // ----------------------------------------------------------
  38. // Metadata definitions
  39. // ----------------------------------------------------------
  40. // helper for map<key, value> where value is a pointer to a FreeImage tag
  41. typedef std::map<std::string, FITAG*> TAGMAP;
  42. // helper for map<FREE_IMAGE_MDMODEL, TAGMAP*>
  43. typedef std::map<int, TAGMAP*> METADATAMAP;
  44. // helper for metadata iterator
  45. FI_STRUCT (METADATAHEADER) {
  46. long pos; // current position when iterating the map
  47. TAGMAP *tagmap; // pointer to the tag map
  48. };
  49. // ----------------------------------------------------------
  50. // FIBITMAP definition
  51. // ----------------------------------------------------------
  52. FI_STRUCT (FREEIMAGEHEADER) {
  53. FREE_IMAGE_TYPE type; // data type - bitmap, array of long, double, complex, etc
  54. unsigned red_mask; // bit layout of the red components
  55. unsigned green_mask; // bit layout of the green components
  56. unsigned blue_mask; // bit layout of the blue components
  57. RGBQUAD bkgnd_color; // background color used for RGB transparency
  58. BOOL transparent; // why another table? for easy transparency table retrieval!
  59. int transparency_count; // transparency could be stored in the palette, which is better
  60. BYTE transparent_table[256];// overall, but it requires quite some changes and it will render
  61. // FreeImage_GetTransparencyTable obsolete in its current form;
  62. FIICCPROFILE iccProfile; // space to hold ICC profile
  63. METADATAMAP *metadata; // contains a list of metadata models attached to the bitmap
  64. BOOL has_pixels; // FALSE if the FIBITMAP only contains the header and no pixel data
  65. FIBITMAP *thumbnail; // optionally contains a thumbnail attached to the bitmap
  66. //BYTE filler[1]; // fill to 32-bit alignment
  67. };
  68. // ----------------------------------------------------------
  69. // Memory allocation on a specified alignment boundary
  70. // ----------------------------------------------------------
  71. #if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
  72. void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
  73. assert(alignment == FIBITMAP_ALIGNMENT);
  74. return _aligned_malloc(amount, alignment);
  75. }
  76. void FreeImage_Aligned_Free(void* mem) {
  77. _aligned_free(mem);
  78. }
  79. #elif defined (__MINGW32__)
  80. void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
  81. assert(alignment == FIBITMAP_ALIGNMENT);
  82. return __mingw_aligned_malloc (amount, alignment);
  83. }
  84. void FreeImage_Aligned_Free(void* mem) {
  85. __mingw_aligned_free (mem);
  86. }
  87. #else
  88. void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
  89. assert(alignment == FIBITMAP_ALIGNMENT);
  90. /*
  91. In some rare situations, the malloc routines can return misaligned memory.
  92. The routine FreeImage_Aligned_Malloc allocates a bit more memory to do
  93. aligned writes. Normally, it *should* allocate "alignment" extra memory and then writes
  94. one dword back the true pointer. But if the memory manager returns a
  95. misaligned block that is less than a dword from the next alignment,
  96. then the writing back one dword will corrupt memory.
  97. For example, suppose that alignment is 16 and malloc returns the address 0xFFFF.
  98. 16 - 0xFFFF % 16 + 0xFFFF = 16 - 15 + 0xFFFF = 0x10000.
  99. Now, you subtract one dword from that and write and that will corrupt memory.
  100. That's why the code below allocates *two* alignments instead of one.
  101. */
  102. void* mem_real = malloc(amount + 2 * alignment);
  103. if(!mem_real) return NULL;
  104. char* mem_align = (char*)((unsigned long)(2 * alignment - (unsigned long)mem_real % (unsigned long)alignment) + (unsigned long)mem_real);
  105. *((long*)mem_align - 1) = (long)mem_real;
  106. return mem_align;
  107. }
  108. void FreeImage_Aligned_Free(void* mem) {
  109. free((void*)*((long*)mem - 1));
  110. }
  111. #endif // _WIN32 || _WIN64
  112. // ----------------------------------------------------------
  113. // DIB information functions
  114. // ----------------------------------------------------------
  115. /**
  116. Calculate the size of a FreeImage image.
  117. Align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary.
  118. @param header_only If TRUE, calculate a 'header only' FIBITMAP size, otherwise calculate a full FIBITMAP size
  119. @param width
  120. @param height
  121. @param bpp
  122. @see FreeImage_AllocateHeaderT
  123. */
  124. static size_t
  125. FreeImage_GetImageSizeHeader(BOOL header_only, unsigned width, unsigned height, unsigned bpp) {
  126. size_t dib_size = sizeof(FREEIMAGEHEADER);
  127. dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0);
  128. dib_size += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT;
  129. dib_size += sizeof(BITMAPINFOHEADER);
  130. // palette is aligned on a 16 bytes boundary
  131. dib_size += sizeof(RGBQUAD) * CalculateUsedPaletteEntries(bpp);
  132. dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0);
  133. if(!header_only) {
  134. const size_t header_size = dib_size;
  135. // pixels are aligned on a 16 bytes boundary
  136. dib_size += (size_t)CalculatePitch(CalculateLine(width, bpp)) * (size_t)height;
  137. // check for possible malloc overflow using a KISS integer overflow detection mechanism
  138. {
  139. /*
  140. The following constant take into account the additionnal memory used by
  141. aligned malloc functions as well as debug malloc functions.
  142. It is supposed here that using a (8 * FIBITMAP_ALIGNMENT) risk margin will be enough
  143. for the target compiler.
  144. */
  145. const double FIBITMAP_MAX_MEMORY = (double)((size_t)-1) - 8 * FIBITMAP_ALIGNMENT;
  146. const double dPitch = floor( ((double)bpp * width + 31.0) / 32.0 ) * 4.0;
  147. const double dImageSize = (double)header_size + dPitch * height;
  148. if(dImageSize != (double)dib_size) {
  149. // here, we are sure to encounter a malloc overflow: try to avoid it ...
  150. return 0;
  151. }
  152. if(dImageSize > FIBITMAP_MAX_MEMORY) {
  153. // avoid possible overflow inside C allocation functions
  154. return 0;
  155. }
  156. }
  157. }
  158. return dib_size;
  159. }
  160. FIBITMAP * DLL_CALLCONV
  161. FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
  162. FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP));
  163. if (bitmap != NULL) {
  164. width = abs(width);
  165. height = abs(height);
  166. // check pixel bit depth
  167. switch(type) {
  168. case FIT_BITMAP:
  169. switch(bpp) {
  170. case 1:
  171. case 4:
  172. case 8:
  173. case 16:
  174. case 24:
  175. case 32:
  176. break;
  177. default:
  178. bpp = 8;
  179. break;
  180. }
  181. break;
  182. case FIT_UINT16:
  183. bpp = 8 * sizeof(unsigned short);
  184. break;
  185. case FIT_INT16:
  186. bpp = 8 * sizeof(short);
  187. break;
  188. case FIT_UINT32:
  189. bpp = 8 * sizeof(DWORD);
  190. break;
  191. case FIT_INT32:
  192. bpp = 8 * sizeof(LONG);
  193. break;
  194. case FIT_FLOAT:
  195. bpp = 8 * sizeof(float);
  196. break;
  197. case FIT_DOUBLE:
  198. bpp = 8 * sizeof(double);
  199. break;
  200. case FIT_COMPLEX:
  201. bpp = 8 * sizeof(FICOMPLEX);
  202. break;
  203. case FIT_RGB16:
  204. bpp = 8 * sizeof(FIRGB16);
  205. break;
  206. case FIT_RGBA16:
  207. bpp = 8 * sizeof(FIRGBA16);
  208. break;
  209. case FIT_RGBF:
  210. bpp = 8 * sizeof(FIRGBF);
  211. break;
  212. case FIT_RGBAF:
  213. bpp = 8 * sizeof(FIRGBAF);
  214. break;
  215. default:
  216. free(bitmap);
  217. return NULL;
  218. }
  219. // calculate the size of a FreeImage image
  220. // align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
  221. // palette is aligned on a 16 bytes boundary
  222. // pixels are aligned on a 16 bytes boundary
  223. size_t dib_size = FreeImage_GetImageSizeHeader(header_only, width, height, bpp);
  224. if(dib_size == 0) {
  225. // memory allocation will fail (probably a malloc overflow)
  226. free(bitmap);
  227. return NULL;
  228. }
  229. bitmap->data = (BYTE *)FreeImage_Aligned_Malloc(dib_size * sizeof(BYTE), FIBITMAP_ALIGNMENT);
  230. if (bitmap->data != NULL) {
  231. memset(bitmap->data, 0, dib_size);
  232. // write out the FREEIMAGEHEADER
  233. FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)bitmap->data;
  234. fih->type = type;
  235. fih->red_mask = red_mask;
  236. fih->green_mask = green_mask;
  237. fih->blue_mask = blue_mask;
  238. memset(&fih->bkgnd_color, 0, sizeof(RGBQUAD));
  239. fih->transparent = FALSE;
  240. fih->transparency_count = 0;
  241. memset(fih->transparent_table, 0xff, 256);
  242. fih->has_pixels = header_only ? FALSE : TRUE;
  243. // initialize FIICCPROFILE link
  244. FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap);
  245. iccProfile->size = 0;
  246. iccProfile->data = 0;
  247. iccProfile->flags = 0;
  248. // initialize metadata models list
  249. fih->metadata = new(std::nothrow) METADATAMAP;
  250. // initialize attached thumbnail
  251. fih->thumbnail = NULL;
  252. // write out the BITMAPINFOHEADER
  253. BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(bitmap);
  254. bih->biSize = sizeof(BITMAPINFOHEADER);
  255. bih->biWidth = width;
  256. bih->biHeight = height;
  257. bih->biPlanes = 1;
  258. bih->biCompression = 0;
  259. bih->biBitCount = (WORD)bpp;
  260. bih->biClrUsed = CalculateUsedPaletteEntries(bpp);
  261. bih->biClrImportant = bih->biClrUsed;
  262. bih->biXPelsPerMeter = 2835; // 72 dpi
  263. bih->biYPelsPerMeter = 2835; // 72 dpi
  264. if(bpp == 8) {
  265. // build a default greyscale palette (very useful for image processing)
  266. RGBQUAD *pal = FreeImage_GetPalette(bitmap);
  267. for(int i = 0; i < 256; i++) {
  268. pal[i].rgbRed = (BYTE)i;
  269. pal[i].rgbGreen = (BYTE)i;
  270. pal[i].rgbBlue = (BYTE)i;
  271. }
  272. }
  273. return bitmap;
  274. }
  275. free(bitmap);
  276. }
  277. return NULL;
  278. }
  279. FIBITMAP * DLL_CALLCONV
  280. FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
  281. return FreeImage_AllocateHeaderT(header_only, FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask);
  282. }
  283. FIBITMAP * DLL_CALLCONV
  284. FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
  285. return FreeImage_AllocateHeaderT(FALSE, FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask);
  286. }
  287. FIBITMAP * DLL_CALLCONV
  288. FreeImage_AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
  289. return FreeImage_AllocateHeaderT(FALSE, type, width, height, bpp, red_mask, green_mask, blue_mask);
  290. }
  291. void DLL_CALLCONV
  292. FreeImage_Unload(FIBITMAP *dib) {
  293. if (NULL != dib) {
  294. if (NULL != dib->data) {
  295. // delete possible icc profile ...
  296. if (FreeImage_GetICCProfile(dib)->data)
  297. free(FreeImage_GetICCProfile(dib)->data);
  298. // delete metadata models
  299. METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
  300. for(METADATAMAP::iterator i = (*metadata).begin(); i != (*metadata).end(); i++) {
  301. TAGMAP *tagmap = (*i).second;
  302. if(tagmap) {
  303. for(TAGMAP::iterator j = tagmap->begin(); j != tagmap->end(); j++) {
  304. FITAG *tag = (*j).second;
  305. FreeImage_DeleteTag(tag);
  306. }
  307. delete tagmap;
  308. }
  309. }
  310. delete metadata;
  311. // delete embedded thumbnail
  312. FreeImage_Unload(FreeImage_GetThumbnail(dib));
  313. // delete bitmap ...
  314. FreeImage_Aligned_Free(dib->data);
  315. }
  316. free(dib); // ... and the wrapper
  317. }
  318. }
  319. // ----------------------------------------------------------
  320. FIBITMAP * DLL_CALLCONV
  321. FreeImage_Clone(FIBITMAP *dib) {
  322. if(!dib) return NULL;
  323. unsigned width = FreeImage_GetWidth(dib);
  324. unsigned height = FreeImage_GetHeight(dib);
  325. unsigned bpp = FreeImage_GetBPP(dib);
  326. // check for pixel availability ...
  327. BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE;
  328. // allocate a new dib
  329. FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, FreeImage_GetImageType(dib), width, height, bpp,
  330. FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib));
  331. if (new_dib) {
  332. // save ICC profile links
  333. FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib);
  334. FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib);
  335. // save metadata links
  336. METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
  337. METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata;
  338. // calculate the size of a FreeImage image
  339. // align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
  340. // palette is aligned on a 16 bytes boundary
  341. // pixels are aligned on a 16 bytes boundary
  342. size_t dib_size = FreeImage_GetImageSizeHeader(header_only, width, height, bpp);
  343. // copy the bitmap + internal pointers (remember to restore new_dib internal pointers later)
  344. memcpy(new_dib->data, dib->data, dib_size);
  345. // reset ICC profile link for new_dib
  346. memset(dst_iccProfile, 0, sizeof(FIICCPROFILE));
  347. // restore metadata link for new_dib
  348. ((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata;
  349. // reset thumbnail link for new_dib
  350. ((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL;
  351. // copy possible ICC profile
  352. FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size);
  353. dst_iccProfile->flags = src_iccProfile->flags;
  354. // copy metadata models
  355. for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
  356. int model = (*i).first;
  357. TAGMAP *src_tagmap = (*i).second;
  358. if(src_tagmap) {
  359. // create a metadata model
  360. TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP();
  361. if(dst_tagmap) {
  362. // fill the model
  363. for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
  364. std::string dst_key = (*j).first;
  365. FITAG *dst_tag = FreeImage_CloneTag( (*j).second );
  366. // assign key and tag value
  367. (*dst_tagmap)[dst_key] = dst_tag;
  368. }
  369. // assign model and tagmap
  370. (*dst_metadata)[model] = dst_tagmap;
  371. }
  372. }
  373. }
  374. // copy the thumbnail
  375. FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib));
  376. return new_dib;
  377. }
  378. return NULL;
  379. }
  380. // ----------------------------------------------------------
  381. FIBITMAP* DLL_CALLCONV
  382. FreeImage_GetThumbnail(FIBITMAP *dib) {
  383. return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->thumbnail : NULL;
  384. }
  385. BOOL DLL_CALLCONV
  386. FreeImage_SetThumbnail(FIBITMAP *dib, FIBITMAP *thumbnail) {
  387. if(dib == NULL) {
  388. return FALSE;
  389. }
  390. FIBITMAP *currentThumbnail = ((FREEIMAGEHEADER *)dib->data)->thumbnail;
  391. if(currentThumbnail == thumbnail) {
  392. return TRUE;
  393. }
  394. FreeImage_Unload(currentThumbnail);
  395. ((FREEIMAGEHEADER *)dib->data)->thumbnail = FreeImage_HasPixels(thumbnail) ? FreeImage_Clone(thumbnail) : NULL;
  396. return TRUE;
  397. }
  398. // ----------------------------------------------------------
  399. FREE_IMAGE_COLOR_TYPE DLL_CALLCONV
  400. FreeImage_GetColorType(FIBITMAP *dib) {
  401. RGBQUAD *rgb;
  402. const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
  403. // special bitmap type
  404. if(image_type != FIT_BITMAP) {
  405. switch(image_type) {
  406. case FIT_RGB16:
  407. case FIT_RGBF:
  408. return FIC_RGB;
  409. case FIT_RGBA16:
  410. case FIT_RGBAF:
  411. return FIC_RGBALPHA;
  412. }
  413. return FIC_MINISBLACK;
  414. }
  415. // standard image type
  416. switch (FreeImage_GetBPP(dib)) {
  417. case 1:
  418. {
  419. rgb = FreeImage_GetPalette(dib);
  420. if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0)) {
  421. rgb++;
  422. if ((rgb->rgbRed == 255) && (rgb->rgbGreen == 255) && (rgb->rgbBlue == 255))
  423. return FIC_MINISBLACK;
  424. }
  425. if ((rgb->rgbRed == 255) && (rgb->rgbGreen == 255) && (rgb->rgbBlue == 255)) {
  426. rgb++;
  427. if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0))
  428. return FIC_MINISWHITE;
  429. }
  430. return FIC_PALETTE;
  431. }
  432. case 4:
  433. case 8: // Check if the DIB has a color or a greyscale palette
  434. {
  435. int ncolors = FreeImage_GetColorsUsed(dib);
  436. int minisblack = 1;
  437. rgb = FreeImage_GetPalette(dib);
  438. for (int i = 0; i < ncolors; i++) {
  439. if ((rgb->rgbRed != rgb->rgbGreen) || (rgb->rgbRed != rgb->rgbBlue))
  440. return FIC_PALETTE;
  441. // The DIB has a color palette if the greyscale isn't a linear ramp
  442. // Take care of reversed grey images
  443. if (rgb->rgbRed != i) {
  444. if ((ncolors-i-1) != rgb->rgbRed)
  445. return FIC_PALETTE;
  446. else
  447. minisblack = 0;
  448. }
  449. rgb++;
  450. }
  451. return minisblack ? FIC_MINISBLACK : FIC_MINISWHITE;
  452. }
  453. case 16:
  454. case 24:
  455. return FIC_RGB;
  456. case 32:
  457. {
  458. if (FreeImage_GetICCProfile(dib)->flags & FIICC_COLOR_IS_CMYK)
  459. return FIC_CMYK;
  460. for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
  461. rgb = (RGBQUAD *)FreeImage_GetScanLine(dib, y);
  462. for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++)
  463. if (rgb[x].rgbReserved != 0xFF)
  464. return FIC_RGBALPHA;
  465. }
  466. return FIC_RGB;
  467. }
  468. default :
  469. return FIC_MINISBLACK;
  470. }
  471. }
  472. // ----------------------------------------------------------
  473. FREE_IMAGE_TYPE DLL_CALLCONV
  474. FreeImage_GetImageType(FIBITMAP *dib) {
  475. return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->type : FIT_UNKNOWN;
  476. }
  477. // ----------------------------------------------------------
  478. BOOL DLL_CALLCONV
  479. FreeImage_HasPixels(FIBITMAP *dib) {
  480. return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->has_pixels : FALSE;
  481. }
  482. // ----------------------------------------------------------
  483. unsigned DLL_CALLCONV
  484. FreeImage_GetRedMask(FIBITMAP *dib) {
  485. return dib ? ((FREEIMAGEHEADER *)dib->data)->red_mask : 0;
  486. }
  487. unsigned DLL_CALLCONV
  488. FreeImage_GetGreenMask(FIBITMAP *dib) {
  489. return dib ? ((FREEIMAGEHEADER *)dib->data)->green_mask : 0;
  490. }
  491. unsigned DLL_CALLCONV
  492. FreeImage_GetBlueMask(FIBITMAP *dib) {
  493. return dib ? ((FREEIMAGEHEADER *)dib->data)->blue_mask : 0;
  494. }
  495. // ----------------------------------------------------------
  496. BOOL DLL_CALLCONV
  497. FreeImage_HasBackgroundColor(FIBITMAP *dib) {
  498. if(dib) {
  499. RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color;
  500. return (bkgnd_color->rgbReserved != 0) ? TRUE : FALSE;
  501. }
  502. return FALSE;
  503. }
  504. BOOL DLL_CALLCONV
  505. FreeImage_GetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor) {
  506. if(dib && bkcolor) {
  507. if(FreeImage_HasBackgroundColor(dib)) {
  508. // get the background color
  509. RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color;
  510. memcpy(bkcolor, bkgnd_color, sizeof(RGBQUAD));
  511. // get the background index
  512. if(FreeImage_GetBPP(dib) == 8) {
  513. RGBQUAD *pal = FreeImage_GetPalette(dib);
  514. for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) {
  515. if(bkgnd_color->rgbRed == pal[i].rgbRed) {
  516. if(bkgnd_color->rgbGreen == pal[i].rgbGreen) {
  517. if(bkgnd_color->rgbBlue == pal[i].rgbBlue) {
  518. bkcolor->rgbReserved = (BYTE)i;
  519. return TRUE;
  520. }
  521. }
  522. }
  523. }
  524. }
  525. bkcolor->rgbReserved = 0;
  526. return TRUE;
  527. }
  528. }
  529. return FALSE;
  530. }
  531. BOOL DLL_CALLCONV
  532. FreeImage_SetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor) {
  533. if(dib) {
  534. RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color;
  535. if(bkcolor) {
  536. // set the background color
  537. memcpy(bkgnd_color, bkcolor, sizeof(RGBQUAD));
  538. // enable the file background color
  539. bkgnd_color->rgbReserved = 1;
  540. } else {
  541. // clear and disable the file background color
  542. memset(bkgnd_color, 0, sizeof(RGBQUAD));
  543. }
  544. return TRUE;
  545. }
  546. return FALSE;
  547. }
  548. // ----------------------------------------------------------
  549. BOOL DLL_CALLCONV
  550. FreeImage_IsTransparent(FIBITMAP *dib) {
  551. if(dib) {
  552. FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
  553. switch(image_type) {
  554. case FIT_BITMAP:
  555. if(FreeImage_GetBPP(dib) == 32) {
  556. if(FreeImage_GetColorType(dib) == FIC_RGBALPHA) {
  557. return TRUE;
  558. }
  559. } else {
  560. return ((FREEIMAGEHEADER *)dib->data)->transparent ? TRUE : FALSE;
  561. }
  562. break;
  563. case FIT_RGBA16:
  564. case FIT_RGBAF:
  565. return TRUE;
  566. default:
  567. break;
  568. }
  569. }
  570. return FALSE;
  571. }
  572. BYTE * DLL_CALLCONV
  573. FreeImage_GetTransparencyTable(FIBITMAP *dib) {
  574. return dib ? ((FREEIMAGEHEADER *)dib->data)->transparent_table : NULL;
  575. }
  576. void DLL_CALLCONV
  577. FreeImage_SetTransparent(FIBITMAP *dib, BOOL enabled) {
  578. if (dib) {
  579. if ((FreeImage_GetBPP(dib) <= 8) || (FreeImage_GetBPP(dib) == 32)) {
  580. ((FREEIMAGEHEADER *)dib->data)->transparent = enabled;
  581. } else {
  582. ((FREEIMAGEHEADER *)dib->data)->transparent = FALSE;
  583. }
  584. }
  585. }
  586. unsigned DLL_CALLCONV
  587. FreeImage_GetTransparencyCount(FIBITMAP *dib) {
  588. return dib ? ((FREEIMAGEHEADER *)dib->data)->transparency_count : 0;
  589. }
  590. void DLL_CALLCONV
  591. FreeImage_SetTransparencyTable(FIBITMAP *dib, BYTE *table, int count) {
  592. if (dib) {
  593. count = MIN(count, 256);
  594. if (FreeImage_GetBPP(dib) <= 8) {
  595. ((FREEIMAGEHEADER *)dib->data)->transparent = TRUE;
  596. ((FREEIMAGEHEADER *)dib->data)->transparency_count = count;
  597. if (table) {
  598. memcpy(((FREEIMAGEHEADER *)dib->data)->transparent_table, table, count);
  599. } else {
  600. memset(((FREEIMAGEHEADER *)dib->data)->transparent_table, 0xff, count);
  601. }
  602. }
  603. }
  604. }
  605. /** @brief Sets the index of the palette entry to be used as transparent color
  606. for the image specified. Does nothing on high color images.
  607. This method sets the index of the palette entry to be used as single transparent
  608. color for the image specified. This works on palletised images only and does
  609. nothing for high color images.
  610. Although it is possible for palletised images to have more than one transparent
  611. color, this method sets the palette entry specified as the single transparent
  612. color for the image. All other colors will be set to be non-transparent by this
  613. method.
  614. As with FreeImage_SetTransparencyTable(), this method also sets the image's
  615. transparency property to TRUE (as it is set and obtained by
  616. FreeImage_SetTransparent() and FreeImage_IsTransparent() respectively) for
  617. palletised images.
  618. @param dib Input image, whose transparent color is to be set.
  619. @param index The index of the palette entry to be set as transparent color.
  620. */
  621. void DLL_CALLCONV
  622. FreeImage_SetTransparentIndex(FIBITMAP *dib, int index) {
  623. if (dib) {
  624. int count = FreeImage_GetColorsUsed(dib);
  625. if (count) {
  626. BYTE *new_tt = (BYTE *)malloc(count * sizeof(BYTE));
  627. memset(new_tt, 0xFF, count);
  628. if ((index >= 0) && (index < count)) {
  629. new_tt[index] = 0x00;
  630. }
  631. FreeImage_SetTransparencyTable(dib, new_tt, count);
  632. free(new_tt);
  633. }
  634. }
  635. }
  636. /** @brief Returns the palette entry used as transparent color for the image
  637. specified. Works for palletised images only and returns -1 for high color
  638. images or if the image has no color set to be transparent.
  639. Although it is possible for palletised images to have more than one transparent
  640. color, this function always returns the index of the first palette entry, set
  641. to be transparent.
  642. @param dib Input image, whose transparent color is to be returned.
  643. @return Returns the index of the palette entry used as transparent color for
  644. the image specified or -1 if there is no transparent color found (e.g. the image
  645. is a high color image).
  646. */
  647. int DLL_CALLCONV
  648. FreeImage_GetTransparentIndex(FIBITMAP *dib) {
  649. int count = FreeImage_GetTransparencyCount(dib);
  650. BYTE *tt = FreeImage_GetTransparencyTable(dib);
  651. for (int i = 0; i < count; i++) {
  652. if (tt[i] == 0) {
  653. return i;
  654. }
  655. }
  656. return -1;
  657. }
  658. // ----------------------------------------------------------
  659. FIICCPROFILE * DLL_CALLCONV
  660. FreeImage_GetICCProfile(FIBITMAP *dib) {
  661. FIICCPROFILE *profile = (dib) ? (FIICCPROFILE *)&((FREEIMAGEHEADER *)dib->data)->iccProfile : NULL;
  662. return profile;
  663. }
  664. FIICCPROFILE * DLL_CALLCONV
  665. FreeImage_CreateICCProfile(FIBITMAP *dib, void *data, long size) {
  666. // clear the profile but preserve profile->flags
  667. FreeImage_DestroyICCProfile(dib);
  668. // create the new profile
  669. FIICCPROFILE *profile = FreeImage_GetICCProfile(dib);
  670. if(size && profile) {
  671. profile->data = malloc(size);
  672. if(profile->data) {
  673. memcpy(profile->data, data, profile->size = size);
  674. }
  675. }
  676. return profile;
  677. }
  678. void DLL_CALLCONV
  679. FreeImage_DestroyICCProfile(FIBITMAP *dib) {
  680. FIICCPROFILE *profile = FreeImage_GetICCProfile(dib);
  681. if(profile) {
  682. if (profile->data) {
  683. free (profile->data);
  684. }
  685. // clear the profile but preserve profile->flags
  686. profile->data = NULL;
  687. profile->size = 0;
  688. }
  689. }
  690. // ----------------------------------------------------------
  691. unsigned DLL_CALLCONV
  692. FreeImage_GetWidth(FIBITMAP *dib) {
  693. return dib ? FreeImage_GetInfoHeader(dib)->biWidth : 0;
  694. }
  695. unsigned DLL_CALLCONV
  696. FreeImage_GetHeight(FIBITMAP *dib) {
  697. return (dib) ? FreeImage_GetInfoHeader(dib)->biHeight : 0;
  698. }
  699. unsigned DLL_CALLCONV
  700. FreeImage_GetBPP(FIBITMAP *dib) {
  701. return dib ? FreeImage_GetInfoHeader(dib)->biBitCount : 0;
  702. }
  703. unsigned DLL_CALLCONV
  704. FreeImage_GetLine(FIBITMAP *dib) {
  705. return dib ? ((FreeImage_GetWidth(dib) * FreeImage_GetBPP(dib)) + 7) / 8 : 0;
  706. }
  707. unsigned DLL_CALLCONV
  708. FreeImage_GetPitch(FIBITMAP *dib) {
  709. return dib ? FreeImage_GetLine(dib) + 3 & ~3 : 0;
  710. }
  711. unsigned DLL_CALLCONV
  712. FreeImage_GetColorsUsed(FIBITMAP *dib) {
  713. return dib ? FreeImage_GetInfoHeader(dib)->biClrUsed : 0;
  714. }
  715. unsigned DLL_CALLCONV
  716. FreeImage_GetDIBSize(FIBITMAP *dib) {
  717. return (dib) ? sizeof(BITMAPINFOHEADER) + (FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD)) + (FreeImage_GetPitch(dib) * FreeImage_GetHeight(dib)) : 0;
  718. }
  719. RGBQUAD * DLL_CALLCONV
  720. FreeImage_GetPalette(FIBITMAP *dib) {
  721. return (dib && FreeImage_GetBPP(dib) < 16) ? (RGBQUAD *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL;
  722. }
  723. unsigned DLL_CALLCONV
  724. FreeImage_GetDotsPerMeterX(FIBITMAP *dib) {
  725. return (dib) ? FreeImage_GetInfoHeader(dib)->biXPelsPerMeter : 0;
  726. }
  727. unsigned DLL_CALLCONV
  728. FreeImage_GetDotsPerMeterY(FIBITMAP *dib) {
  729. return (dib) ? FreeImage_GetInfoHeader(dib)->biYPelsPerMeter : 0;
  730. }
  731. void DLL_CALLCONV
  732. FreeImage_SetDotsPerMeterX(FIBITMAP *dib, unsigned res) {
  733. if(dib) {
  734. FreeImage_GetInfoHeader(dib)->biXPelsPerMeter = res;
  735. }
  736. }
  737. void DLL_CALLCONV
  738. FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res) {
  739. if(dib) {
  740. FreeImage_GetInfoHeader(dib)->biYPelsPerMeter = res;
  741. }
  742. }
  743. BITMAPINFOHEADER * DLL_CALLCONV
  744. FreeImage_GetInfoHeader(FIBITMAP *dib) {
  745. if(!dib) return NULL;
  746. size_t lp = (size_t)dib->data + sizeof(FREEIMAGEHEADER);
  747. lp += (lp % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - lp % FIBITMAP_ALIGNMENT : 0);
  748. lp += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT;
  749. return (BITMAPINFOHEADER *)lp;
  750. }
  751. BITMAPINFO * DLL_CALLCONV
  752. FreeImage_GetInfo(FIBITMAP *dib) {
  753. return (BITMAPINFO *)FreeImage_GetInfoHeader(dib);
  754. }
  755. // ----------------------------------------------------------
  756. // Metadata routines
  757. // ----------------------------------------------------------
  758. FIMETADATA * DLL_CALLCONV
  759. FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag) {
  760. if(!dib)
  761. return NULL;
  762. // get the metadata model
  763. METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
  764. TAGMAP *tagmap = NULL;
  765. if( (*metadata).find(model) != (*metadata).end() ) {
  766. tagmap = (*metadata)[model];
  767. }
  768. if(tagmap) {
  769. // allocate a handle
  770. FIMETADATA *handle = (FIMETADATA *)malloc(sizeof(FIMETADATA));
  771. if(handle) {
  772. // calculate the size of a METADATAHEADER
  773. int header_size = sizeof(METADATAHEADER);
  774. handle->data = (BYTE *)malloc(header_size * sizeof(BYTE));
  775. if(handle->data) {
  776. memset(handle->data, 0, header_size * sizeof(BYTE));
  777. // write out the METADATAHEADER
  778. METADATAHEADER *mdh = (METADATAHEADER *)handle->data;
  779. mdh->pos = 1;
  780. mdh->tagmap = tagmap;
  781. // get the first element
  782. TAGMAP::iterator i = tagmap->begin();
  783. *tag = (*i).second;
  784. return handle;
  785. }
  786. free(handle);
  787. }
  788. }
  789. return NULL;
  790. }
  791. BOOL DLL_CALLCONV
  792. FreeImage_FindNextMetadata(FIMETADATA *mdhandle, FITAG **tag) {
  793. if(!mdhandle)
  794. return FALSE;
  795. METADATAHEADER *mdh = (METADATAHEADER *)mdhandle->data;
  796. TAGMAP *tagmap = mdh->tagmap;
  797. int current_pos = mdh->pos;
  798. int mapsize = (int)tagmap->size();
  799. if(current_pos < mapsize) {
  800. // get the tag element at position pos
  801. int count = 0;
  802. for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) {
  803. if(count == current_pos) {
  804. *tag = (*i).second;
  805. mdh->pos++;
  806. break;
  807. }
  808. count++;
  809. }
  810. return TRUE;
  811. }
  812. return FALSE;
  813. }
  814. void DLL_CALLCONV
  815. FreeImage_FindCloseMetadata(FIMETADATA *mdhandle) {
  816. if (NULL != mdhandle) { // delete the handle
  817. if (NULL != mdhandle->data) {
  818. free(mdhandle->data);
  819. }
  820. free(mdhandle); // ... and the wrapper
  821. }
  822. }
  823. // ----------------------------------------------------------
  824. BOOL DLL_CALLCONV
  825. FreeImage_CloneMetadata(FIBITMAP *dst, FIBITMAP *src) {
  826. if(!src || !dst) return FALSE;
  827. // get metadata links
  828. METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)src->data)->metadata;
  829. METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)dst->data)->metadata;
  830. // copy metadata models, *except* the FIMD_ANIMATION model
  831. for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
  832. int model = (*i).first;
  833. if(model == (int)FIMD_ANIMATION) {
  834. continue;
  835. }
  836. TAGMAP *src_tagmap = (*i).second;
  837. if(src_tagmap) {
  838. if( dst_metadata->find(model) != dst_metadata->end() ) {
  839. // destroy dst model
  840. FreeImage_SetMetadata((FREE_IMAGE_MDMODEL)model, dst, NULL, NULL);
  841. }
  842. // create a metadata model
  843. TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP();
  844. if(dst_tagmap) {
  845. // fill the model
  846. for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
  847. std::string dst_key = (*j).first;
  848. FITAG *dst_tag = FreeImage_CloneTag( (*j).second );
  849. // assign key and tag value
  850. (*dst_tagmap)[dst_key] = dst_tag;
  851. }
  852. // assign model and tagmap
  853. (*dst_metadata)[model] = dst_tagmap;
  854. }
  855. }
  856. }
  857. // clone resolution
  858. FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src));
  859. FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src));
  860. return TRUE;
  861. }
  862. // ----------------------------------------------------------
  863. BOOL DLL_CALLCONV
  864. FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag) {
  865. if(!dib)
  866. return FALSE;
  867. TAGMAP *tagmap = NULL;
  868. // get the metadata model
  869. METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
  870. METADATAMAP::iterator model_iterator = metadata->find(model);
  871. if (model_iterator != metadata->end()) {
  872. tagmap = model_iterator->second;
  873. }
  874. if(key != NULL) {
  875. if(!tagmap) {
  876. // this model, doesn't exist: create it
  877. tagmap = new(std::nothrow) TAGMAP();
  878. (*metadata)[model] = tagmap;
  879. }
  880. if(tag) {
  881. // first check the tag
  882. if(FreeImage_GetTagKey(tag) == NULL) {
  883. FreeImage_SetTagKey(tag, key);
  884. } else if(strcmp(key, FreeImage_GetTagKey(tag)) != 0) {
  885. // set the tag key
  886. FreeImage_SetTagKey(tag, key);
  887. }
  888. if(FreeImage_GetTagCount(tag) * FreeImage_TagDataWidth(FreeImage_GetTagType(tag)) != FreeImage_GetTagLength(tag)) {
  889. FreeImage_OutputMessageProc(FIF_UNKNOWN, "Invalid data count for tag '%s'", key);
  890. return FALSE;
  891. }
  892. // fill the tag ID if possible and if it's needed
  893. TagLib& tag_lib = TagLib::instance();
  894. switch(model) {
  895. case FIMD_IPTC:
  896. {
  897. int id = tag_lib.getTagID(TagLib::IPTC, key);
  898. /*
  899. if(id == -1) {
  900. FreeImage_OutputMessageProc(FIF_UNKNOWN, "IPTC: Invalid key '%s'", key);
  901. }
  902. */
  903. FreeImage_SetTagID(tag, (WORD)id);
  904. }
  905. break;
  906. default:
  907. break;
  908. }
  909. // delete existing tag
  910. FITAG *old_tag = (*tagmap)[key];
  911. if(old_tag) {
  912. FreeImage_DeleteTag(old_tag);
  913. }
  914. // create a new tag
  915. (*tagmap)[key] = FreeImage_CloneTag(tag);
  916. }
  917. else {
  918. // delete existing tag
  919. TAGMAP::iterator i = tagmap->find(key);
  920. if(i != tagmap->end()) {
  921. FITAG *old_tag = (*i).second;
  922. FreeImage_DeleteTag(old_tag);
  923. tagmap->erase(key);
  924. }
  925. }
  926. }
  927. else {
  928. // destroy the metadata model
  929. if(tagmap) {
  930. for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) {
  931. FITAG *tag = (*i).second;
  932. FreeImage_DeleteTag(tag);
  933. }
  934. delete tagmap;
  935. metadata->erase(model_iterator);
  936. }
  937. }
  938. return TRUE;
  939. }
  940. BOOL DLL_CALLCONV
  941. FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG **tag) {
  942. if(!dib || !key || !tag)
  943. return FALSE;
  944. TAGMAP *tagmap = NULL;
  945. *tag = NULL;
  946. // get the metadata model
  947. METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
  948. if(!(*metadata).empty()) {
  949. METADATAMAP::iterator model_iterator = metadata->find(model);
  950. if (model_iterator != metadata->end() ) {
  951. // this model exists : try to get the requested tag
  952. tagmap = model_iterator->second;
  953. TAGMAP::iterator tag_iterator = tagmap->find(key);
  954. if (tag_iterator != tagmap->end() ) {
  955. // get the requested tag
  956. *tag = tag_iterator->second;
  957. }
  958. }
  959. }
  960. return (*tag != NULL) ? TRUE : FALSE;
  961. }
  962. // ----------------------------------------------------------
  963. unsigned DLL_CALLCONV
  964. FreeImage_GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP *dib) {
  965. if(!dib)
  966. return FALSE;
  967. TAGMAP *tagmap = NULL;
  968. // get the metadata model
  969. METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
  970. if( (*metadata).find(model) != (*metadata).end() ) {
  971. tagmap = (*metadata)[model];
  972. }
  973. if(!tagmap) {
  974. // this model, doesn't exist: return
  975. return 0;
  976. }
  977. // get the tag count
  978. return (unsigned)tagmap->size();
  979. }
  980. // ----------------------------------------------------------