2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: ilbigray.c /main/6 1996/09/24 17:12:45 drk $ */
24 /**---------------------------------------------------------------------
26 *** (c)Copyright 1991 Hewlett-Packard Co.
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).
38 ***-------------------------------------------------------------------*/
40 /* /ilc/ilbigray.c : Contains ilBitonalToGray(), which adds a pipe element
41 to convert the pipe image (which must be IL_BITONAL) to gray scale.
45 #include "ilpipelem.h"
46 #include "ilscaleint.h"
50 extern void flip_bits(register ilPtr start, register unsigned n);
52 # define flip_bits(s,n) /*EMPTY*/
55 #define IL_FILTER_SIZE 3 /* size of one side of filter square */
56 #define IL_FILTER_SQUARE (IL_FILTER_SIZE*IL_FILTER_SIZE) /* square size of filter */
57 #define MIN_DESIRED_STRIP 16 /* arbitrary: desired size of strips */
59 /* Private data for pipe elements.
60 See comments under ilInit9BitFilter() for a description of "filterValues".
64 /* Data inited by ilScaleBitonalToGray() when pipe element added. */
65 ilByte filterValues [512]; /* should be first for efficiency! */
66 ilBool bitonalOutput; /* true: outputting bitonal, else gray */
67 int *pGrayThreshold; /* bitonal out only: ptr to threshold */
68 int defaultGrayThreshold; /* pGrayThreshold -> this if defaulting */
69 long srcWidth, srcHeight; /* size of src (pipe) image */
70 long dstWidth, dstHeight; /* size of dst (output) image */
71 long widthDiff, heightDiff; /* src - dst of width/height */
72 long srcBufferHeight; /* height of perm src image, else 0 */
74 /* Data inited by ilBiGrayInit() */
75 unsigned int grayThreshold; /* *pGrayThreshold for this pass */
76 long lineAcc; /* line accumulator for vert scaling */
77 long srcRowBytes; /* bytes/row of src image */
78 ilPtr pSrcPixels; /* ptr to start of src pixels */
79 long dstRowBytes; /* bytes/row of dst image */
80 ilPtr pDstPixels; /* ptr to start of dst pixels */
81 } ilBiGrayPrivRec, *ilBiGrayPrivPtr;
84 /* --------------------------- ilInit9BitFilter ---------------------------- */
85 /* Init "*pTable", a 512 entry table, with the values to be indexed by a 9 bit
86 number formed as follows:
88 | 8 | 7 | 6 | <- top source line
90 | 5 | 4 | 3 | <- bit "4" is logical center point
94 The bits are shifted into a 9 bit number, as above, then used as an index
95 into the table. The value in entry 0xff (all bits on) should equal
96 the max gray value ("nLevels" - 1).
98 static void ilInit9BitFilter (
103 unsigned long nLevels,
108 double filter [IL_FILTER_SQUARE];
109 double fraction, widthScale, heightScale, totalArea, widthSmall, heightSmall;
110 long value, nLevelsM1;
113 /* Setup "filter" with the fractional (0..1) contribution of each pixel to
114 the whole, in the bit order described above (bit 0 is the top-left pixel).
115 The sum of all values should ~= 1.0. The portion of each pixel selected
116 is based on a square of size "srcWidth/dstWidth" by "srcHeight/dstHeight",
117 mapped over the source pixels, centered on pixel 4 (above). If the scale
118 factor is greater than 3.0 in either direction, make it 3.0 (all pixels
119 contribute equally in that direction.
121 widthScale = (double)srcWidth / (double)dstWidth;
122 if (widthScale > 3.0)
124 heightScale = (double)srcHeight / (double)dstHeight;
125 if (heightScale > 3.0)
127 totalArea = widthScale * heightScale;
129 /* The center pixel is a 1x1 square.
130 The four corner pixels are overlayed by a rect of width or height (wh) =
131 (wh - 1) / 2: the whole side is "wh", - 1 for center, / 2 cause there are 2.
132 The four side pixels have width/height of corner pixels, but other dim = 1.
134 filter [4] = 1.0 / totalArea;
135 widthSmall = (widthScale - 1.0) / 2.0;
136 heightSmall = (heightScale - 1.0) / 2.0;
137 filter [0] = filter [2] = filter [6] = filter [8] =
138 (widthSmall * heightSmall) / totalArea;
139 filter [1] = filter [7] = heightSmall / totalArea;
140 filter [3] = filter [5] = widthSmall / totalArea;
142 /* Convert the filter to an array indexed by a 9 bit number: the filter bits
143 as shown above, in order "876543210". If whitePixel is 0, add the filter
144 fraction if bit is off. If whitePixel not zero than add the filter fraction
147 nLevelsM1 = nLevels - 1;
149 for (i = 0; i < 512; i++) {
151 if (!(i & 1)) fraction += filter [0];
152 if (!(i & 2)) fraction += filter [1];
153 if (!(i & 4)) fraction += filter [2];
154 if (!(i & 8)) fraction += filter [3];
155 if (!(i & 16)) fraction += filter [4];
156 if (!(i & 32)) fraction += filter [5];
157 if (!(i & 64)) fraction += filter [6];
158 if (!(i & 128)) fraction += filter [7];
159 if (!(i & 256)) fraction += filter [8];
160 value = fraction * nLevelsM1 + 0.5;
161 if (value > nLevelsM1)
166 else { /* a 1 is white */
167 for (i = 0; i < 512; i++) {
169 if (i & 1) fraction += filter [0];
170 if (i & 2) fraction += filter [1];
171 if (i & 4) fraction += filter [2];
172 if (i & 8) fraction += filter [3];
173 if (i & 16) fraction += filter [4];
174 if (i & 32) fraction += filter [5];
175 if (i & 64) fraction += filter [6];
176 if (i & 128) fraction += filter [7];
177 if (i & 256) fraction += filter [8];
178 value = fraction * nLevelsM1 + 0.5;
179 if (value > nLevelsM1)
186 /* --------------------- ilBiGrayInit -------------------------- */
187 /* Init() function: copy values from given images to private for fast reference.
189 static ilError ilBiGrayInit (
190 ilBiGrayPrivPtr pPriv,
191 ilImageInfo *pSrcImage,
192 ilImageInfo *pDstImage
196 pPriv->lineAcc = pPriv->heightDiff;
197 pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
198 pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
199 pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
200 pPriv->pDstPixels = pDstImage->plane[0].pPixels;
202 /* Copy caller's threshold if scaling to bitonal.
204 if (pPriv->bitonalOutput)
205 pPriv->grayThreshold = *pPriv->pGrayThreshold;
210 /* --------------------- ilBiGrayExecute -------------------------- */
211 /* Execute() pipe element function for scaling bitonal to gray.
213 static ilError ilBiGrayExecute (
214 ilExecuteData *pData,
219 #define ULPTR CARD32 *
221 # define SPECIAL_MASK_BIT 0x00000001 /* for LSB bit order */
222 # define SHIFT_MASK(m) ((m) <<= 1)
224 # define SPECIAL_MASK_BIT 0x80000000 /* for MSB bit order */
225 # define SHIFT_MASK(m) ((m) >>= 1)
227 long nLines, nLinesWritten;
228 ilPtr pSrcLine, pDstLine;
229 long colAcc, nDstBits, dstWidth, bottomLine, line;
230 register long srcBytesAbove, srcBytesBelow;
231 register ilBiGrayPrivPtr pPriv;
232 register CARD32 index, *pSrc;
233 register int shift, bitNumber;
235 /* Point pSrcLine to srcLine: = middle line of 3x3 matrix.
236 Set bottomLine to last available line in the buffer.
238 pPriv = (ilBiGrayPrivPtr)pData->pPrivate;
239 dstWidth = pPriv->dstWidth;
240 pSrcLine = pPriv->pSrcPixels + pData->srcLine * pPriv->srcRowBytes;
241 pDstLine = pPriv->pDstPixels + dstLine * pPriv->dstRowBytes;
245 return; /* no lines, EXIT */
246 if (pPriv->srcBufferHeight)
247 bottomLine = pPriv->srcBufferHeight - 1;
248 else bottomLine = pData->srcLine + nLines - 1;
249 line = pData->srcLine - 1; /* line of top of 3x3 matrix */
253 while (pPriv->lineAcc > 0) {
254 if (nLines-- <= 0) goto BGLinesDone;
255 pPriv->lineAcc -= pPriv->dstHeight;
256 pSrcLine += pPriv->srcRowBytes;
259 if (nLines-- <= 0) goto BGLinesDone;
260 pPriv->lineAcc += pPriv->heightDiff;
262 /* Algorithm: skip src bits, using basic scale algorithm. To form dst bit,
263 form 9 bit value from 3x3, with top bits in high order bits. Lookup
264 the 9 bit value in table of correct gray scale. "bitNumber" is the
265 # of the left bit of 3x3; 31 = left bit of long. If bitNumber is < 2,
266 the bits cross a long boundary: get bits from bytes, low order of this
267 long and high order byte of next long.
268 pSrc will point to the middle line of 3x3; the line above is
269 "-srcBytesAbove" away; the line below is "srcBytesBelow" away. If the 3x3
270 is outside of the buffer being read, set "srcBytesAbove/Below" to 0,
271 causing the middle line to be re-read and replicated to replace the
274 srcBytesAbove = (line < 0) ? 0 : pPriv->srcRowBytes;
275 srcBytesBelow = ((line + 2) > bottomLine) ? 0 : pPriv->srcRowBytes;
276 nDstBits = pPriv->dstWidth;
278 /* Set pSrc and bitNumber to point to the rightmost bit of the long before
279 the first long. The "colAcc > 0" check below will be true, causing a bump
280 to the next bit (first bit in row), _except_ when "widthDiff" is 0 (no
281 hori scaling). In this case, set colAcc to 1, forcing the first colAcc>0
282 check to be true and bumping past first bit - the rest proceeds normally.
284 pSrc = ((ULPTR)pSrcLine) - 1;
286 colAcc = pPriv->widthDiff;
290 /* If bitonal output, logically produce a gray pixel, then output a 1 if
293 if (pPriv->bitonalOutput) {
295 CARD32 mask, outLong;
297 pDst = (ULPTR)pDstLine;
298 mask = SPECIAL_MASK_BIT;
299 outLong = 0; /* fill with 1's as necessary */
304 if (--bitNumber < 0) {
309 colAcc += pPriv->widthDiff;
311 /* If done and mask != left bit on, output bits in "outLong". */
313 if (mask != SPECIAL_MASK_BIT) {
314 flip_bits((ilPtr)&outLong, sizeof(outLong));
317 break; /* done this line; exit while */
319 if (--nDstBits <= 0) {
320 INT32 rightBit = (((ilPtr)pSrc - pSrcLine) << 3) + 34 - bitNumber;
321 if ((rightBit > pPriv->srcWidth) && (pPriv->srcWidth > 3))
322 if (++bitNumber > 31) {bitNumber = 0; pSrc--; }
324 if (bitNumber >= 2) {
325 shift = bitNumber - 2;
326 index = (*((ULPTR)((ilPtr)pSrc - srcBytesAbove)) >> shift) & 7;
328 index |= (*pSrc >> shift) & 7;
330 index |= (*((ULPTR)((ilPtr)pSrc + srcBytesBelow)) >> shift) & 7;
333 ilPtr pSrcTemp = (ilPtr)pSrc - srcBytesAbove + 3;
334 shift = 6 + bitNumber;
335 index = ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
337 pSrcTemp += srcBytesAbove;
338 index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
340 pSrcTemp += srcBytesBelow;
341 index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
343 if (pPriv->filterValues [index] < pPriv->grayThreshold)
345 if (!(SHIFT_MASK(mask))) {
346 flip_bits((ilPtr)&outLong, sizeof(outLong));
348 mask = SPECIAL_MASK_BIT;
351 if (--bitNumber < 0) { /* next src bit */
355 } /* END column loop */
357 else { /* outputting gray */
364 if (--bitNumber < 0) {
369 colAcc += pPriv->widthDiff;
371 break; /* done this line; exit while */
372 if (--nDstBits <= 0) {
373 INT32 rightBit = (((ilPtr)pSrc - pSrcLine) << 3) + 34 - bitNumber;
374 if ((rightBit > pPriv->srcWidth) && (pPriv->srcWidth > 3))
375 if (++bitNumber > 31) {bitNumber = 0; pSrc--; }
377 if (bitNumber >= 2) {
378 shift = bitNumber - 2;
379 index = (*((ULPTR)((ilPtr)pSrc - srcBytesAbove)) >> shift) & 7;
381 index |= (*pSrc >> shift) & 7;
383 index |= (*((ULPTR)((ilPtr)pSrc + srcBytesBelow)) >> shift) & 7;
386 ilPtr pSrcTemp = (ilPtr)pSrc - srcBytesAbove + 3;
387 shift = 6 + bitNumber;
388 index = ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
390 pSrcTemp += srcBytesAbove;
391 index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
393 pSrcTemp += srcBytesBelow;
394 index |= ((CARD32)((*pSrcTemp << 8) | *(pSrcTemp + 1)) >> shift) & 7;
396 *pDst++ = pPriv->filterValues [index];
397 if (--bitNumber < 0) { /* next src bit */
401 } /* END column loop */
404 /* Line done; next src, dst lines; inc line index and # lines written.
406 pSrcLine += pPriv->srcRowBytes;
408 pDstLine += pPriv->dstRowBytes;
410 } /* END loop, one dst line */
413 *pNLines = nLinesWritten;
418 /* ------------------------- ilScaleBitonalToGray ---------------------------- */
419 /* Called by ilScale().
420 Adds an element to "pipe" to scale the pipe image to "dstWidth" by "dstHeight"
421 which both must be > 0. The input pipe image must be a bitonal,
422 bit-per-pixel image, with the given "blackIsZero". "pInfo" points to the
423 pipe info, "dstWidth/Height" is the (> 0) size to scale to, and nGrayLevels
424 is the number of levels of gray. The output image is a gray image.
425 Only a scale down in both directions is allowed; the following must be true:
426 srcWidth must be >= dstWidth and srcHeight must be >= dstHeight!
428 IL_PRIVATE void _ilScaleBitonalToGray (
430 unsigned long dstWidth,
431 unsigned long dstHeight,
432 unsigned long nGrayLevels,
437 register ilBiGrayPrivPtr pPriv;
438 ilDstElementData dstData;
442 /* Idiot check the number of gray levels */
444 if ((nGrayLevels < 2) || (nGrayLevels > 256)) {
445 ilDeclarePipeInvalid (pipe, IL_ERROR_LEVELS_PER_SAMPLE);
449 /* Add a filter to do the scale, then init *pPriv.
451 dstData.producerObject = (ilObject)NULL;
453 des.nLevelsPerSample[0] = nGrayLevels;
455 dstData.pFormat = IL_FORMAT_BYTE;
456 dstData.width = dstWidth;
457 dstData.height = dstHeight;
458 dstData.stripHeight = ((dstHeight * pInfo->recommendedStripHeight) / pInfo->height) + 1;
459 dstData.constantStrip = FALSE;
460 dstData.pPalette = (unsigned short *)NULL;
461 pPriv = (ilBiGrayPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof (ilBiGrayPrivRec),
462 IL_ADD_PIPE_HOLD_SRC, (ilSrcElementData *)NULL, &dstData,
463 ilBiGrayInit, IL_NPF, IL_NPF, ilBiGrayExecute, NULL, 0);
467 /* Pipe element added, init pPriv. If not a tempImage, reading directly from
468 a permanent image: set srcHeight to image height; else set to 0.
470 pPriv->bitonalOutput = FALSE;
471 pPriv->srcWidth = pInfo->width;
472 pPriv->srcHeight = pInfo->height;
473 pPriv->dstWidth = dstWidth;
474 pPriv->dstHeight = dstHeight;
475 pPriv->widthDiff = pInfo->width - dstWidth;
476 pPriv->heightDiff = pInfo->height - dstHeight;
477 if (!pInfo->tempImage)
478 pPriv->srcBufferHeight = pInfo->height;
479 else pPriv->srcBufferHeight = 0;
481 /* Init the filter table in private based on scale factors and # gray levels.
483 ilInit9BitFilter (pPriv->srcWidth, pPriv->srcHeight, pPriv->dstWidth,
484 pPriv->dstHeight, nGrayLevels, blackIsZero, pPriv->filterValues);
486 pipe->context->error = IL_OK;
490 /* ------------------------- ilAreaScaleBitonal ---------------------------- */
491 /* Called by ilScale().
492 Adds an element to "pipe" to scale the pipe image to "dstWidth" by "dstHeight"
493 which both must be > 0. The input pipe image must be a bitonal,
494 bit-per-pixel image, with _any_ "blackIsZero". The resulting image is of the
495 same type. "pInfo" points to the pipe info, "dstWidth/Height" is the (> 0) size
497 Only a scale down in both directions is allowed; the following must be true:
498 srcWidth must be >= dstWidth and srcHeight must be >= dstHeight!
499 Logically the same as ilScaleBitonalToGray(): a gray byte is produced for
500 each destination pixel, using 256 levels of gray. If that byte is
501 >= "*pGrayThreshold"; a white pixel is written; else a black pixel is written.
502 NOTE: the value at "*pGrayThreshold" is read each time the pipe is executed
503 (during Init()); the caller change its value and get different results without
504 recreating the pipe. If "pGrayThreshold" is NULL, a default value is used.
506 IL_PRIVATE void _ilAreaScaleBitonal (
508 unsigned long dstWidth,
509 unsigned long dstHeight,
514 register ilBiGrayPrivPtr pPriv;
515 ilDstElementData dstData;
516 #define DEFAULT_GRAY_THRESHOLD 128 /* assumes 256 levels */
518 /* Add a filter to do the scale, then init *pPriv.
520 dstData.producerObject = (ilObject)NULL;
521 dstData.pDes = (ilImageDes *)NULL;
522 dstData.pFormat = IL_FORMAT_BIT;
523 dstData.width = dstWidth;
524 dstData.height = dstHeight;
525 dstData.stripHeight = ((dstHeight * pInfo->recommendedStripHeight) / pInfo->height) + 1;
526 dstData.constantStrip = FALSE;
527 dstData.pPalette = (unsigned short *)NULL;
528 pPriv = (ilBiGrayPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof (ilBiGrayPrivRec),
529 IL_ADD_PIPE_HOLD_SRC, (ilSrcElementData *)NULL, &dstData,
530 ilBiGrayInit, IL_NPF, IL_NPF, ilBiGrayExecute, NULL, 0);
534 /* Pipe element added, init pPriv. If not a tempImage, reading directly from
535 a permanent image: set srcHeight to image height; else set to 0.
537 pPriv->bitonalOutput = TRUE;
539 pPriv->pGrayThreshold = pGrayThreshold;
541 pPriv->defaultGrayThreshold = DEFAULT_GRAY_THRESHOLD;
542 pPriv->pGrayThreshold = &pPriv->defaultGrayThreshold;
544 pPriv->srcWidth = pInfo->width;
545 pPriv->srcHeight = pInfo->height;
546 pPriv->dstWidth = dstWidth;
547 pPriv->dstHeight = dstHeight;
548 pPriv->widthDiff = pInfo->width - dstWidth;
549 pPriv->heightDiff = pInfo->height - dstHeight;
550 if (!pInfo->tempImage)
551 pPriv->srcBufferHeight = pInfo->height;
552 else pPriv->srcBufferHeight = 0;
554 /* Init the filter table in private based on scale factors and 256 gray levels.
555 Note that "blackIsZero" is passed as FALSE below, because we want to output
556 the same blackIsZero as input. We output a zero when the gray is
557 >= threshold; this works for either sense of blackIsZero.
559 ilInit9BitFilter (pPriv->srcWidth, pPriv->srcHeight, pPriv->dstWidth,
560 pPriv->dstHeight, 256, FALSE, pPriv->filterValues);
562 pipe->context->error = IL_OK;