/src/FreeImage/Source/FreeImage/Conversion4.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 246 lines · 165 code · 46 blank · 35 comment · 46 complexity · fbcde04e0d0c46d153d69054f536edc3 MD5 · raw file

  1. // ==========================================================
  2. // Bitmap conversion routines
  3. //
  4. // Design and implementation by
  5. // - Riley McNiff (rmcniff@marexgroup.com)
  6. //
  7. // This file is part of FreeImage 3
  8. //
  9. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  10. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  11. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  12. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  13. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  14. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  15. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  16. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  17. // THIS DISCLAIMER.
  18. //
  19. // Use at your own risk!
  20. // ==========================================================
  21. #include "FreeImage.h"
  22. #include "Utilities.h"
  23. // ----------------------------------------------------------
  24. // internal conversions X to 4 bits
  25. // ----------------------------------------------------------
  26. void DLL_CALLCONV
  27. FreeImage_ConvertLine1To4(BYTE *target, BYTE *source, int width_in_pixels) {
  28. BOOL hinibble = TRUE;
  29. for (int cols = 0; cols < width_in_pixels; cols++){
  30. if (hinibble == TRUE){
  31. target[cols >> 1] = ((source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 15 : 0) << 4;
  32. }
  33. else {
  34. target[cols >> 1] |= ((source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 15 : 0);
  35. }
  36. hinibble = !hinibble;
  37. }
  38. }
  39. void DLL_CALLCONV
  40. FreeImage_ConvertLine8To4(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
  41. BOOL hinibble = TRUE;
  42. BYTE index;
  43. for (int cols = 0; cols < width_in_pixels; cols++){
  44. index = GREY(palette[source[cols]].rgbRed, palette[source[cols]].rgbGreen, palette[source[cols]].rgbBlue);
  45. if (hinibble) {
  46. target[cols >> 1] = (index & 0xF0);
  47. } else {
  48. target[cols >> 1] |= (index >> 4);
  49. }
  50. hinibble = !hinibble;
  51. }
  52. }
  53. void DLL_CALLCONV
  54. FreeImage_ConvertLine16To4_555(BYTE *target, BYTE *source, int width_in_pixels) {
  55. WORD *bits = (WORD *)source;
  56. BOOL hinibble = TRUE;
  57. for (int cols = 0; cols < width_in_pixels; cols++) {
  58. if (hinibble) {
  59. target[cols >> 1] = GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F,
  60. (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
  61. (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F)
  62. & 0xF0;
  63. } else {
  64. target[cols >> 1] |= GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F,
  65. (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
  66. (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F)
  67. >> 4;
  68. }
  69. hinibble = !hinibble;
  70. }
  71. }
  72. void DLL_CALLCONV
  73. FreeImage_ConvertLine16To4_565(BYTE *target, BYTE *source, int width_in_pixels) {
  74. WORD *bits = (WORD *)source;
  75. BOOL hinibble = TRUE;
  76. for (int cols = 0; cols < width_in_pixels; cols++) {
  77. if (hinibble) {
  78. target[cols >> 1] = GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F,
  79. (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
  80. (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F)
  81. & 0xF0;
  82. } else {
  83. target[cols >> 1] |= GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F,
  84. (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
  85. (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F)
  86. >> 4;
  87. }
  88. hinibble = !hinibble;
  89. }
  90. }
  91. void DLL_CALLCONV
  92. FreeImage_ConvertLine24To4(BYTE *target, BYTE *source, int width_in_pixels) {
  93. BOOL hinibble = TRUE;
  94. for (int cols = 0; cols < width_in_pixels; cols++) {
  95. if (hinibble) {
  96. target[cols >> 1] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) & 0xF0;
  97. } else {
  98. target[cols >> 1] |= GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) >> 4;
  99. }
  100. source += 3;
  101. hinibble = !hinibble;
  102. }
  103. }
  104. void DLL_CALLCONV
  105. FreeImage_ConvertLine32To4(BYTE *target, BYTE *source, int width_in_pixels) {
  106. BOOL hinibble = TRUE;
  107. for (int cols = 0; cols < width_in_pixels; cols++) {
  108. if (hinibble) {
  109. target[cols >> 1] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) & 0xF0;
  110. } else {
  111. target[cols >> 1] |= GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) >> 4;
  112. }
  113. source += 4;
  114. hinibble = !hinibble;
  115. }
  116. }
  117. // ----------------------------------------------------------
  118. // smart convert X to 4 bits
  119. // ----------------------------------------------------------
  120. FIBITMAP * DLL_CALLCONV
  121. FreeImage_ConvertTo4Bits(FIBITMAP *dib) {
  122. if(!FreeImage_HasPixels(dib)) return NULL;
  123. const int bpp = FreeImage_GetBPP(dib);
  124. if(bpp != 4) {
  125. const int width = FreeImage_GetWidth(dib);
  126. const int height = FreeImage_GetHeight(dib);
  127. FIBITMAP *new_dib = FreeImage_Allocate(width, height, 4);
  128. if(new_dib == NULL) {
  129. return NULL;
  130. }
  131. // copy metadata from src to dst
  132. FreeImage_CloneMetadata(new_dib, dib);
  133. // Build a greyscale palette (*always* needed for image processing)
  134. RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
  135. for(int i = 0; i < 16; i++) {
  136. new_pal[i].rgbRed = (BYTE)((i << 4) + i);
  137. new_pal[i].rgbGreen = (BYTE)((i << 4) + i);
  138. new_pal[i].rgbBlue = (BYTE)((i << 4) + i);
  139. }
  140. switch(bpp) {
  141. case 1:
  142. {
  143. if(FreeImage_GetColorType(dib) == FIC_PALETTE) {
  144. // Copy the palette
  145. RGBQUAD *old_pal = FreeImage_GetPalette(dib);
  146. memcpy(&new_pal[0], &old_pal[0], sizeof(RGBQUAD));
  147. memcpy(&new_pal[15], &old_pal[1], sizeof(RGBQUAD));
  148. }
  149. else if(FreeImage_GetColorType(dib) == FIC_MINISWHITE) {
  150. // Reverse the grayscale palette
  151. for(int i = 0; i < 16; i++) {
  152. new_pal[i].rgbRed = new_pal[i].rgbGreen = new_pal[i].rgbBlue = (BYTE)(255 - ((i << 4) + i));
  153. }
  154. }
  155. // Expand and copy the bitmap data
  156. for (int rows = 0; rows < height; rows++) {
  157. FreeImage_ConvertLine1To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  158. }
  159. return new_dib;
  160. }
  161. case 8 :
  162. {
  163. // Expand and copy the bitmap data
  164. for (int rows = 0; rows < height; rows++) {
  165. FreeImage_ConvertLine8To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
  166. }
  167. return new_dib;
  168. }
  169. case 16 :
  170. {
  171. // Expand and copy the bitmap data
  172. for (int rows = 0; rows < height; rows++) {
  173. if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
  174. FreeImage_ConvertLine16To4_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  175. } else {
  176. FreeImage_ConvertLine16To4_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  177. }
  178. }
  179. return new_dib;
  180. }
  181. case 24 :
  182. {
  183. // Expand and copy the bitmap data
  184. for (int rows = 0; rows < height; rows++) {
  185. FreeImage_ConvertLine24To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  186. }
  187. return new_dib;
  188. }
  189. case 32 :
  190. {
  191. // Expand and copy the bitmap data
  192. for (int rows = 0; rows < height; rows++) {
  193. FreeImage_ConvertLine32To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
  194. }
  195. return new_dib;
  196. }
  197. }
  198. }
  199. return FreeImage_Clone(dib);
  200. }