/src/FreeImage/Source/FreeImage/Conversion8.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 327 lines · 210 code · 73 blank · 44 comment · 62 complexity · 479f0ff8553b04b0735ec09ecf5160ee MD5 · raw file

  1. // ==========================================================
  2. // Bitmap conversion routines
  3. //
  4. // Design and implementation by
  5. // - Floris van den Berg (flvdberg@wxs.nl)
  6. // - Hervé Drolon (drolon@infonie.fr)
  7. // - Jani Kajala (janik@remedy.fi)
  8. // - Karl-Heinz Bussian (khbussian@moss.de)
  9. //
  10. // This file is part of FreeImage 3
  11. //
  12. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  13. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  14. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  15. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  16. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  17. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  18. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  19. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  20. // THIS DISCLAIMER.
  21. //
  22. // Use at your own risk!
  23. // ==========================================================
  24. #include "FreeImage.h"
  25. #include "Utilities.h"
  26. // ----------------------------------------------------------
  27. // internal conversions X to 8 bits
  28. // ----------------------------------------------------------
  29. void DLL_CALLCONV
  30. FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels) {
  31. for (int cols = 0; cols < width_in_pixels; cols++)
  32. target[cols] = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 255 : 0;
  33. }
  34. void DLL_CALLCONV
  35. FreeImage_ConvertLine4To8(BYTE *target, BYTE *source, int width_in_pixels) {
  36. int count_new = 0;
  37. int count_org = 0;
  38. BOOL hinibble = TRUE;
  39. while (count_new < width_in_pixels) {
  40. if (hinibble) {
  41. target[count_new] = (source[count_org] & 0xF0) >> 4;
  42. } else {
  43. target[count_new] = (source[count_org] & 0x0F);
  44. count_org++;
  45. }
  46. hinibble = !hinibble;
  47. count_new++;
  48. }
  49. }
  50. void DLL_CALLCONV
  51. FreeImage_ConvertLine16To8_555(BYTE *target, BYTE *source, int width_in_pixels) {
  52. WORD *bits = (WORD *)source;
  53. for (int cols = 0; cols < width_in_pixels; cols++) {
  54. target[cols] = GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F,
  55. (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
  56. (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
  57. }
  58. }
  59. void DLL_CALLCONV
  60. FreeImage_ConvertLine16To8_565(BYTE *target, BYTE *source, int width_in_pixels) {
  61. WORD *bits = (WORD *)source;
  62. for (int cols = 0; cols < width_in_pixels; cols++)
  63. target[cols] = GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F,
  64. (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
  65. (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);
  66. }
  67. void DLL_CALLCONV
  68. FreeImage_ConvertLine24To8(BYTE *target, BYTE *source, int width_in_pixels) {
  69. for (int cols = 0; cols < width_in_pixels; cols++) {
  70. target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]);
  71. source += 3;
  72. }
  73. }
  74. void DLL_CALLCONV
  75. FreeImage_ConvertLine32To8(BYTE *target, BYTE *source, int width_in_pixels) {
  76. for (int cols = 0; cols < width_in_pixels; cols++) {
  77. target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]);
  78. source += 4;
  79. }
  80. }
  81. // ----------------------------------------------------------
  82. // smart convert X to 8 bits
  83. // ----------------------------------------------------------
  84. FIBITMAP * DLL_CALLCONV
  85. FreeImage_ConvertTo8Bits(FIBITMAP *dib) {
  86. if(!FreeImage_HasPixels(dib)) return NULL;
  87. const int bpp = FreeImage_GetBPP(dib);
  88. const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
  89. if((image_type != FIT_BITMAP) && (image_type != FIT_UINT16)) {
  90. return NULL;
  91. }
  92. if(bpp != 8) {
  93. const int width = FreeImage_GetWidth(dib);
  94. const int height = FreeImage_GetHeight(dib);
  95. FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
  96. if(new_dib == NULL) {
  97. return NULL;
  98. }
  99. // copy metadata from src to dst
  100. FreeImage_CloneMetadata(new_dib, dib);
  101. // Build a greyscale palette (*always* needed for image processing)
  102. RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
  103. for(int i = 0; i < 256; i++) {
  104. new_pal[i].rgbRed = (BYTE)i;
  105. new_pal[i].rgbGreen = (BYTE)i;
  106. new_pal[i].rgbBlue = (BYTE)i;
  107. }
  108. if(image_type == FIT_BITMAP) {
  109. switch(bpp) {
  110. case 1:
  111. {
  112. if(FreeImage_GetColorType(dib) == FIC_PALETTE) {
  113. // Copy the palette
  114. RGBQUAD *old_pal = FreeImage_GetPalette(dib);
  115. memcpy(&new_pal[0], &old_pal[0], sizeof(RGBQUAD));
  116. memcpy(&new_pal[255], &old_pal[1], sizeof(RGBQUAD));
  117. }
  118. else if(FreeImage_GetColorType(dib) == FIC_MINISWHITE) {
  119. // Reverse the grayscale palette
  120. for(int i = 0; i < 256; i++) {
  121. new_pal[i].rgbRed = new_pal[i].rgbGreen = new_pal[i].rgbBlue = (BYTE)(255 - i);
  122. }
  123. }
  124. // Expand and copy the bitmap data
  125. for (int rows = 0; rows < height; rows++) {
  126. FreeImage_ConvertLine1To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  127. }
  128. return new_dib;
  129. }
  130. case 4 :
  131. {
  132. if(FreeImage_GetColorType(dib) == FIC_PALETTE) {
  133. // Copy the palette
  134. RGBQUAD *old_pal = FreeImage_GetPalette(dib);
  135. for (int i = 0; i < 16; i++) {
  136. new_pal[i].rgbRed = old_pal[i].rgbRed;
  137. new_pal[i].rgbGreen = old_pal[i].rgbGreen;
  138. new_pal[i].rgbBlue = old_pal[i].rgbBlue;
  139. }
  140. }
  141. // Expand and copy the bitmap data
  142. for (int rows = 0; rows < height; rows++) {
  143. FreeImage_ConvertLine4To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  144. }
  145. return new_dib;
  146. }
  147. case 16 :
  148. {
  149. // Expand and copy the bitmap data
  150. for (int rows = 0; rows < height; rows++) {
  151. if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
  152. FreeImage_ConvertLine16To8_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  153. } else {
  154. FreeImage_ConvertLine16To8_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  155. }
  156. }
  157. return new_dib;
  158. }
  159. case 24 :
  160. {
  161. // Expand and copy the bitmap data
  162. for (int rows = 0; rows < height; rows++) {
  163. FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  164. }
  165. return new_dib;
  166. }
  167. case 32 :
  168. {
  169. // Expand and copy the bitmap data
  170. for (int rows = 0; rows < height; rows++) {
  171. FreeImage_ConvertLine32To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  172. }
  173. return new_dib;
  174. }
  175. }
  176. } else if(image_type == FIT_UINT16) {
  177. const unsigned src_pitch = FreeImage_GetPitch(dib);
  178. const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
  179. const BYTE *src_bits = FreeImage_GetBits(dib);
  180. BYTE *dst_bits = FreeImage_GetBits(new_dib);
  181. for (int rows = 0; rows < height; rows++) {
  182. const WORD *src_pixel = (WORD*)src_bits;
  183. BYTE *dst_pixel = (BYTE*)dst_bits;
  184. for(int cols = 0; cols < width; cols++) {
  185. dst_pixel[cols] = (BYTE)(src_pixel[cols] >> 8);
  186. }
  187. src_bits += src_pitch;
  188. dst_bits += dst_pitch;
  189. }
  190. return new_dib;
  191. }
  192. } // bpp != 8
  193. return FreeImage_Clone(dib);
  194. }
  195. FIBITMAP * DLL_CALLCONV
  196. FreeImage_ConvertToGreyscale(FIBITMAP *dib) {
  197. if(!FreeImage_HasPixels(dib)) return NULL;
  198. const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
  199. const int bpp = FreeImage_GetBPP(dib);
  200. if((color_type == FIC_PALETTE) || (color_type == FIC_MINISWHITE)) {
  201. const int width = FreeImage_GetWidth(dib);
  202. const int height = FreeImage_GetHeight(dib);
  203. FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
  204. if(new_dib == NULL) {
  205. return NULL;
  206. }
  207. // copy metadata from src to dst
  208. FreeImage_CloneMetadata(new_dib, dib);
  209. // Build a greyscale palette
  210. RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
  211. for(int i = 0; i < 256; i++) {
  212. new_pal[i].rgbRed = (BYTE)i;
  213. new_pal[i].rgbGreen = (BYTE)i;
  214. new_pal[i].rgbBlue = (BYTE)i;
  215. }
  216. // allocate a 24-bit buffer
  217. BYTE *buffer = (BYTE*)malloc( CalculatePitch(CalculateLine(width, 24)) * sizeof(BYTE) );
  218. if(NULL == buffer) {
  219. FreeImage_Unload(new_dib);
  220. return NULL;
  221. }
  222. // Convert the palette to 24-bit, then to 8-bit
  223. switch(bpp) {
  224. case 1:
  225. {
  226. for (int rows = 0; rows < height; rows++) {
  227. FreeImage_ConvertLine1To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
  228. FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
  229. }
  230. }
  231. break;
  232. case 4:
  233. {
  234. for (int rows = 0; rows < height; rows++) {
  235. FreeImage_ConvertLine4To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
  236. FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
  237. }
  238. }
  239. break;
  240. case 8:
  241. {
  242. for (int rows = 0; rows < height; rows++) {
  243. FreeImage_ConvertLine8To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
  244. FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
  245. }
  246. }
  247. break;
  248. }
  249. free(buffer);
  250. return new_dib;
  251. }
  252. // Convert the bitmap to 8-bit greyscale
  253. return FreeImage_ConvertTo8Bits(dib);
  254. }