ilbigray.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  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: ilbigray.c /main/6 1996/09/24 17:12:45 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. /* /ilc/ilbigray.c : Contains ilBitonalToGray(), which adds a pipe element
  40. to convert the pipe image (which must be IL_BITONAL) to gray scale.
  41. */
  42. #include "ilint.h"
  43. #include "ilpipelem.h"
  44. #include "ilscaleint.h"
  45. #include "ilerrors.h"
  46. #ifdef LSB_BIT_ORDER
  47. extern void flip_bits(ilPtr start, unsigned n);
  48. #else
  49. # define flip_bits(s,n) /*EMPTY*/
  50. #endif
  51. #define IL_FILTER_SIZE 3 /* size of one side of filter square */
  52. #define IL_FILTER_SQUARE (IL_FILTER_SIZE*IL_FILTER_SIZE) /* square size of filter */
  53. #define MIN_DESIRED_STRIP 16 /* arbitrary: desired size of strips */
  54. /* Private data for pipe elements.
  55. See comments under ilInit9BitFilter() for a description of "filterValues".
  56. */
  57. typedef struct {
  58. /* Data inited by ilScaleBitonalToGray() when pipe element added. */
  59. ilByte filterValues [512]; /* should be first for efficiency! */
  60. ilBool bitonalOutput; /* true: outputting bitonal, else gray */
  61. int *pGrayThreshold; /* bitonal out only: ptr to threshold */
  62. int defaultGrayThreshold; /* pGrayThreshold -> this if defaulting */
  63. long srcWidth, srcHeight; /* size of src (pipe) image */
  64. long dstWidth, dstHeight; /* size of dst (output) image */
  65. long widthDiff, heightDiff; /* src - dst of width/height */
  66. long srcBufferHeight; /* height of perm src image, else 0 */
  67. /* Data inited by ilBiGrayInit() */
  68. unsigned int grayThreshold; /* *pGrayThreshold for this pass */
  69. long lineAcc; /* line accumulator for vert scaling */
  70. long srcRowBytes; /* bytes/row of src image */
  71. ilPtr pSrcPixels; /* ptr to start of src pixels */
  72. long dstRowBytes; /* bytes/row of dst image */
  73. ilPtr pDstPixels; /* ptr to start of dst pixels */
  74. } ilBiGrayPrivRec, *ilBiGrayPrivPtr;
  75. /* --------------------------- ilInit9BitFilter ---------------------------- */
  76. /* Init "*pTable", a 512 entry table, with the values to be indexed by a 9 bit
  77. number formed as follows:
  78. -----------
  79. | 8 | 7 | 6 | <- top source line
  80. -----------
  81. | 5 | 4 | 3 | <- bit "4" is logical center point
  82. -----------
  83. | 2 | 1 | 0 |
  84. -----------
  85. The bits are shifted into a 9 bit number, as above, then used as an index
  86. into the table. The value in entry 0xff (all bits on) should equal
  87. the max gray value ("nLevels" - 1).
  88. */
  89. static void ilInit9BitFilter (
  90. long srcWidth,
  91. long srcHeight,
  92. long dstWidth,
  93. long dstHeight,
  94. unsigned long nLevels,
  95. ilBool blackIsZero,
  96. ilByte *pTable
  97. )
  98. {
  99. double filter [IL_FILTER_SQUARE];
  100. double fraction, widthScale, heightScale, totalArea, widthSmall, heightSmall;
  101. long value, nLevelsM1;
  102. int i;
  103. /* Setup "filter" with the fractional (0..1) contribution of each pixel to
  104. the whole, in the bit order described above (bit 0 is the top-left pixel).
  105. The sum of all values should ~= 1.0. The portion of each pixel selected
  106. is based on a square of size "srcWidth/dstWidth" by "srcHeight/dstHeight",
  107. mapped over the source pixels, centered on pixel 4 (above). If the scale
  108. factor is greater than 3.0 in either direction, make it 3.0 (all pixels
  109. contribute equally in that direction.
  110. */
  111. widthScale = (double)srcWidth / (double)dstWidth;
  112. if (widthScale > 3.0)
  113. widthScale = 3.0;
  114. heightScale = (double)srcHeight / (double)dstHeight;
  115. if (heightScale > 3.0)
  116. heightScale = 3.0;
  117. totalArea = widthScale * heightScale;
  118. /* The center pixel is a 1x1 square.
  119. The four corner pixels are overlayed by a rect of width or height (wh) =
  120. (wh - 1) / 2: the whole side is "wh", - 1 for center, / 2 cause there are 2.
  121. The four side pixels have width/height of corner pixels, but other dim = 1.
  122. */
  123. filter [4] = 1.0 / totalArea;
  124. widthSmall = (widthScale - 1.0) / 2.0;
  125. heightSmall = (heightScale - 1.0) / 2.0;
  126. filter [0] = filter [2] = filter [6] = filter [8] =
  127. (widthSmall * heightSmall) / totalArea;
  128. filter [1] = filter [7] = heightSmall / totalArea;
  129. filter [3] = filter [5] = widthSmall / totalArea;
  130. /* Convert the filter to an array indexed by a 9 bit number: the filter bits
  131. as shown above, in order "876543210". If whitePixel is 0, add the filter
  132. fraction if bit is off. If whitePixel not zero than add the filter fraction
  133. if bit is on.
  134. */
  135. nLevelsM1 = nLevels - 1;
  136. if (!blackIsZero) {
  137. for (i = 0; i < 512; i++) {
  138. fraction = 0.0;
  139. if (!(i & 1)) fraction += filter [0];
  140. if (!(i & 2)) fraction += filter [1];
  141. if (!(i & 4)) fraction += filter [2];
  142. if (!(i & 8)) fraction += filter [3];
  143. if (!(i & 16)) fraction += filter [4];
  144. if (!(i & 32)) fraction += filter [5];
  145. if (!(i & 64)) fraction += filter [6];
  146. if (!(i & 128)) fraction += filter [7];
  147. if (!(i & 256)) fraction += filter [8];
  148. value = fraction * nLevelsM1 + 0.5;
  149. if (value > nLevelsM1)
  150. value = nLevelsM1;
  151. pTable [i] = value;
  152. }
  153. }
  154. else { /* a 1 is white */
  155. for (i = 0; i < 512; i++) {
  156. fraction = 0.0;
  157. if (i & 1) fraction += filter [0];
  158. if (i & 2) fraction += filter [1];
  159. if (i & 4) fraction += filter [2];
  160. if (i & 8) fraction += filter [3];
  161. if (i & 16) fraction += filter [4];
  162. if (i & 32) fraction += filter [5];
  163. if (i & 64) fraction += filter [6];
  164. if (i & 128) fraction += filter [7];
  165. if (i & 256) fraction += filter [8];
  166. value = fraction * nLevelsM1 + 0.5;
  167. if (value > nLevelsM1)
  168. value = nLevelsM1;
  169. pTable [i] = value;
  170. }
  171. }
  172. }
  173. /* --------------------- ilBiGrayInit -------------------------- */
  174. /* Init() function: copy values from given images to private for fast reference.
  175. */
  176. static ilError ilBiGrayInit (
  177. ilBiGrayPrivPtr pPriv,
  178. ilImageInfo *pSrcImage,
  179. ilImageInfo *pDstImage
  180. )
  181. {
  182. pPriv->lineAcc = pPriv->heightDiff;
  183. pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
  184. pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
  185. pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
  186. pPriv->pDstPixels = pDstImage->plane[0].pPixels;
  187. /* Copy caller's threshold if scaling to bitonal.
  188. */
  189. if (pPriv->bitonalOutput)
  190. pPriv->grayThreshold = *pPriv->pGrayThreshold;
  191. return IL_OK;
  192. }
  193. /* --------------------- ilBiGrayExecute -------------------------- */
  194. /* Execute() pipe element function for scaling bitonal to gray.
  195. */
  196. static ilError ilBiGrayExecute (
  197. ilExecuteData *pData,
  198. long dstLine,
  199. long *pNLines
  200. )
  201. {
  202. #define ULPTR CARD32 *
  203. #ifdef LSB_BIT_ORDER
  204. # define SPECIAL_MASK_BIT 0x00000001 /* for LSB bit order */
  205. # define SHIFT_MASK(m) ((m) <<= 1)
  206. #else
  207. # define SPECIAL_MASK_BIT 0x80000000 /* for MSB bit order */
  208. # define SHIFT_MASK(m) ((m) >>= 1)
  209. #endif
  210. long nLines, nLinesWritten;
  211. ilPtr pSrcLine, pDstLine;
  212. long colAcc, nDstBits, dstWidth, bottomLine, line;
  213. long srcBytesAbove, srcBytesBelow;
  214. ilBiGrayPrivPtr pPriv;
  215. CARD32 index, *pSrc;
  216. int shift, bitNumber;
  217. /* Point pSrcLine to srcLine: = middle line of 3x3 matrix.
  218. Set bottomLine to last available line in the buffer.
  219. */
  220. pPriv = (ilBiGrayPrivPtr)pData->pPrivate;
  221. dstWidth = pPriv->dstWidth;
  222. pSrcLine = pPriv->pSrcPixels + pData->srcLine * pPriv->srcRowBytes;
  223. pDstLine = pPriv->pDstPixels + dstLine * pPriv->dstRowBytes;
  224. nLines = *pNLines;
  225. if (nLines <= 0)
  226. return 0; /* no lines, EXIT */
  227. if (pPriv->srcBufferHeight)
  228. bottomLine = pPriv->srcBufferHeight - 1;
  229. else bottomLine = pData->srcLine + nLines - 1;
  230. line = pData->srcLine - 1; /* line of top of 3x3 matrix */
  231. nLinesWritten = 0;
  232. while (TRUE) {
  233. while (pPriv->lineAcc > 0) {
  234. if (nLines-- <= 0) goto BGLinesDone;
  235. pPriv->lineAcc -= pPriv->dstHeight;
  236. pSrcLine += pPriv->srcRowBytes;
  237. line++;
  238. }
  239. if (nLines-- <= 0) goto BGLinesDone;
  240. pPriv->lineAcc += pPriv->heightDiff;
  241. /* Algorithm: skip src bits, using basic scale algorithm. To form dst bit,
  242. form 9 bit value from 3x3, with top bits in high order bits. Lookup
  243. the 9 bit value in table of correct gray scale. "bitNumber" is the
  244. # of the left bit of 3x3; 31 = left bit of long. If bitNumber is < 2,
  245. the bits cross a long boundary: get bits from bytes, low order of this
  246. long and high order byte of next long.
  247. pSrc will point to the middle line of 3x3; the line above is
  248. "-srcBytesAbove" away; the line below is "srcBytesBelow" away. If the 3x3
  249. is outside of the buffer being read, set "srcBytesAbove/Below" to 0,
  250. causing the middle line to be re-read and replicated to replace the
  251. unaccessible line.
  252. */
  253. srcBytesAbove = (line < 0) ? 0 : pPriv->srcRowBytes;
  254. srcBytesBelow = ((line + 2) > bottomLine) ? 0 : pPriv->srcRowBytes;
  255. nDstBits = pPriv->dstWidth;
  256. /* Set pSrc and bitNumber to point to the rightmost bit of the long before
  257. the first long. The "colAcc > 0" check below will be true, causing a bump
  258. to the next bit (first bit in row), _except_ when "widthDiff" is 0 (no
  259. hori scaling). In this case, set colAcc to 1, forcing the first colAcc>0
  260. check to be true and bumping past first bit - the rest proceeds normally.
  261. */
  262. pSrc = ((ULPTR)pSrcLine) - 1;
  263. bitNumber = 0;
  264. colAcc = pPriv->widthDiff;
  265. if (colAcc <= 0)
  266. colAcc = 1;
  267. /* If bitonal output, logically produce a gray pixel, then output a 1 if
  268. gray is < threshold.
  269. */
  270. if (pPriv->bitonalOutput) {
  271. ULPTR pDst;
  272. CARD32 mask, outLong;
  273. pDst = (ULPTR)pDstLine;
  274. mask = SPECIAL_MASK_BIT;
  275. outLong = 0; /* fill with 1's as necessary */
  276. while (TRUE) {
  277. while (colAcc > 0) {
  278. colAcc -= dstWidth;
  279. if (--bitNumber < 0) {
  280. pSrc++;
  281. bitNumber = 31;
  282. }
  283. }
  284. colAcc += pPriv->widthDiff;
  285. /* If done and mask != left bit on, output bits in "outLong". */
  286. if (nDstBits <= 0) {
  287. if (mask != SPECIAL_MASK_BIT) {
  288. flip_bits((ilPtr)&outLong, sizeof(outLong));
  289. *pDst++ = outLong;
  290. }
  291. break; /* done this line; exit while */
  292. }
  293. if (--nDstBits <= 0) {
  294. INT32 rightBit = (((ilPtr)pSrc - pSrcLine) << 3) + 34 - bitNumber;
  295. if ((rightBit > pPriv->srcWidth) && (pPriv->srcWidth > 3))
  296. if (++bitNumber > 31) {bitNumber = 0; pSrc--; }
  297. }
  298. if (bitNumber >= 2) {
  299. shift = bitNumber - 2;
  300. index = (*((ULPTR)((ilPtr)pSrc - srcBytesAbove)) >> shift) & 7;
  301. index <<= 3;
  302. index |= (*pSrc >> shift) & 7;
  303. index <<= 3;
  304. index |= (*((ULPTR)((ilPtr)pSrc + srcBytesBelow)) >> shift) & 7;
  305. }
  306. else {
  307. ilPtr pSrcTemp = (ilPtr)pSrc - srcBytesAbove + 3;
  308. shift = 6 + bitNumber;
  309. index = ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
  310. index <<= 3;
  311. pSrcTemp += srcBytesAbove;
  312. index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
  313. index <<= 3;
  314. pSrcTemp += srcBytesBelow;
  315. index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
  316. }
  317. if (pPriv->filterValues [index] < pPriv->grayThreshold)
  318. outLong |= mask;
  319. if (!(SHIFT_MASK(mask))) {
  320. flip_bits((ilPtr)&outLong, sizeof(outLong));
  321. *pDst++ = outLong;
  322. mask = SPECIAL_MASK_BIT;
  323. outLong = 0;
  324. }
  325. if (--bitNumber < 0) { /* next src bit */
  326. pSrc++;
  327. bitNumber = 31;
  328. }
  329. } /* END column loop */
  330. }
  331. else { /* outputting gray */
  332. ilPtr pDst;
  333. pDst = pDstLine;
  334. while (TRUE) {
  335. while (colAcc > 0) {
  336. colAcc -= dstWidth;
  337. if (--bitNumber < 0) {
  338. pSrc++;
  339. bitNumber = 31;
  340. }
  341. }
  342. colAcc += pPriv->widthDiff;
  343. if (nDstBits <= 0)
  344. break; /* done this line; exit while */
  345. if (--nDstBits <= 0) {
  346. INT32 rightBit = (((ilPtr)pSrc - pSrcLine) << 3) + 34 - bitNumber;
  347. if ((rightBit > pPriv->srcWidth) && (pPriv->srcWidth > 3))
  348. if (++bitNumber > 31) {bitNumber = 0; pSrc--; }
  349. }
  350. if (bitNumber >= 2) {
  351. shift = bitNumber - 2;
  352. index = (*((ULPTR)((ilPtr)pSrc - srcBytesAbove)) >> shift) & 7;
  353. index <<= 3;
  354. index |= (*pSrc >> shift) & 7;
  355. index <<= 3;
  356. index |= (*((ULPTR)((ilPtr)pSrc + srcBytesBelow)) >> shift) & 7;
  357. }
  358. else {
  359. ilPtr pSrcTemp = (ilPtr)pSrc - srcBytesAbove + 3;
  360. shift = 6 + bitNumber;
  361. index = ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
  362. index <<= 3;
  363. pSrcTemp += srcBytesAbove;
  364. index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
  365. index <<= 3;
  366. pSrcTemp += srcBytesBelow;
  367. index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
  368. }
  369. *pDst++ = pPriv->filterValues [index];
  370. if (--bitNumber < 0) { /* next src bit */
  371. pSrc++;
  372. bitNumber = 31;
  373. }
  374. } /* END column loop */
  375. }
  376. /* Line done; next src, dst lines; inc line index and # lines written.
  377. */
  378. pSrcLine += pPriv->srcRowBytes;
  379. line++;
  380. pDstLine += pPriv->dstRowBytes;
  381. nLinesWritten++;
  382. } /* END loop, one dst line */
  383. BGLinesDone:
  384. *pNLines = nLinesWritten;
  385. return IL_OK;
  386. }
  387. /* ------------------------- ilScaleBitonalToGray ---------------------------- */
  388. /* Called by ilScale().
  389. Adds an element to "pipe" to scale the pipe image to "dstWidth" by "dstHeight"
  390. which both must be > 0. The input pipe image must be a bitonal,
  391. bit-per-pixel image, with the given "blackIsZero". "pInfo" points to the
  392. pipe info, "dstWidth/Height" is the (> 0) size to scale to, and nGrayLevels
  393. is the number of levels of gray. The output image is a gray image.
  394. Only a scale down in both directions is allowed; the following must be true:
  395. srcWidth must be >= dstWidth and srcHeight must be >= dstHeight!
  396. */
  397. IL_PRIVATE void _ilScaleBitonalToGray (
  398. ilPipe pipe,
  399. unsigned long dstWidth,
  400. unsigned long dstHeight,
  401. unsigned long nGrayLevels,
  402. ilBool blackIsZero,
  403. ilPipeInfo *pInfo
  404. )
  405. {
  406. ilBiGrayPrivPtr pPriv;
  407. ilDstElementData dstData;
  408. ilImageDes des;
  409. /* Idiot check the number of gray levels */
  410. if ((nGrayLevels < 2) || (nGrayLevels > 256)) {
  411. ilDeclarePipeInvalid (pipe, IL_ERROR_LEVELS_PER_SAMPLE);
  412. return; /* EXIT */
  413. }
  414. /* Add a filter to do the scale, then init *pPriv.
  415. */
  416. dstData.producerObject = (ilObject)NULL;
  417. des = *IL_DES_GRAY;
  418. des.nLevelsPerSample[0] = nGrayLevels;
  419. dstData.pDes = &des;
  420. dstData.pFormat = IL_FORMAT_BYTE;
  421. dstData.width = dstWidth;
  422. dstData.height = dstHeight;
  423. dstData.stripHeight = ((dstHeight * pInfo->recommendedStripHeight) / pInfo->height) + 1;
  424. dstData.constantStrip = FALSE;
  425. dstData.pPalette = (unsigned short *)NULL;
  426. pPriv = (ilBiGrayPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof (ilBiGrayPrivRec),
  427. IL_ADD_PIPE_HOLD_SRC, (ilSrcElementData *)NULL, &dstData,
  428. ilBiGrayInit, IL_NPF, IL_NPF, ilBiGrayExecute, NULL, 0);
  429. if (!pPriv)
  430. return;
  431. /* Pipe element added, init pPriv. If not a tempImage, reading directly from
  432. a permanent image: set srcHeight to image height; else set to 0.
  433. */
  434. pPriv->bitonalOutput = FALSE;
  435. pPriv->srcWidth = pInfo->width;
  436. pPriv->srcHeight = pInfo->height;
  437. pPriv->dstWidth = dstWidth;
  438. pPriv->dstHeight = dstHeight;
  439. pPriv->widthDiff = pInfo->width - dstWidth;
  440. pPriv->heightDiff = pInfo->height - dstHeight;
  441. if (!pInfo->tempImage)
  442. pPriv->srcBufferHeight = pInfo->height;
  443. else pPriv->srcBufferHeight = 0;
  444. /* Init the filter table in private based on scale factors and # gray levels.
  445. */
  446. ilInit9BitFilter (pPriv->srcWidth, pPriv->srcHeight, pPriv->dstWidth,
  447. pPriv->dstHeight, nGrayLevels, blackIsZero, pPriv->filterValues);
  448. pipe->context->error = IL_OK;
  449. }
  450. /* ------------------------- ilAreaScaleBitonal ---------------------------- */
  451. /* Called by ilScale().
  452. Adds an element to "pipe" to scale the pipe image to "dstWidth" by "dstHeight"
  453. which both must be > 0. The input pipe image must be a bitonal,
  454. bit-per-pixel image, with _any_ "blackIsZero". The resulting image is of the
  455. same type. "pInfo" points to the pipe info, "dstWidth/Height" is the (> 0) size
  456. to scale to.
  457. Only a scale down in both directions is allowed; the following must be true:
  458. srcWidth must be >= dstWidth and srcHeight must be >= dstHeight!
  459. Logically the same as ilScaleBitonalToGray(): a gray byte is produced for
  460. each destination pixel, using 256 levels of gray. If that byte is
  461. >= "*pGrayThreshold"; a white pixel is written; else a black pixel is written.
  462. NOTE: the value at "*pGrayThreshold" is read each time the pipe is executed
  463. (during Init()); the caller change its value and get different results without
  464. recreating the pipe. If "pGrayThreshold" is NULL, a default value is used.
  465. */
  466. IL_PRIVATE void _ilAreaScaleBitonal (
  467. ilPipe pipe,
  468. unsigned long dstWidth,
  469. unsigned long dstHeight,
  470. int *pGrayThreshold,
  471. ilPipeInfo *pInfo
  472. )
  473. {
  474. ilBiGrayPrivPtr pPriv;
  475. ilDstElementData dstData;
  476. #define DEFAULT_GRAY_THRESHOLD 128 /* assumes 256 levels */
  477. /* Add a filter to do the scale, then init *pPriv.
  478. */
  479. dstData.producerObject = (ilObject)NULL;
  480. dstData.pDes = (ilImageDes *)NULL;
  481. dstData.pFormat = IL_FORMAT_BIT;
  482. dstData.width = dstWidth;
  483. dstData.height = dstHeight;
  484. dstData.stripHeight = ((dstHeight * pInfo->recommendedStripHeight) / pInfo->height) + 1;
  485. dstData.constantStrip = FALSE;
  486. dstData.pPalette = (unsigned short *)NULL;
  487. pPriv = (ilBiGrayPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof (ilBiGrayPrivRec),
  488. IL_ADD_PIPE_HOLD_SRC, (ilSrcElementData *)NULL, &dstData,
  489. ilBiGrayInit, IL_NPF, IL_NPF, ilBiGrayExecute, NULL, 0);
  490. if (!pPriv)
  491. return;
  492. /* Pipe element added, init pPriv. If not a tempImage, reading directly from
  493. a permanent image: set srcHeight to image height; else set to 0.
  494. */
  495. pPriv->bitonalOutput = TRUE;
  496. if (pGrayThreshold)
  497. pPriv->pGrayThreshold = pGrayThreshold;
  498. else {
  499. pPriv->defaultGrayThreshold = DEFAULT_GRAY_THRESHOLD;
  500. pPriv->pGrayThreshold = &pPriv->defaultGrayThreshold;
  501. }
  502. pPriv->srcWidth = pInfo->width;
  503. pPriv->srcHeight = pInfo->height;
  504. pPriv->dstWidth = dstWidth;
  505. pPriv->dstHeight = dstHeight;
  506. pPriv->widthDiff = pInfo->width - dstWidth;
  507. pPriv->heightDiff = pInfo->height - dstHeight;
  508. if (!pInfo->tempImage)
  509. pPriv->srcBufferHeight = pInfo->height;
  510. else pPriv->srcBufferHeight = 0;
  511. /* Init the filter table in private based on scale factors and 256 gray levels.
  512. Note that "blackIsZero" is passed as FALSE below, because we want to output
  513. the same blackIsZero as input. We output a zero when the gray is
  514. >= threshold; this works for either sense of blackIsZero.
  515. */
  516. ilInit9BitFilter (pPriv->srcWidth, pPriv->srcHeight, pPriv->dstWidth,
  517. pPriv->dstHeight, 256, FALSE, pPriv->filterValues);
  518. pipe->context->error = IL_OK;
  519. }