/src/FreeImage/Source/FreeImageToolkit/Colors.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 967 lines · 567 code · 91 blank · 309 comment · 181 complexity · bb299c635590762e09c7c646947d2cce MD5 · raw file

  1. // ==========================================================
  2. // Color manipulation routines
  3. //
  4. // Design and implementation by
  5. // - Hervé Drolon (drolon@infonie.fr)
  6. // - Carsten Klein (c.klein@datagis.com)
  7. // - Mihail Naydenov (mnaydenov@users.sourceforge.net)
  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. #include "FreeImage.h"
  24. #include "Utilities.h"
  25. // ----------------------------------------------------------
  26. // Macros + structures
  27. // ----------------------------------------------------------
  28. #define GET_HI_NIBBLE(byte) ((byte) >> 4)
  29. #define SET_HI_NIBBLE(byte, n) byte &= 0x0F, byte |= ((n) << 4)
  30. #define GET_LO_NIBBLE(byte) ((byte) & 0x0F)
  31. #define SET_LO_NIBBLE(byte, n) byte &= 0xF0, byte |= ((n) & 0x0F)
  32. #define GET_NIBBLE(cn, byte) ((cn) ? (GET_HI_NIBBLE(byte)) : (GET_LO_NIBBLE(byte)))
  33. #define SET_NIBBLE(cn, byte, n) if (cn) SET_HI_NIBBLE(byte, n); else SET_LO_NIBBLE(byte, n)
  34. // ----------------------------------------------------------
  35. /** @brief Inverts each pixel data.
  36. @param src Input image to be processed.
  37. @return Returns TRUE if successful, FALSE otherwise.
  38. */
  39. BOOL DLL_CALLCONV
  40. FreeImage_Invert(FIBITMAP *src) {
  41. if (!FreeImage_HasPixels(src)) return FALSE;
  42. unsigned i, x, y, k;
  43. const unsigned width = FreeImage_GetWidth(src);
  44. const unsigned height = FreeImage_GetHeight(src);
  45. const unsigned bpp = FreeImage_GetBPP(src);
  46. FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
  47. if(image_type == FIT_BITMAP) {
  48. switch(bpp) {
  49. case 1 :
  50. case 4 :
  51. case 8 :
  52. {
  53. // if the dib has a colormap, just invert it
  54. // else, keep the linear grayscale
  55. if (FreeImage_GetColorType(src) == FIC_PALETTE) {
  56. RGBQUAD *pal = FreeImage_GetPalette(src);
  57. for(i = 0; i < FreeImage_GetColorsUsed(src); i++) {
  58. pal[i].rgbRed = 255 - pal[i].rgbRed;
  59. pal[i].rgbGreen = 255 - pal[i].rgbGreen;
  60. pal[i].rgbBlue = 255 - pal[i].rgbBlue;
  61. }
  62. } else {
  63. for(y = 0; y < height; y++) {
  64. BYTE *bits = FreeImage_GetScanLine(src, y);
  65. for (x = 0; x < FreeImage_GetLine(src); x++) {
  66. bits[x] = ~bits[x];
  67. }
  68. }
  69. }
  70. break;
  71. }
  72. case 24 :
  73. case 32 :
  74. {
  75. // Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
  76. const unsigned bytespp = FreeImage_GetLine(src) / width;
  77. for(y = 0; y < height; y++) {
  78. BYTE *bits = FreeImage_GetScanLine(src, y);
  79. for(x = 0; x < width; x++) {
  80. for(k = 0; k < bytespp; k++) {
  81. bits[k] = ~bits[k];
  82. }
  83. bits += bytespp;
  84. }
  85. }
  86. break;
  87. }
  88. default:
  89. return FALSE;
  90. }
  91. }
  92. else if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
  93. // Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit)
  94. const unsigned wordspp = (FreeImage_GetLine(src) / width) / sizeof(WORD);
  95. for(y = 0; y < height; y++) {
  96. WORD *bits = (WORD*)FreeImage_GetScanLine(src, y);
  97. for(x = 0; x < width; x++) {
  98. for(k = 0; k < wordspp; k++) {
  99. bits[k] = ~bits[k];
  100. }
  101. bits += wordspp;
  102. }
  103. }
  104. }
  105. else {
  106. // anything else ...
  107. return FALSE;
  108. }
  109. return TRUE;
  110. }
  111. /** @brief Perfoms an histogram transformation on a 8, 24 or 32-bit image
  112. according to the values of a lookup table (LUT).
  113. The transformation is done as follows.<br>
  114. Image 8-bit : if the image has a color palette, the LUT is applied to this palette,
  115. otherwise, it is applied to the grey values.<br>
  116. Image 24-bit & 32-bit : if channel == FICC_RGB, the same LUT is applied to each color
  117. plane (R,G, and B). Otherwise, the LUT is applied to the specified channel only.
  118. @param src Input image to be processed.
  119. @param LUT Lookup table. <b>The size of 'LUT' is assumed to be 256.</b>
  120. @param channel The color channel to be processed (only used with 24 & 32-bit DIB).
  121. @return Returns TRUE if successful, FALSE otherwise.
  122. @see FREE_IMAGE_COLOR_CHANNEL
  123. */
  124. BOOL DLL_CALLCONV
  125. FreeImage_AdjustCurve(FIBITMAP *src, BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel) {
  126. unsigned x, y;
  127. BYTE *bits = NULL;
  128. if(!FreeImage_HasPixels(src) || !LUT || (FreeImage_GetImageType(src) != FIT_BITMAP))
  129. return FALSE;
  130. int bpp = FreeImage_GetBPP(src);
  131. if((bpp != 8) && (bpp != 24) && (bpp != 32))
  132. return FALSE;
  133. // apply the LUT
  134. switch(bpp) {
  135. case 8 :
  136. {
  137. // if the dib has a colormap, apply the LUT to it
  138. // else, apply the LUT to pixel values
  139. if(FreeImage_GetColorType(src) == FIC_PALETTE) {
  140. RGBQUAD *rgb = FreeImage_GetPalette(src);
  141. for (unsigned pal = 0; pal < FreeImage_GetColorsUsed(src); pal++) {
  142. rgb->rgbRed = LUT[rgb->rgbRed];
  143. rgb->rgbGreen = LUT[rgb->rgbGreen];
  144. rgb->rgbBlue = LUT[rgb->rgbBlue];
  145. rgb++;
  146. }
  147. }
  148. else {
  149. for(y = 0; y < FreeImage_GetHeight(src); y++) {
  150. bits = FreeImage_GetScanLine(src, y);
  151. for(x = 0; x < FreeImage_GetWidth(src); x++) {
  152. bits[x] = LUT[ bits[x] ];
  153. }
  154. }
  155. }
  156. break;
  157. }
  158. case 24 :
  159. case 32 :
  160. {
  161. int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
  162. switch(channel) {
  163. case FICC_RGB :
  164. for(y = 0; y < FreeImage_GetHeight(src); y++) {
  165. bits = FreeImage_GetScanLine(src, y);
  166. for(x = 0; x < FreeImage_GetWidth(src); x++) {
  167. bits[FI_RGBA_BLUE] = LUT[ bits[FI_RGBA_BLUE] ]; // B
  168. bits[FI_RGBA_GREEN] = LUT[ bits[FI_RGBA_GREEN] ]; // G
  169. bits[FI_RGBA_RED] = LUT[ bits[FI_RGBA_RED] ]; // R
  170. bits += bytespp;
  171. }
  172. }
  173. break;
  174. case FICC_BLUE :
  175. for(y = 0; y < FreeImage_GetHeight(src); y++) {
  176. bits = FreeImage_GetScanLine(src, y);
  177. for(x = 0; x < FreeImage_GetWidth(src); x++) {
  178. bits[FI_RGBA_BLUE] = LUT[ bits[FI_RGBA_BLUE] ]; // B
  179. bits += bytespp;
  180. }
  181. }
  182. break;
  183. case FICC_GREEN :
  184. for(y = 0; y < FreeImage_GetHeight(src); y++) {
  185. bits = FreeImage_GetScanLine(src, y);
  186. for(x = 0; x < FreeImage_GetWidth(src); x++) {
  187. bits[FI_RGBA_GREEN] = LUT[ bits[FI_RGBA_GREEN] ]; // G
  188. bits += bytespp;
  189. }
  190. }
  191. break;
  192. case FICC_RED :
  193. for(y = 0; y < FreeImage_GetHeight(src); y++) {
  194. bits = FreeImage_GetScanLine(src, y);
  195. for(x = 0; x < FreeImage_GetWidth(src); x++) {
  196. bits[FI_RGBA_RED] = LUT[ bits[FI_RGBA_RED] ]; // R
  197. bits += bytespp;
  198. }
  199. }
  200. break;
  201. case FICC_ALPHA :
  202. if(32 == bpp) {
  203. for(y = 0; y < FreeImage_GetHeight(src); y++) {
  204. bits = FreeImage_GetScanLine(src, y);
  205. for(x = 0; x < FreeImage_GetWidth(src); x++) {
  206. bits[FI_RGBA_ALPHA] = LUT[ bits[FI_RGBA_ALPHA] ]; // A
  207. bits += bytespp;
  208. }
  209. }
  210. }
  211. break;
  212. default:
  213. break;
  214. }
  215. break;
  216. }
  217. }
  218. return TRUE;
  219. }
  220. /** @brief Performs gamma correction on a 8, 24 or 32-bit image.
  221. @param src Input image to be processed.
  222. @param gamma Gamma value to use. A value of 1.0 leaves the image alone,
  223. less than one darkens it, and greater than one lightens it.
  224. @return Returns TRUE if successful, FALSE otherwise.
  225. */
  226. BOOL DLL_CALLCONV
  227. FreeImage_AdjustGamma(FIBITMAP *src, double gamma) {
  228. BYTE LUT[256]; // Lookup table
  229. if(!FreeImage_HasPixels(src) || (gamma <= 0))
  230. return FALSE;
  231. // Build the lookup table
  232. double exponent = 1 / gamma;
  233. double v = 255.0 * (double)pow((double)255, -exponent);
  234. for(int i = 0; i < 256; i++) {
  235. double color = (double)pow((double)i, exponent) * v;
  236. if(color > 255)
  237. color = 255;
  238. LUT[i] = (BYTE)floor(color + 0.5);
  239. }
  240. // Apply the gamma correction
  241. return FreeImage_AdjustCurve(src, LUT, FICC_RGB);
  242. }
  243. /** @brief Adjusts the brightness of a 8, 24 or 32-bit image by a certain amount.
  244. @param src Input image to be processed.
  245. @param percentage Where -100 <= percentage <= 100<br>
  246. A value 0 means no change, less than 0 will make the image darker
  247. and greater than 0 will make the image brighter.
  248. @return Returns TRUE if successful, FALSE otherwise.
  249. */
  250. BOOL DLL_CALLCONV
  251. FreeImage_AdjustBrightness(FIBITMAP *src, double percentage) {
  252. BYTE LUT[256]; // Lookup table
  253. double value;
  254. if(!FreeImage_HasPixels(src))
  255. return FALSE;
  256. // Build the lookup table
  257. const double scale = (100 + percentage) / 100;
  258. for(int i = 0; i < 256; i++) {
  259. value = i * scale;
  260. value = MAX(0.0, MIN(value, 255.0));
  261. LUT[i] = (BYTE)floor(value + 0.5);
  262. }
  263. return FreeImage_AdjustCurve(src, LUT, FICC_RGB);
  264. }
  265. /** @brief Adjusts the contrast of a 8, 24 or 32-bit image by a certain amount.
  266. @param src Input image to be processed.
  267. @param percentage Where -100 <= percentage <= 100<br>
  268. A value 0 means no change, less than 0 will decrease the contrast
  269. and greater than 0 will increase the contrast of the image.
  270. @return Returns TRUE if successful, FALSE otherwise.
  271. */
  272. BOOL DLL_CALLCONV
  273. FreeImage_AdjustContrast(FIBITMAP *src, double percentage) {
  274. BYTE LUT[256]; // Lookup table
  275. double value;
  276. if(!FreeImage_HasPixels(src))
  277. return FALSE;
  278. // Build the lookup table
  279. const double scale = (100 + percentage) / 100;
  280. for(int i = 0; i < 256; i++) {
  281. value = 128 + (i - 128) * scale;
  282. value = MAX(0.0, MIN(value, 255.0));
  283. LUT[i] = (BYTE)floor(value + 0.5);
  284. }
  285. return FreeImage_AdjustCurve(src, LUT, FICC_RGB);
  286. }
  287. /** @brief Computes image histogram
  288. For 24-bit and 32-bit images, histogram can be computed from red, green, blue and
  289. black channels. For 8-bit images, histogram is computed from the black channel. Other
  290. bit depth is not supported (nothing is done).
  291. @param src Input image to be processed.
  292. @param histo Histogram array to fill. <b>The size of 'histo' is assumed to be 256.</b>
  293. @param channel Color channel to use
  294. @return Returns TRUE if succesful, returns FALSE if the image bit depth isn't supported.
  295. */
  296. BOOL DLL_CALLCONV
  297. FreeImage_GetHistogram(FIBITMAP *src, DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel) {
  298. BYTE pixel;
  299. BYTE *bits = NULL;
  300. unsigned x, y;
  301. if(!FreeImage_HasPixels(src) || !histo) return FALSE;
  302. unsigned width = FreeImage_GetWidth(src);
  303. unsigned height = FreeImage_GetHeight(src);
  304. unsigned bpp = FreeImage_GetBPP(src);
  305. if(bpp == 8) {
  306. // clear histogram array
  307. memset(histo, 0, 256 * sizeof(DWORD));
  308. // compute histogram for black channel
  309. for(y = 0; y < height; y++) {
  310. bits = FreeImage_GetScanLine(src, y);
  311. for(x = 0; x < width; x++) {
  312. // get pixel value
  313. pixel = bits[x];
  314. histo[pixel]++;
  315. }
  316. }
  317. return TRUE;
  318. }
  319. else if((bpp == 24) || (bpp == 32)) {
  320. int bytespp = bpp / 8; // bytes / pixel
  321. // clear histogram array
  322. memset(histo, 0, 256 * sizeof(DWORD));
  323. switch(channel) {
  324. case FICC_RED:
  325. // compute histogram for red channel
  326. for(y = 0; y < height; y++) {
  327. bits = FreeImage_GetScanLine(src, y);
  328. for(x = 0; x < width; x++) {
  329. pixel = bits[FI_RGBA_RED]; // R
  330. histo[pixel]++;
  331. bits += bytespp;
  332. }
  333. }
  334. return TRUE;
  335. case FICC_GREEN:
  336. // compute histogram for green channel
  337. for(y = 0; y < height; y++) {
  338. bits = FreeImage_GetScanLine(src, y);
  339. for(x = 0; x < width; x++) {
  340. pixel = bits[FI_RGBA_GREEN]; // G
  341. histo[pixel]++;
  342. bits += bytespp;
  343. }
  344. }
  345. return TRUE;
  346. case FICC_BLUE:
  347. // compute histogram for blue channel
  348. for(y = 0; y < height; y++) {
  349. bits = FreeImage_GetScanLine(src, y);
  350. for(x = 0; x < width; x++) {
  351. pixel = bits[FI_RGBA_BLUE]; // B
  352. histo[pixel]++;
  353. bits += bytespp;
  354. }
  355. }
  356. return TRUE;
  357. case FICC_BLACK:
  358. case FICC_RGB:
  359. // compute histogram for black channel
  360. for(y = 0; y < height; y++) {
  361. bits = FreeImage_GetScanLine(src, y);
  362. for(x = 0; x < width; x++) {
  363. // RGB to GREY conversion
  364. pixel = GREY(bits[FI_RGBA_RED], bits[FI_RGBA_GREEN], bits[FI_RGBA_BLUE]);
  365. histo[pixel]++;
  366. bits += bytespp;
  367. }
  368. }
  369. return TRUE;
  370. default:
  371. return FALSE;
  372. }
  373. }
  374. return FALSE;
  375. }
  376. // ----------------------------------------------------------
  377. /** @brief Creates a lookup table to be used with FreeImage_AdjustCurve() which
  378. may adjust brightness and contrast, correct gamma and invert the image with a
  379. single call to FreeImage_AdjustCurve().
  380. This function creates a lookup table to be used with FreeImage_AdjustCurve()
  381. which may adjust brightness and contrast, correct gamma and invert the image
  382. with a single call to FreeImage_AdjustCurve(). If more than one of these image
  383. display properties need to be adjusted, using a combined lookup table should be
  384. preferred over calling each adjustment function separately. That's particularly
  385. true for huge images or if performance is an issue. Then, the expensive process
  386. of iterating over all pixels of an image is performed only once and not up to
  387. four times.
  388. Furthermore, the lookup table created does not depend on the order, in which
  389. each single adjustment operation is performed. Due to rounding and byte casting
  390. issues, it actually matters in which order individual adjustment operations
  391. are performed. Both of the following snippets most likely produce different
  392. results:
  393. // snippet 1: contrast, brightness
  394. FreeImage_AdjustContrast(dib, 15.0);
  395. FreeImage_AdjustBrightness(dib, 50.0);
  396. // snippet 2: brightness, contrast
  397. FreeImage_AdjustBrightness(dib, 50.0);
  398. FreeImage_AdjustContrast(dib, 15.0);
  399. Better and even faster would be snippet 3:
  400. // snippet 3:
  401. BYTE LUT[256];
  402. FreeImage_GetAdjustColorsLookupTable(LUT, 50.0, 15.0, 1.0, FALSE);
  403. FreeImage_AdjustCurve(dib, LUT, FICC_RGB);
  404. This function is also used internally by FreeImage_AdjustColors(), which does
  405. not return the lookup table, but uses it to call FreeImage_AdjustCurve() on the
  406. passed image.
  407. @param LUT Output lookup table to be used with FreeImage_AdjustCurve(). <b>The
  408. size of 'LUT' is assumed to be 256.</b>
  409. @param brightness Percentage brightness value where -100 <= brightness <= 100<br>
  410. A value of 0 means no change, less than 0 will make the image darker and greater
  411. than 0 will make the image brighter.
  412. @param contrast Percentage contrast value where -100 <= contrast <= 100<br>
  413. A value of 0 means no change, less than 0 will decrease the contrast
  414. and greater than 0 will increase the contrast of the image.
  415. @param gamma Gamma value to be used for gamma correction. A value of 1.0 leaves
  416. the image alone, less than one darkens it, and greater than one lightens it.
  417. This parameter must not be zero or smaller than zero. If so, it will be ignored
  418. and no gamma correction will be performed using the lookup table created.
  419. @param invert If set to TRUE, the image will be inverted.
  420. @return Returns the number of adjustments applied to the resulting lookup table
  421. compared to a blind lookup table.
  422. */
  423. int DLL_CALLCONV
  424. FreeImage_GetAdjustColorsLookupTable(BYTE *LUT, double brightness, double contrast, double gamma, BOOL invert) {
  425. double dblLUT[256];
  426. double value;
  427. int result = 0;
  428. if ((brightness == 0.0) && (contrast == 0.0) && (gamma == 1.0) && (!invert)) {
  429. // nothing to do, if all arguments have their default values
  430. // return a blind LUT
  431. for (int i = 0; i < 256; i++) {
  432. LUT[i] = (BYTE)i;
  433. }
  434. return 0;
  435. }
  436. // first, create a blind LUT, which does nothing to the image
  437. for (int i = 0; i < 256; i++) {
  438. dblLUT[i] = i;
  439. }
  440. if (contrast != 0.0) {
  441. // modify lookup table with contrast adjustment data
  442. const double v = (100.0 + contrast) / 100.0;
  443. for (int i = 0; i < 256; i++) {
  444. value = 128 + (dblLUT[i] - 128) * v;
  445. dblLUT[i] = MAX(0.0, MIN(value, 255.0));
  446. }
  447. result++;
  448. }
  449. if (brightness != 0.0) {
  450. // modify lookup table with brightness adjustment data
  451. const double v = (100.0 + brightness) / 100.0;
  452. for (int i = 0; i < 256; i++) {
  453. value = dblLUT[i] * v;
  454. dblLUT[i] = MAX(0.0, MIN(value, 255.0));
  455. }
  456. result++;
  457. }
  458. if ((gamma > 0) && (gamma != 1.0)) {
  459. // modify lookup table with gamma adjustment data
  460. double exponent = 1 / gamma;
  461. const double v = 255.0 * (double)pow((double)255, -exponent);
  462. for (int i = 0; i < 256; i++) {
  463. value = pow(dblLUT[i], exponent) * v;
  464. dblLUT[i] = MAX(0.0, MIN(value, 255.0));
  465. }
  466. result++;
  467. }
  468. if (!invert) {
  469. for (int i = 0; i < 256; i++) {
  470. LUT[i] = (BYTE)floor(dblLUT[i] + 0.5);
  471. }
  472. } else {
  473. for (int i = 0; i < 256; i++) {
  474. LUT[i] = 255 - (BYTE)floor(dblLUT[i] + 0.5);
  475. }
  476. result++;
  477. }
  478. // return the number of adjustments made
  479. return result;
  480. }
  481. /** @brief Adjusts an image's brightness, contrast and gamma as well as it may
  482. optionally invert the image within a single operation.
  483. This function adjusts an image's brightness, contrast and gamma as well as it
  484. may optionally invert the image within a single operation. If more than one of
  485. these image display properties need to be adjusted, using this function should
  486. be preferred over calling each adjustment function separately. That's
  487. particularly true for huge images or if performance is an issue.
  488. This function relies on FreeImage_GetAdjustColorsLookupTable(), which creates a
  489. single lookup table, that combines all adjustment operations requested.
  490. Furthermore, the lookup table created by FreeImage_GetAdjustColorsLookupTable()
  491. does not depend on the order, in which each single adjustment operation is
  492. performed. Due to rounding and byte casting issues, it actually matters in which
  493. order individual adjustment operations are performed. Both of the following
  494. snippets most likely produce different results:
  495. // snippet 1: contrast, brightness
  496. FreeImage_AdjustContrast(dib, 15.0);
  497. FreeImage_AdjustBrightness(dib, 50.0);
  498. // snippet 2: brightness, contrast
  499. FreeImage_AdjustBrightness(dib, 50.0);
  500. FreeImage_AdjustContrast(dib, 15.0);
  501. Better and even faster would be snippet 3:
  502. // snippet 3:
  503. FreeImage_AdjustColors(dib, 50.0, 15.0, 1.0, FALSE);
  504. @param dib Input/output image to be processed.
  505. @param brightness Percentage brightness value where -100 <= brightness <= 100<br>
  506. A value of 0 means no change, less than 0 will make the image darker and greater
  507. than 0 will make the image brighter.
  508. @param contrast Percentage contrast value where -100 <= contrast <= 100<br>
  509. A value of 0 means no change, less than 0 will decrease the contrast
  510. and greater than 0 will increase the contrast of the image.
  511. @param gamma Gamma value to be used for gamma correction. A value of 1.0 leaves
  512. the image alone, less than one darkens it, and greater than one lightens it.<br>
  513. This parameter must not be zero or smaller than zero. If so, it will be ignored
  514. and no gamma correction will be performed on the image.
  515. @param invert If set to TRUE, the image will be inverted.
  516. @return Returns TRUE on success, FALSE otherwise (e.g. when the bitdeph of the
  517. source dib cannot be handled).
  518. */
  519. BOOL DLL_CALLCONV
  520. FreeImage_AdjustColors(FIBITMAP *dib, double brightness, double contrast, double gamma, BOOL invert) {
  521. BYTE LUT[256];
  522. if (!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
  523. return FALSE;
  524. }
  525. int bpp = FreeImage_GetBPP(dib);
  526. if ((bpp != 8) && (bpp != 24) && (bpp != 32)) {
  527. return FALSE;
  528. }
  529. if (FreeImage_GetAdjustColorsLookupTable(LUT, brightness, contrast, gamma, invert)) {
  530. return FreeImage_AdjustCurve(dib, LUT, FICC_RGB);
  531. }
  532. return FALSE;
  533. }
  534. /** @brief Applies color mapping for one or several colors on a 1-, 4- or 8-bit
  535. palletized or a 16-, 24- or 32-bit high color image.
  536. This function maps up to <i>count</i> colors specified in <i>srccolors</i> to
  537. these specified in <i>dstcolors</i>. Thereby, color <i>srccolors[N]</i>,
  538. if found in the image, will be replaced by color <i>dstcolors[N]</i>. If
  539. parameter <i>swap</i> is TRUE, additionally all colors specified in
  540. <i>dstcolors</i> are also mapped to these specified in <i>srccolors</i>. For
  541. high color images, the actual image data will be modified whereas, for
  542. palletized images only the palette will be changed.<br>
  543. The function returns the number of pixels changed or zero, if no pixels were
  544. changed.
  545. Both arrays <i>srccolors</i> and <i>dstcolors</i> are assumed not to hold less
  546. than <i>count</i> colors.<br>
  547. For 16-bit images, all colors specified are transparently converted to their
  548. proper 16-bit representation (either in RGB555 or RGB565 format, which is
  549. determined by the image's red- green- and blue-mask).<br>
  550. <b>Note, that this behaviour is different from what FreeImage_ApplyPaletteIndexMapping()
  551. does, which modifies the actual image data on palletized images.</b>
  552. @param dib Input/output image to be processed.
  553. @param srccolors Array of colors to be used as the mapping source.
  554. @param dstcolors Array of colors to be used as the mapping destination.
  555. @param count The number of colors to be mapped. This is the size of both
  556. <i>srccolors</i> and <i>dstcolors</i>.
  557. @param ignore_alpha If TRUE, 32-bit images and colors are treated as 24-bit.
  558. @param swap If TRUE, source and destination colors are swapped, that is,
  559. each destination color is also mapped to the corresponding source color.
  560. @return Returns the total number of pixels changed.
  561. */
  562. unsigned DLL_CALLCONV
  563. FreeImage_ApplyColorMapping(FIBITMAP *dib, RGBQUAD *srccolors, RGBQUAD *dstcolors, unsigned count, BOOL ignore_alpha, BOOL swap) {
  564. unsigned result = 0;
  565. if (!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
  566. return 0;
  567. }
  568. // validate parameters
  569. if ((!srccolors) || (!dstcolors)|| (count < 1)) {
  570. return 0;
  571. }
  572. int bpp = FreeImage_GetBPP(dib);
  573. switch (bpp) {
  574. case 1:
  575. case 4:
  576. case 8: {
  577. unsigned size = FreeImage_GetColorsUsed(dib);
  578. RGBQUAD *pal = FreeImage_GetPalette(dib);
  579. RGBQUAD *a, *b;
  580. for (unsigned x = 0; x < size; x++) {
  581. for (unsigned j = 0; j < count; j++) {
  582. a = srccolors;
  583. b = dstcolors;
  584. for (int i = (swap ? 0 : 1); i < 2; i++) {
  585. if ((pal[x].rgbBlue == a[j].rgbBlue)&&(pal[x].rgbGreen == a[j].rgbGreen) &&(pal[x].rgbRed== a[j].rgbRed)) {
  586. pal[x].rgbBlue = b[j].rgbBlue;
  587. pal[x].rgbGreen = b[j].rgbGreen;
  588. pal[x].rgbRed = b[j].rgbRed;
  589. result++;
  590. j = count;
  591. break;
  592. }
  593. a = dstcolors;
  594. b = srccolors;
  595. }
  596. }
  597. }
  598. return result;
  599. }
  600. case 16: {
  601. WORD *src16 = (WORD *)malloc(sizeof(WORD) * count);
  602. if (NULL == src16) {
  603. return 0;
  604. }
  605. WORD *dst16 = (WORD *)malloc(sizeof(WORD) * count);
  606. if (NULL == dst16) {
  607. free(src16);
  608. return 0;
  609. }
  610. for (unsigned j = 0; j < count; j++) {
  611. src16[j] = RGBQUAD_TO_WORD(dib, (srccolors + j));
  612. dst16[j] = RGBQUAD_TO_WORD(dib, (dstcolors + j));
  613. }
  614. unsigned height = FreeImage_GetHeight(dib);
  615. unsigned width = FreeImage_GetWidth(dib);
  616. WORD *a, *b;
  617. for (unsigned y = 0; y < height; y++) {
  618. WORD *bits = (WORD *)FreeImage_GetScanLine(dib, y);
  619. for (unsigned x = 0; x < width; x++, bits++) {
  620. for (unsigned j = 0; j < count; j++) {
  621. a = src16;
  622. b = dst16;
  623. for (int i = (swap ? 0 : 1); i < 2; i++) {
  624. if (*bits == a[j]) {
  625. *bits = b[j];
  626. result++;
  627. j = count;
  628. break;
  629. }
  630. a = dst16;
  631. b = src16;
  632. }
  633. }
  634. }
  635. }
  636. free(src16);
  637. free(dst16);
  638. return result;
  639. }
  640. case 24: {
  641. unsigned height = FreeImage_GetHeight(dib);
  642. unsigned width = FreeImage_GetWidth(dib);
  643. RGBQUAD *a, *b;
  644. for (unsigned y = 0; y < height; y++) {
  645. BYTE *bits = FreeImage_GetScanLine(dib, y);
  646. for (unsigned x = 0; x < width; x++, bits += 3) {
  647. for (unsigned j = 0; j < count; j++) {
  648. a = srccolors;
  649. b = dstcolors;
  650. for (int i = (swap ? 0 : 1); i < 2; i++) {
  651. if ((bits[FI_RGBA_BLUE] == a[j].rgbBlue) && (bits[FI_RGBA_GREEN] == a[j].rgbGreen) &&(bits[FI_RGBA_RED] == a[j].rgbRed)) {
  652. bits[FI_RGBA_BLUE] = b[j].rgbBlue;
  653. bits[FI_RGBA_GREEN] = b[j].rgbGreen;
  654. bits[FI_RGBA_RED] = b[j].rgbRed;
  655. result++;
  656. j = count;
  657. break;
  658. }
  659. a = dstcolors;
  660. b = srccolors;
  661. }
  662. }
  663. }
  664. }
  665. return result;
  666. }
  667. case 32: {
  668. unsigned height = FreeImage_GetHeight(dib);
  669. unsigned width = FreeImage_GetWidth(dib);
  670. RGBQUAD *a, *b;
  671. for (unsigned y = 0; y < height; y++) {
  672. BYTE *bits = FreeImage_GetScanLine(dib, y);
  673. for (unsigned x = 0; x < width; x++, bits += 4) {
  674. for (unsigned j = 0; j < count; j++) {
  675. a = srccolors;
  676. b = dstcolors;
  677. for (int i = (swap ? 0 : 1); i < 2; i++) {
  678. if ((bits[FI_RGBA_BLUE] == a[j].rgbBlue) &&(bits[FI_RGBA_GREEN] == a[j].rgbGreen) &&(bits[FI_RGBA_RED] == a[j].rgbRed)
  679. &&((ignore_alpha) || (bits[FI_RGBA_ALPHA] == a[j].rgbReserved))) {
  680. bits[FI_RGBA_BLUE] = b[j].rgbBlue;
  681. bits[FI_RGBA_GREEN] = b[j].rgbGreen;
  682. bits[FI_RGBA_RED] = b[j].rgbRed;
  683. if (!ignore_alpha) {
  684. bits[FI_RGBA_ALPHA] = b[j].rgbReserved;
  685. }
  686. result++;
  687. j = count;
  688. break;
  689. }
  690. a = dstcolors;
  691. b = srccolors;
  692. }
  693. }
  694. }
  695. }
  696. return result;
  697. }
  698. default: {
  699. return 0;
  700. }
  701. }
  702. }
  703. /** @brief Swaps two specified colors on a 1-, 4- or 8-bit palletized
  704. or a 16-, 24- or 32-bit high color image.
  705. This function swaps the two specified colors <i>color_a</i> and <i>color_b</i>
  706. on a palletized or high color image. For high color images, the actual image
  707. data will be modified whereas, for palletized images only the palette will be
  708. changed.<br>
  709. <b>Note, that this behaviour is different from what FreeImage_SwapPaletteIndices()
  710. does, which modifies the actual image data on palletized images.</b><br>
  711. This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:<br>
  712. <i>return FreeImage_ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, TRUE);</i>
  713. @param dib Input/output image to be processed.
  714. @param color_a On of the two colors to be swapped.
  715. @param color_b The other of the two colors to be swapped.
  716. @param ignore_alpha If TRUE, 32-bit images and colors are treated as 24-bit.
  717. @return Returns the total number of pixels changed.
  718. */
  719. unsigned DLL_CALLCONV
  720. FreeImage_SwapColors(FIBITMAP *dib, RGBQUAD *color_a, RGBQUAD *color_b, BOOL ignore_alpha) {
  721. return FreeImage_ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, TRUE);
  722. }
  723. /** @brief Applies palette index mapping for one or several indices on a 1-, 4-
  724. or 8-bit palletized image.
  725. This function maps up to <i>count</i> palette indices specified in
  726. <i>srcindices</i> to these specified in <i>dstindices</i>. Thereby, index
  727. <i>srcindices[N]</i>, if present in the image, will be replaced by index
  728. <i>dstindices[N]</i>. If parameter <i>swap</i> is TRUE, additionally all indices
  729. specified in <i>dstindices</i> are also mapped to these specified in
  730. <i>srcindices</i>.<br>
  731. The function returns the number of pixels changed or zero, if no pixels were
  732. changed.
  733. Both arrays <i>srcindices</i> and <i>dstindices</i> are assumed not to hold less
  734. than <i>count</i> indices.<br>
  735. <b>Note, that this behaviour is different from what FreeImage_ApplyColorMapping()
  736. does, which modifies the actual image data on palletized images.</b>
  737. @param dib Input/output image to be processed.
  738. @param srcindices Array of palette indices to be used as the mapping source.
  739. @param dstindices Array of palette indices to be used as the mapping destination.
  740. @param count The number of palette indices to be mapped. This is the size of both
  741. <i>srcindices</i> and <i>dstindices</i>.
  742. @param swap If TRUE, source and destination palette indices are swapped, that is,
  743. each destination index is also mapped to the corresponding source index.
  744. @return Returns the total number of pixels changed.
  745. */
  746. unsigned DLL_CALLCONV
  747. FreeImage_ApplyPaletteIndexMapping(FIBITMAP *dib, BYTE *srcindices, BYTE *dstindices, unsigned count, BOOL swap) {
  748. unsigned result = 0;
  749. if (!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
  750. return 0;
  751. }
  752. // validate parameters
  753. if ((!srcindices) || (!dstindices)|| (count < 1)) {
  754. return 0;
  755. }
  756. unsigned height = FreeImage_GetHeight(dib);
  757. unsigned width = FreeImage_GetLine(dib);
  758. BYTE *a, *b;
  759. int bpp = FreeImage_GetBPP(dib);
  760. switch (bpp) {
  761. case 1: {
  762. return result;
  763. }
  764. case 4: {
  765. int skip_last = (FreeImage_GetWidth(dib) & 0x01);
  766. unsigned max_x = width - 1;
  767. for (unsigned y = 0; y < height; y++) {
  768. BYTE *bits = FreeImage_GetScanLine(dib, y);
  769. for (unsigned x = 0; x < width; x++) {
  770. int start = ((skip_last) && (x == max_x)) ? 1 : 0;
  771. for (int cn = start; cn < 2; cn++) {
  772. for (unsigned j = 0; j < count; j++) {
  773. a = srcindices;
  774. b = dstindices;
  775. for (int i = ((swap) ? 0 : 1); i < 2; i++) {
  776. if (GET_NIBBLE(cn, bits[x]) == (a[j] & 0x0F)) {
  777. SET_NIBBLE(cn, bits[x], b[j]);
  778. result++;
  779. j = count;
  780. break;
  781. }
  782. a = dstindices;
  783. b = srcindices;
  784. }
  785. }
  786. }
  787. }
  788. }
  789. return result;
  790. }
  791. case 8: {
  792. for (unsigned y = 0; y < height; y++) {
  793. BYTE *bits = FreeImage_GetScanLine(dib, y);
  794. for (unsigned x = 0; x < width; x++) {
  795. for (unsigned j = 0; j < count; j++) {
  796. a = srcindices;
  797. b = dstindices;
  798. for (int i = ((swap) ? 0 : 1); i < 2; i++) {
  799. if (bits[x] == a[j]) {
  800. bits[x] = b[j];
  801. result++;
  802. j = count;
  803. break;
  804. }
  805. a = dstindices;
  806. b = srcindices;
  807. }
  808. }
  809. }
  810. }
  811. return result;
  812. }
  813. default: {
  814. return 0;
  815. }
  816. }
  817. }
  818. /** @brief Swaps two specified palette indices on a 1-, 4- or 8-bit palletized
  819. image.
  820. This function swaps the two specified palette indices <i>index_a</i> and
  821. <i>index_b</i> on a palletized image. Therefore, not the palette, but the
  822. actual image data will be modified.<br>
  823. <b>Note, that this behaviour is different from what FreeImage_SwapColors() does
  824. on palletized images, which only swaps the colors in the palette.</b><br>
  825. This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:<br>
  826. <i>return FreeImage_ApplyPaletteIndexMapping(dib, index_a, index_b, 1, TRUE);</i>
  827. @param dib Input/output image to be processed.
  828. @param index_a On of the two palette indices to be swapped.
  829. @param index_b The other of the two palette indices to be swapped.
  830. @return Returns the total number of pixels changed.
  831. */
  832. unsigned DLL_CALLCONV
  833. FreeImage_SwapPaletteIndices(FIBITMAP *dib, BYTE *index_a, BYTE *index_b) {
  834. return FreeImage_ApplyPaletteIndexMapping(dib, index_a, index_b, 1, TRUE);
  835. }