ilgraybi.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: ilgraybi.c /main/6 1996/10/30 11:09:02 drk $ */
  24. /**---------------------------------------------------------------------
  25. ***
  26. *** (c)Copyright 1991 Hewlett-Packard Co.
  27. ***
  28. *** RESTRICTED RIGHTS LEGEND
  29. *** Use, duplication, or disclosure by the U.S. Government is subject to
  30. *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
  31. *** Technical Data and Computer Software clause in DFARS 252.227-7013.
  32. *** Hewlett-Packard Company
  33. *** 3000 Hanover Street
  34. *** Palo Alto, CA 94304 U.S.A.
  35. *** Rights for non-DOD U.S. Government Departments and Agencies are as set
  36. *** forth in FAR 52.227-19(c)(1,2).
  37. ***
  38. ***-------------------------------------------------------------------*/
  39. #include <stdlib.h>
  40. #include "ilint.h"
  41. #include "ilpipelem.h"
  42. #include "ilconvert.h"
  43. #include "ilerrors.h"
  44. #ifndef LSB_BIT_ORDER
  45. # define flip_bits(start,n) /*EMPTY*/
  46. #else
  47. extern void flip_bits(ilPtr start, unsigned n);
  48. extern void
  49. flip_bits(ilPtr start,
  50. unsigned n )
  51. {
  52. int i;
  53. unsigned char c;
  54. for (i = 0; i < n; i++) {
  55. c = *start;
  56. *start++ = ilBitReverseTable[c];
  57. }
  58. }
  59. #endif
  60. /* =========================== BITONAL DITHER CODE =============================== */
  61. /* Private data for error diffusion to bitonal, inited by Init() function. */
  62. typedef struct {
  63. long width; /* width of src/dst images */
  64. long srcRowBytes; /* bytes/row of src image */
  65. ilPtr pSrcPixels; /* ptr to start of src pixels */
  66. long dstRowBytes; /* bytes/row of dst image */
  67. ilPtr pDstPixels; /* ptr to start of dst pixels */
  68. ilBool blackIsZero; /* src image: true if 0 is black, else white */
  69. short *pError1, *pError2; /* ptr to error accumulator buffers */
  70. } ilBiDiffusionPrivRec, *ilBiDiffusionPrivPtr;
  71. /* Init() function: malloc and zero error accumulator buffers. */
  72. static ilError ilInitBiDiffusion (
  73. ilBiDiffusionPrivPtr pPriv,
  74. ilImageInfo *pSrcImage,
  75. ilImageInfo *pDstImage
  76. )
  77. {
  78. pPriv->width = pSrcImage->width;
  79. pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
  80. pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
  81. pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
  82. pPriv->pDstPixels = pDstImage->plane[0].pPixels;
  83. pPriv->blackIsZero = pSrcImage->pDes->blackIsZero;
  84. /* Create error accumulator buffers, 2 larger than width because the pixels
  85. above to the left and right are examined.
  86. */
  87. pPriv->pError1 = (short *)IL_MALLOC_ZERO (sizeof (short) * (pPriv->width + 2));
  88. pPriv->pError2 = (short *)IL_MALLOC_ZERO (sizeof (short) * (pPriv->width + 2));
  89. if (!pPriv->pError1 || !pPriv->pError2)
  90. return IL_ERROR_MALLOC;
  91. return IL_OK;
  92. }
  93. /* Cleanup() function: dispose error accumulator buffers. */
  94. static ilError ilCleanupBiDiffusion (
  95. ilBiDiffusionPrivPtr pPriv
  96. )
  97. {
  98. if (pPriv->pError1)
  99. IL_FREE (pPriv->pError1);
  100. if (pPriv->pError2)
  101. IL_FREE (pPriv->pError2);
  102. return IL_OK;
  103. }
  104. /* ----------------------- ilDiffuseGrayToBitonal ------------------------- */
  105. /* Dithers using error diffusion to bitonal.
  106. Input image: IL_DES_GRAY, IL_FORMAT_BYTE.
  107. Output image: IL_DES_BITONAL, IL_FORMAT_BIT
  108. */
  109. /* Execute() function: dither and pack the given # of src lines. */
  110. static ilError ilExecuteBiDiffusion (
  111. ilExecuteData *pData,
  112. long dstLine,
  113. long *pNLines /* ignored on input */
  114. )
  115. {
  116. #ifdef LSB_BIT_ORDER
  117. # define SPECIAL_MASK_BIT 0x00000001 /* for LSB bit order */
  118. # define SHIFT_MASK(m) ((m) <<= 1)
  119. #else
  120. # define SPECIAL_MASK_BIT 0x80000000 /* for MSB bit order */
  121. # define SHIFT_MASK(m) ((m) >>= 1)
  122. #endif
  123. ilBiDiffusionPrivPtr pPriv;
  124. long nLinesM1, nPixelsM1Init, nPixelsM1;
  125. short *pPrevError, *pError;
  126. int errorAcc, invert;
  127. long srcRowBytes, dstRowBytes;
  128. ilPtr pSrcLine, pDstLine;
  129. ilPtr pSrc;
  130. CARD32 mask, *pDst;
  131. CARD32 outLong;
  132. pPriv = (ilBiDiffusionPrivPtr)pData->pPrivate;
  133. srcRowBytes = pPriv->srcRowBytes;
  134. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  135. dstRowBytes = pPriv->dstRowBytes;
  136. pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
  137. nLinesM1 = *pNLines;
  138. if (nLinesM1 <= 0)
  139. return IL_OK;
  140. nLinesM1--;
  141. nPixelsM1Init = pPriv->width;
  142. if (nPixelsM1Init <= 0)
  143. return IL_OK;
  144. nPixelsM1Init--;
  145. /* Set "invert" to 0 if blackIsZero, else to 0xff, and xor each src pixel
  146. with invert. Thus if 0 is white, the xor turns 0 into 255, 1 into 254, etc.
  147. */
  148. invert = (pPriv->blackIsZero) ? 0 : 0xff;
  149. /* Dither: do Floyd-Steinberg dither (error diffusion) requiring src to be
  150. 256 gray levels. True error diffusion would map:
  151. (srcLevels-1)/(dstLevels-1) = 255/1
  152. but we will use 256/1 to make muls/divs easy. Use the following:
  153. 1/16 5/16 3/16
  154. 7/16 x
  155. where the fractions indicate what portion of the error from the surrounding
  156. pixels should be added to this pixels value (x) to determine dst pixel to
  157. write at "x".
  158. */
  159. do {
  160. pSrc = pSrcLine;
  161. pSrcLine += srcRowBytes;
  162. pDst = (CARD32 *)pDstLine;
  163. pDstLine += dstRowBytes;
  164. /* Point to error accumulator buffers and switch, so *pError becomes
  165. *pPrevError for next line. Bump ptrs by 1: prev scan line error is
  166. examined above to left and right: need zero extra value there to handle
  167. beginning/end of line.
  168. */
  169. pError = pPriv->pError1;
  170. pPrevError = pPriv->pError2;
  171. pPriv->pError1 = pPrevError;
  172. pPriv->pError2 = pError;
  173. pError++;
  174. pPrevError++;
  175. errorAcc = 0; /* holds error from pixel to the left */
  176. mask = SPECIAL_MASK_BIT;
  177. outLong = 0;
  178. nPixelsM1 = nPixelsM1Init;
  179. do {
  180. errorAcc *= 7; /* 7 * error to left */
  181. errorAcc += *(pPrevError - 1); /* 1 * error above left */
  182. errorAcc += 5 * *pPrevError++; /* 5 * error above */
  183. errorAcc += 3 * *pPrevError; /* 3 * error above right */
  184. errorAcc >>= 4; /* /16 */
  185. errorAcc += *pSrc++ ^ invert; /* + "x"; w/ blackIsZero handled */
  186. if (errorAcc >= 128) /* output white: don't set out bit */
  187. errorAcc -= 255; /* sub value of white from errorAcc */
  188. else /* output black: errorAcc -= 0 */
  189. outLong |= mask;
  190. *pError++ = errorAcc; /* store error into buffer */
  191. if (!(SHIFT_MASK(mask))) {
  192. flip_bits((ilPtr)&outLong, sizeof(outLong));
  193. *pDst++ = outLong;
  194. mask = SPECIAL_MASK_BIT;
  195. outLong = 0;
  196. }
  197. } while (--nPixelsM1 >= 0);
  198. if (mask != SPECIAL_MASK_BIT) { /* bits left in outLong; write them */
  199. flip_bits((ilPtr)&outLong, sizeof(outLong));
  200. *pDst++ = outLong;
  201. }
  202. } while (--nLinesM1 >= 0);
  203. return IL_OK;
  204. }
  205. /* Table exported to ilConvert(), declared in /ilc/ilconvert.h . */
  206. IL_PRIVATE ilConvertRec _ilDiffuseGrayToBitonal = {
  207. IL_NPF, /* CheckFormat() */
  208. IL_STD_FORMAT_BYTE, /* srcFormatCode */
  209. IL_NPF, /* AddElement() */
  210. IL_DES_BITONAL, /* pDstDes */
  211. IL_FORMAT_BIT, /* pDstFormat */
  212. sizeof (ilBiDiffusionPrivRec), /* nBytesPrivate */
  213. ilInitBiDiffusion, /* Init() */
  214. ilCleanupBiDiffusion, /* Cleanup() */
  215. IL_NPF, /* Destroy() */
  216. ilExecuteBiDiffusion /* Execute() */
  217. };
  218. /* =========================== BITONAL THRESHOLD CODE =============================== */
  219. /* ----------------------- ilThresholdGrayToBitonal ------------------------- */
  220. /* Convert gray to bitonal using a user-defined threshold.
  221. Input image: IL_DES_GRAY, IL_FORMAT_BYTE.
  222. Output image: IL_DES_BITONAL, IL_FORMAT_BIT
  223. */
  224. /* Private data for threshold conversion, inited by Init() function. */
  225. typedef struct {
  226. CARD32 *pThreshold; /* ptr to threshold for such gray->bi cvts */
  227. long width; /* width of src/dst images */
  228. long srcRowBytes; /* bytes/row of src image */
  229. ilPtr pSrcPixels; /* ptr to start of src pixels */
  230. long dstRowBytes; /* bytes/row of dst image */
  231. ilPtr pDstPixels; /* ptr to start of dst pixels */
  232. ilBool blackIsZero; /* true if 0 is black, else is white */
  233. } ilThresholdPrivRec, *ilThresholdPrivPtr;
  234. /* AddElement function: save copy of pThreshold (pOptionData to ilConvert())
  235. into private. This ptr is dereferenced every time the pipe is run, allowing
  236. the caller to change the threshold without reforming the pipe.
  237. */
  238. static ilError ilAddElementThreshold (
  239. ilThresholdPrivPtr pPriv,
  240. unsigned short *pPalette, /* not used */
  241. CARD32 *pThreshold /* pOptionData to ilConvert() */
  242. )
  243. {
  244. pPriv->pThreshold = pThreshold;
  245. return IL_OK;
  246. }
  247. /* Init() function: init the counter of "y" within private; load image pixel
  248. address and rowBytes into private for faster reference in Execute().
  249. */
  250. static ilError ilInitThreshold (
  251. ilThresholdPrivPtr pPriv,
  252. ilImageInfo *pSrcImage,
  253. ilImageInfo *pDstImage
  254. )
  255. {
  256. pPriv->width = pSrcImage->width;
  257. pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
  258. pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
  259. pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
  260. pPriv->pDstPixels = pDstImage->plane[0].pPixels;
  261. pPriv->blackIsZero = pSrcImage->pDes->blackIsZero;
  262. return IL_OK;
  263. }
  264. /* Execute() function: dither and pack the given # of src lines.
  265. */
  266. static ilError ilExecuteThreshold (
  267. ilExecuteData *pData,
  268. long dstLine,
  269. long *pNLines /* ignored on input */
  270. )
  271. {
  272. #ifdef LSB_BIT_ORDER
  273. # define SPECIAL_MASK_BIT 0x00000001 /* for LSB bit order */
  274. # define SHIFT_MASK(m) ((m) <<= 1)
  275. #else
  276. # define SPECIAL_MASK_BIT 0x80000000 /* for MSB bit order */
  277. # define SHIFT_MASK(m) ((m) >>= 1)
  278. #endif
  279. ilThresholdPrivPtr pPriv;
  280. long nLinesM1, nPixelsM1Init;
  281. long srcRowBytes, dstRowBytes;
  282. ilPtr pSrcLine, pDstLine;
  283. long nPixelsM1;
  284. ilPtr pSrc;
  285. CARD32 mask, *pDst;
  286. CARD32 outLong;
  287. ilByte threshold;
  288. pPriv = (ilThresholdPrivPtr)pData->pPrivate;
  289. threshold = *pPriv->pThreshold;
  290. srcRowBytes = pPriv->srcRowBytes;
  291. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  292. dstRowBytes = pPriv->dstRowBytes;
  293. pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
  294. nLinesM1 = *pNLines;
  295. if (nLinesM1 <= 0)
  296. return IL_OK;;
  297. nLinesM1--;
  298. nPixelsM1Init = pPriv->width;
  299. if (nPixelsM1Init <= 0)
  300. return IL_OK;
  301. nPixelsM1Init--;
  302. /* For each pixel, compare to the threshold and output black if
  303. < threshold (0 = black) or >= threshold (0 = white).
  304. */
  305. do {
  306. pSrc = pSrcLine;
  307. pSrcLine += srcRowBytes;
  308. pDst = (CARD32 *)pDstLine;
  309. pDstLine += dstRowBytes;
  310. mask = SPECIAL_MASK_BIT;
  311. outLong = 0;
  312. nPixelsM1 = nPixelsM1Init;
  313. if (pPriv->blackIsZero) {
  314. do {
  315. if (*pSrc++ < threshold)
  316. outLong |= mask;
  317. if (! SHIFT_MASK(mask)) {
  318. flip_bits((ilPtr)&outLong, sizeof(outLong));
  319. *pDst++ = outLong;
  320. mask = SPECIAL_MASK_BIT;
  321. outLong = 0;
  322. }
  323. } while (--nPixelsM1 >= 0);
  324. }
  325. else {
  326. do {
  327. if (*pSrc++ >= threshold)
  328. outLong |= mask;
  329. if (! SHIFT_MASK(mask)) {
  330. flip_bits((ilPtr)&outLong, sizeof(outLong));
  331. *pDst++ = outLong;
  332. mask = SPECIAL_MASK_BIT;
  333. outLong = 0;
  334. }
  335. } while (--nPixelsM1 >= 0);
  336. }
  337. /* If mask != left bit on, some bits in outLong; output them. Next line.
  338. */
  339. if (mask != SPECIAL_MASK_BIT) {
  340. flip_bits((ilPtr)&outLong, sizeof(outLong));
  341. *pDst++ = outLong;
  342. }
  343. } while (--nLinesM1 >= 0);
  344. return IL_OK;
  345. }
  346. /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
  347. Convert using a user-supplied threshold.
  348. Input image: IL_DES_GRAY (either form of blackIsZero), IL_FORMAT_BYTE.
  349. Output image: IL_DES_BITONAL, IL_FORMAT_BIT
  350. */
  351. IL_PRIVATE ilConvertRec _ilThresholdGrayToBitonal = {
  352. IL_NPF, /* CheckFormat() */
  353. IL_STD_FORMAT_BYTE, /* srcFormatCode */
  354. ilAddElementThreshold, /* AddElement() */
  355. IL_DES_BITONAL, /* pDstDes */
  356. IL_FORMAT_BIT, /* pDstFormat */
  357. sizeof (ilThresholdPrivRec), /* nBytesPrivate */
  358. ilInitThreshold, /* Init() */
  359. IL_NPF, /* Cleanup() */
  360. IL_NPF, /* Destroy() */
  361. ilExecuteThreshold /* Execute() */
  362. };