/src/FreeImage/Source/FreeImage/Halftoning.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 474 lines · 315 code · 54 blank · 105 comment · 64 complexity · aa5bc2f6f2808b5db536b3905586971e MD5 · raw file

  1. // ==========================================================
  2. // Bitmap conversion routines
  3. // Thresholding and halftoning functions
  4. // Design and implementation by
  5. // - Hervé Drolon (drolon@infonie.fr)
  6. // - Dennis Lim (dlkj@users.sourceforge.net)
  7. // - Thomas Chmielewski (Chmielewski.Thomas@oce.de)
  8. //
  9. // Main reference : Ulichney, R., Digital Halftoning, The MIT Press, Cambridge, MA, 1987
  10. //
  11. // This file is part of FreeImage 3
  12. //
  13. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  14. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  15. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  16. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  17. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  18. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  19. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  20. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  21. // THIS DISCLAIMER.
  22. //
  23. // Use at your own risk!
  24. // ==========================================================
  25. #include "FreeImage.h"
  26. #include "Utilities.h"
  27. static const int WHITE = 255;
  28. static const int BLACK = 0;
  29. // Floyd & Steinberg error diffusion dithering
  30. // This algorithm use the following filter
  31. // * 7
  32. // 3 5 1 (1/16)
  33. static FIBITMAP* FloydSteinberg(FIBITMAP *dib) {
  34. #define RAND(RN) (((seed = 1103515245 * seed + 12345) >> 12) % (RN))
  35. #define INITERR(X, Y) (((int) X) - (((int) Y) ? WHITE : BLACK) + ((WHITE/2)-((int)X)) / 2)
  36. int seed = 0;
  37. int x, y, p, pixel, threshold, error;
  38. int width, height, pitch;
  39. BYTE *bits, *new_bits;
  40. FIBITMAP *new_dib = NULL;
  41. // allocate a 8-bit DIB
  42. width = FreeImage_GetWidth(dib);
  43. height = FreeImage_GetHeight(dib);
  44. pitch = FreeImage_GetPitch(dib);
  45. new_dib = FreeImage_Allocate(width, height, 8);
  46. if(NULL == new_dib) return NULL;
  47. // allocate space for error arrays
  48. int *lerr = (int*)malloc (width * sizeof(int));
  49. int *cerr = (int*)malloc (width * sizeof(int));
  50. memset(lerr, 0, width * sizeof(int));
  51. memset(cerr, 0, width * sizeof(int));
  52. // left border
  53. error = 0;
  54. for(y = 0; y < height; y++) {
  55. bits = FreeImage_GetScanLine(dib, y);
  56. new_bits = FreeImage_GetScanLine(new_dib, y);
  57. threshold = (WHITE / 2 + RAND(129) - 64);
  58. pixel = bits[0] + error;
  59. p = (pixel > threshold) ? WHITE : BLACK;
  60. error = pixel - p;
  61. new_bits[0] = (BYTE)p;
  62. }
  63. // right border
  64. error = 0;
  65. for(y = 0; y < height; y++) {
  66. bits = FreeImage_GetScanLine(dib, y);
  67. new_bits = FreeImage_GetScanLine(new_dib, y);
  68. threshold = (WHITE / 2 + RAND(129) - 64);
  69. pixel = bits[width-1] + error;
  70. p = (pixel > threshold) ? WHITE : BLACK;
  71. error = pixel - p;
  72. new_bits[width-1] = (BYTE)p;
  73. }
  74. // top border
  75. bits = FreeImage_GetBits(dib);
  76. new_bits = FreeImage_GetBits(new_dib);
  77. error = 0;
  78. for(x = 0; x < width; x++) {
  79. threshold = (WHITE / 2 + RAND(129) - 64);
  80. pixel = bits[x] + error;
  81. p = (pixel > threshold) ? WHITE : BLACK;
  82. error = pixel - p;
  83. new_bits[x] = (BYTE)p;
  84. lerr[x] = INITERR(bits[x], p);
  85. }
  86. // interior bits
  87. for(y = 1; y < height; y++) {
  88. // scan left to right
  89. bits = FreeImage_GetScanLine(dib, y);
  90. new_bits = FreeImage_GetScanLine(new_dib, y);
  91. cerr[0] = INITERR(bits[0], new_bits[0]);
  92. for(x = 1; x < width - 1; x++) {
  93. error = (lerr[x-1] + 5 * lerr[x] + 3 * lerr[x+1] + 7 * cerr[x-1]) / 16;
  94. pixel = bits[x] + error;
  95. if(pixel > (WHITE / 2)) {
  96. new_bits[x] = WHITE;
  97. cerr[x] = pixel - WHITE;
  98. } else {
  99. new_bits[x] = BLACK;
  100. cerr[x] = pixel - BLACK;
  101. }
  102. }
  103. // set errors for ends of the row
  104. cerr[0] = INITERR (bits[0], new_bits[0]);
  105. cerr[width - 1] = INITERR (bits[width - 1], new_bits[width - 1]);
  106. // swap error buffers
  107. int *terr = lerr; lerr = cerr; cerr = terr;
  108. }
  109. free(lerr);
  110. free(cerr);
  111. return new_dib;
  112. }
  113. // ==========================================================
  114. // Bayer ordered dispersed dot dithering
  115. //
  116. // Function taken from "Ordered Dithering, Stephen Hawley, Graphics Gems, Academic Press, 1990"
  117. // This function is used to generate a Bayer dithering matrice whose dimension are 2^size by 2^size
  118. //
  119. static int dithervalue(int x, int y, int size) {
  120. int d = 0;
  121. /*
  122. * calculate the dither value at a particular
  123. * (x, y) over the size of the matrix.
  124. */
  125. while (size-->0) {
  126. /* Think of d as the density. At every iteration,
  127. * d is shifted left one and a new bit is put in the
  128. * low bit based on x and y. If x is odd and y is even,
  129. * or x is even and y is odd, a bit is put in. This
  130. * generates the checkerboard seen in dithering.
  131. * This quantity is shifted left again and the low bit of
  132. * y is added in.
  133. * This whole thing interleaves a checkerboard bit pattern
  134. * and y's bits, which is the value you want.
  135. */
  136. d = (d <<1 | (x&1 ^ y&1))<<1 | y&1;
  137. x >>= 1;
  138. y >>= 1;
  139. }
  140. return d;
  141. }
  142. // Ordered dithering with a Bayer matrix of size 2^order by 2^order
  143. //
  144. static FIBITMAP* OrderedDispersedDot(FIBITMAP *dib, int order) {
  145. int x, y;
  146. int width, height;
  147. BYTE *bits, *new_bits;
  148. FIBITMAP *new_dib = NULL;
  149. // allocate a 8-bit DIB
  150. width = FreeImage_GetWidth(dib);
  151. height = FreeImage_GetHeight(dib);
  152. new_dib = FreeImage_Allocate(width, height, 8);
  153. if(NULL == new_dib) return NULL;
  154. // build the dithering matrix
  155. int l = (1 << order); // square of dither matrix order; the dimensions of the matrix
  156. BYTE *matrix = (BYTE*)malloc(l*l * sizeof(BYTE));
  157. for(int i = 0; i < l*l; i++) {
  158. // according to "Purdue University: Digital Image Processing Laboratory: Image Halftoning, April 30th, 2006
  159. matrix[i] = (BYTE)( 255 * (((double)dithervalue(i / l, i % l, order) + 0.5) / (l*l)) );
  160. }
  161. // perform the dithering
  162. for(y = 0; y < height; y++) {
  163. // scan left to right
  164. bits = FreeImage_GetScanLine(dib, y);
  165. new_bits = FreeImage_GetScanLine(new_dib, y);
  166. for(x = 0; x < width; x++) {
  167. if(bits[x] > matrix[(x % l) + l * (y % l)]) {
  168. new_bits[x] = WHITE;
  169. } else {
  170. new_bits[x] = BLACK;
  171. }
  172. }
  173. }
  174. free(matrix);
  175. return new_dib;
  176. }
  177. // ==========================================================
  178. // Ordered clustered dot dithering
  179. //
  180. // NB : The predefined dither matrices are the same as matrices used in
  181. // the Netpbm package (http://netpbm.sourceforge.net) and are defined in Ulichney's book.
  182. // See also : The newsprint web site at http://www.cl.cam.ac.uk/~and1000/newsprint/
  183. // for more technical info on this dithering technique
  184. //
  185. static FIBITMAP* OrderedClusteredDot(FIBITMAP *dib, int order) {
  186. // Order-3 clustered dithering matrix.
  187. int cluster3[] = {
  188. 9,11,10, 8, 6, 7,
  189. 12,17,16, 5, 0, 1,
  190. 13,14,15, 4, 3, 2,
  191. 8, 6, 7, 9,11,10,
  192. 5, 0, 1,12,17,16,
  193. 4, 3, 2,13,14,15
  194. };
  195. // Order-4 clustered dithering matrix.
  196. int cluster4[] = {
  197. 18,20,19,16,13,11,12,15,
  198. 27,28,29,22, 4, 3, 2, 9,
  199. 26,31,30,21, 5, 0, 1,10,
  200. 23,25,24,17, 8, 6, 7,14,
  201. 13,11,12,15,18,20,19,16,
  202. 4, 3, 2, 9,27,28,29,22,
  203. 5, 0, 1,10,26,31,30,21,
  204. 8, 6, 7,14,23,25,24,17
  205. };
  206. // Order-8 clustered dithering matrix.
  207. int cluster8[] = {
  208. 64, 69, 77, 87, 86, 76, 68, 67, 63, 58, 50, 40, 41, 51, 59, 60,
  209. 70, 94,100,109,108, 99, 93, 75, 57, 33, 27, 18, 19, 28, 34, 52,
  210. 78,101,114,116,115,112, 98, 83, 49, 26, 13, 11, 12, 15, 29, 44,
  211. 88,110,123,124,125,118,107, 85, 39, 17, 4, 3, 2, 9, 20, 42,
  212. 89,111,122,127,126,117,106, 84, 38, 16, 5, 0, 1, 10, 21, 43,
  213. 79,102,119,121,120,113, 97, 82, 48, 25, 8, 6, 7, 14, 30, 45,
  214. 71, 95,103,104,105, 96, 92, 74, 56, 32, 24, 23, 22, 31, 35, 53,
  215. 65, 72, 80, 90, 91, 81, 73, 66, 62, 55, 47, 37, 36, 46, 54, 61,
  216. 63, 58, 50, 40, 41, 51, 59, 60, 64, 69, 77, 87, 86, 76, 68, 67,
  217. 57, 33, 27, 18, 19, 28, 34, 52, 70, 94,100,109,108, 99, 93, 75,
  218. 49, 26, 13, 11, 12, 15, 29, 44, 78,101,114,116,115,112, 98, 83,
  219. 39, 17, 4, 3, 2, 9, 20, 42, 88,110,123,124,125,118,107, 85,
  220. 38, 16, 5, 0, 1, 10, 21, 43, 89,111,122,127,126,117,106, 84,
  221. 48, 25, 8, 6, 7, 14, 30, 45, 79,102,119,121,120,113, 97, 82,
  222. 56, 32, 24, 23, 22, 31, 35, 53, 71, 95,103,104,105, 96, 92, 74,
  223. 62, 55, 47, 37, 36, 46, 54, 61, 65, 72, 80, 90, 91, 81, 73, 66
  224. };
  225. int x, y, pixel;
  226. int width, height;
  227. BYTE *bits, *new_bits;
  228. FIBITMAP *new_dib = NULL;
  229. // allocate a 8-bit DIB
  230. width = FreeImage_GetWidth(dib);
  231. height = FreeImage_GetHeight(dib);
  232. new_dib = FreeImage_Allocate(width, height, 8);
  233. if(NULL == new_dib) return NULL;
  234. // select the dithering matrix
  235. int *matrix = NULL;
  236. switch(order) {
  237. case 3:
  238. matrix = &cluster3[0];
  239. break;
  240. case 4:
  241. matrix = &cluster4[0];
  242. break;
  243. case 8:
  244. matrix = &cluster8[0];
  245. break;
  246. default:
  247. return NULL;
  248. }
  249. // scale the dithering matrix
  250. int l = 2 * order;
  251. int scale = 256 / (l * order);
  252. for(y = 0; y < l; y++) {
  253. for(x = 0; x < l; x++) {
  254. matrix[y*l + x] *= scale;
  255. }
  256. }
  257. // perform the dithering
  258. for(y = 0; y < height; y++) {
  259. // scan left to right
  260. bits = FreeImage_GetScanLine(dib, y);
  261. new_bits = FreeImage_GetScanLine(new_dib, y);
  262. for(x = 0; x < width; x++) {
  263. pixel = bits[x];
  264. if(pixel >= matrix[(y % l) + l * (x % l)]) {
  265. new_bits[x] = WHITE;
  266. } else {
  267. new_bits[x] = BLACK;
  268. }
  269. }
  270. }
  271. return new_dib;
  272. }
  273. // ==========================================================
  274. // Halftoning function
  275. //
  276. FIBITMAP * DLL_CALLCONV
  277. FreeImage_Dither(FIBITMAP *dib, FREE_IMAGE_DITHER algorithm) {
  278. FIBITMAP *input = NULL, *dib8 = NULL;
  279. if(!FreeImage_HasPixels(dib)) return NULL;
  280. const unsigned bpp = FreeImage_GetBPP(dib);
  281. if(bpp == 1) {
  282. // Just clone the dib and adjust the palette if needed
  283. FIBITMAP *new_dib = FreeImage_Clone(dib);
  284. if(NULL == new_dib) return NULL;
  285. if(FreeImage_GetColorType(new_dib) == FIC_PALETTE) {
  286. // Build a monochrome palette
  287. RGBQUAD *pal = FreeImage_GetPalette(new_dib);
  288. pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
  289. pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
  290. }
  291. return new_dib;
  292. }
  293. // Convert the input dib to a 8-bit greyscale dib
  294. //
  295. switch(bpp) {
  296. case 8:
  297. if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) {
  298. input = dib;
  299. } else {
  300. input = FreeImage_ConvertToGreyscale(dib);
  301. }
  302. break;
  303. case 4:
  304. case 16:
  305. case 24:
  306. case 32:
  307. input = FreeImage_ConvertToGreyscale(dib);
  308. break;
  309. }
  310. if(NULL == input) return NULL;
  311. // Apply the dithering algorithm
  312. switch(algorithm) {
  313. case FID_FS:
  314. dib8 = FloydSteinberg(input);
  315. break;
  316. case FID_BAYER4x4:
  317. dib8 = OrderedDispersedDot(input, 2);
  318. break;
  319. case FID_BAYER8x8:
  320. dib8 = OrderedDispersedDot(input, 3);
  321. break;
  322. case FID_BAYER16x16:
  323. dib8 = OrderedDispersedDot(input, 4);
  324. break;
  325. case FID_CLUSTER6x6:
  326. dib8 = OrderedClusteredDot(input, 3);
  327. break;
  328. case FID_CLUSTER8x8:
  329. dib8 = OrderedClusteredDot(input, 4);
  330. break;
  331. case FID_CLUSTER16x16:
  332. dib8 = OrderedClusteredDot(input, 8);
  333. break;
  334. }
  335. if(input != dib) {
  336. FreeImage_Unload(input);
  337. }
  338. // Build a greyscale palette (needed by threshold)
  339. RGBQUAD *grey_pal = FreeImage_GetPalette(dib8);
  340. for(int i = 0; i < 256; i++) {
  341. grey_pal[i].rgbRed = (BYTE)i;
  342. grey_pal[i].rgbGreen = (BYTE)i;
  343. grey_pal[i].rgbBlue = (BYTE)i;
  344. }
  345. // Convert to 1-bit
  346. FIBITMAP *new_dib = FreeImage_Threshold(dib8, 128);
  347. FreeImage_Unload(dib8);
  348. // copy metadata from src to dst
  349. FreeImage_CloneMetadata(new_dib, dib);
  350. return new_dib;
  351. }
  352. // ==========================================================
  353. // Thresholding function
  354. //
  355. FIBITMAP * DLL_CALLCONV
  356. FreeImage_Threshold(FIBITMAP *dib, BYTE T) {
  357. FIBITMAP *dib8 = NULL;
  358. if(!FreeImage_HasPixels(dib)) return NULL;
  359. const unsigned bpp = FreeImage_GetBPP(dib);
  360. if(bpp == 1) {
  361. // Just clone the dib and adjust the palette if needed
  362. FIBITMAP *new_dib = FreeImage_Clone(dib);
  363. if(NULL == new_dib) return NULL;
  364. if(FreeImage_GetColorType(new_dib) == FIC_PALETTE) {
  365. // Build a monochrome palette
  366. RGBQUAD *pal = FreeImage_GetPalette(new_dib);
  367. pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
  368. pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
  369. }
  370. return new_dib;
  371. }
  372. // Convert the input dib to a 8-bit greyscale dib
  373. //
  374. switch(bpp) {
  375. case 8:
  376. if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) {
  377. dib8 = dib;
  378. } else {
  379. dib8 = FreeImage_ConvertToGreyscale(dib);
  380. }
  381. break;
  382. case 4:
  383. case 16:
  384. case 24:
  385. case 32:
  386. dib8 = FreeImage_ConvertToGreyscale(dib);
  387. break;
  388. }
  389. if(NULL == dib8) return NULL;
  390. // Allocate a new 1-bit DIB
  391. int width = FreeImage_GetWidth(dib);
  392. int height = FreeImage_GetHeight(dib);
  393. FIBITMAP *new_dib = FreeImage_Allocate(width, height, 1);
  394. if(NULL == new_dib) return NULL;
  395. // Build a monochrome palette
  396. RGBQUAD *pal = FreeImage_GetPalette(new_dib);
  397. pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
  398. pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
  399. // Perform the thresholding
  400. //
  401. for(int y = 0; y < height; y++) {
  402. BYTE *bits8 = FreeImage_GetScanLine(dib8, y);
  403. BYTE *bits1 = FreeImage_GetScanLine(new_dib, y);
  404. for(int x = 0; x < width; x++) {
  405. if(bits8[x] < T) {
  406. // Set bit(x, y) to 0
  407. bits1[x >> 3] &= (0xFF7F >> (x & 0x7));
  408. } else {
  409. // Set bit(x, y) to 1
  410. bits1[x >> 3] |= (0x80 >> (x & 0x7));
  411. }
  412. }
  413. }
  414. if(dib8 != dib) {
  415. FreeImage_Unload(dib8);
  416. }
  417. // copy metadata from src to dst
  418. FreeImage_CloneMetadata(new_dib, dib);
  419. return new_dib;
  420. }