123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: ilgraybi.c /main/6 1996/10/30 11:09:02 drk $ */
- /**---------------------------------------------------------------------
- ***
- *** (c)Copyright 1991 Hewlett-Packard Co.
- ***
- *** RESTRICTED RIGHTS LEGEND
- *** Use, duplication, or disclosure by the U.S. Government is subject to
- *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
- *** Technical Data and Computer Software clause in DFARS 252.227-7013.
- *** Hewlett-Packard Company
- *** 3000 Hanover Street
- *** Palo Alto, CA 94304 U.S.A.
- *** Rights for non-DOD U.S. Government Departments and Agencies are as set
- *** forth in FAR 52.227-19(c)(1,2).
- ***
- ***-------------------------------------------------------------------*/
- #include <stdlib.h>
- #include "ilint.h"
- #include "ilpipelem.h"
- #include "ilconvert.h"
- #include "ilerrors.h"
- #ifndef LSB_BIT_ORDER
- # define flip_bits(start,n) /*EMPTY*/
- #else
- extern void flip_bits(ilPtr start, unsigned n);
- extern void
- flip_bits(ilPtr start,
- unsigned n )
- {
- int i;
- unsigned char c;
- for (i = 0; i < n; i++) {
- c = *start;
- *start++ = ilBitReverseTable[c];
- }
- }
- #endif
- /* =========================== BITONAL DITHER CODE =============================== */
- /* Private data for error diffusion to bitonal, inited by Init() function. */
- typedef struct {
- long width; /* width of src/dst images */
- long srcRowBytes; /* bytes/row of src image */
- ilPtr pSrcPixels; /* ptr to start of src pixels */
- long dstRowBytes; /* bytes/row of dst image */
- ilPtr pDstPixels; /* ptr to start of dst pixels */
- ilBool blackIsZero; /* src image: true if 0 is black, else white */
- short *pError1, *pError2; /* ptr to error accumulator buffers */
- } ilBiDiffusionPrivRec, *ilBiDiffusionPrivPtr;
- /* Init() function: malloc and zero error accumulator buffers. */
- static ilError ilInitBiDiffusion (
- ilBiDiffusionPrivPtr pPriv,
- ilImageInfo *pSrcImage,
- ilImageInfo *pDstImage
- )
- {
- pPriv->width = pSrcImage->width;
- pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
- pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
- pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
- pPriv->pDstPixels = pDstImage->plane[0].pPixels;
- pPriv->blackIsZero = pSrcImage->pDes->blackIsZero;
- /* Create error accumulator buffers, 2 larger than width because the pixels
- above to the left and right are examined.
- */
- pPriv->pError1 = (short *)IL_MALLOC_ZERO (sizeof (short) * (pPriv->width + 2));
- pPriv->pError2 = (short *)IL_MALLOC_ZERO (sizeof (short) * (pPriv->width + 2));
- if (!pPriv->pError1 || !pPriv->pError2)
- return IL_ERROR_MALLOC;
- return IL_OK;
- }
- /* Cleanup() function: dispose error accumulator buffers. */
- static ilError ilCleanupBiDiffusion (
- ilBiDiffusionPrivPtr pPriv
- )
- {
- if (pPriv->pError1)
- IL_FREE (pPriv->pError1);
- if (pPriv->pError2)
- IL_FREE (pPriv->pError2);
- return IL_OK;
- }
- /* ----------------------- ilDiffuseGrayToBitonal ------------------------- */
- /* Dithers using error diffusion to bitonal.
- Input image: IL_DES_GRAY, IL_FORMAT_BYTE.
- Output image: IL_DES_BITONAL, IL_FORMAT_BIT
- */
- /* Execute() function: dither and pack the given # of src lines. */
- static ilError ilExecuteBiDiffusion (
- ilExecuteData *pData,
- long dstLine,
- long *pNLines /* ignored on input */
- )
- {
- #ifdef LSB_BIT_ORDER
- # define SPECIAL_MASK_BIT 0x00000001 /* for LSB bit order */
- # define SHIFT_MASK(m) ((m) <<= 1)
- #else
- # define SPECIAL_MASK_BIT 0x80000000 /* for MSB bit order */
- # define SHIFT_MASK(m) ((m) >>= 1)
- #endif
- ilBiDiffusionPrivPtr pPriv;
- long nLinesM1, nPixelsM1Init, nPixelsM1;
- short *pPrevError, *pError;
- int errorAcc, invert;
- long srcRowBytes, dstRowBytes;
- ilPtr pSrcLine, pDstLine;
- ilPtr pSrc;
- CARD32 mask, *pDst;
- CARD32 outLong;
- pPriv = (ilBiDiffusionPrivPtr)pData->pPrivate;
- srcRowBytes = pPriv->srcRowBytes;
- pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
- dstRowBytes = pPriv->dstRowBytes;
- pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
- nLinesM1 = *pNLines;
- if (nLinesM1 <= 0)
- return IL_OK;
- nLinesM1--;
- nPixelsM1Init = pPriv->width;
- if (nPixelsM1Init <= 0)
- return IL_OK;
- nPixelsM1Init--;
- /* Set "invert" to 0 if blackIsZero, else to 0xff, and xor each src pixel
- with invert. Thus if 0 is white, the xor turns 0 into 255, 1 into 254, etc.
- */
- invert = (pPriv->blackIsZero) ? 0 : 0xff;
- /* Dither: do Floyd-Steinberg dither (error diffusion) requiring src to be
- 256 gray levels. True error diffusion would map:
- (srcLevels-1)/(dstLevels-1) = 255/1
- but we will use 256/1 to make muls/divs easy. Use the following:
- 1/16 5/16 3/16
- 7/16 x
- where the fractions indicate what portion of the error from the surrounding
- pixels should be added to this pixels value (x) to determine dst pixel to
- write at "x".
- */
- do {
- pSrc = pSrcLine;
- pSrcLine += srcRowBytes;
- pDst = (CARD32 *)pDstLine;
- pDstLine += dstRowBytes;
- /* Point to error accumulator buffers and switch, so *pError becomes
- *pPrevError for next line. Bump ptrs by 1: prev scan line error is
- examined above to left and right: need zero extra value there to handle
- beginning/end of line.
- */
- pError = pPriv->pError1;
- pPrevError = pPriv->pError2;
- pPriv->pError1 = pPrevError;
- pPriv->pError2 = pError;
- pError++;
- pPrevError++;
- errorAcc = 0; /* holds error from pixel to the left */
- mask = SPECIAL_MASK_BIT;
- outLong = 0;
- nPixelsM1 = nPixelsM1Init;
- do {
- errorAcc *= 7; /* 7 * error to left */
- errorAcc += *(pPrevError - 1); /* 1 * error above left */
- errorAcc += 5 * *pPrevError++; /* 5 * error above */
- errorAcc += 3 * *pPrevError; /* 3 * error above right */
- errorAcc >>= 4; /* /16 */
- errorAcc += *pSrc++ ^ invert; /* + "x"; w/ blackIsZero handled */
- if (errorAcc >= 128) /* output white: don't set out bit */
- errorAcc -= 255; /* sub value of white from errorAcc */
- else /* output black: errorAcc -= 0 */
- outLong |= mask;
- *pError++ = errorAcc; /* store error into buffer */
- if (!(SHIFT_MASK(mask))) {
- flip_bits((ilPtr)&outLong, sizeof(outLong));
- *pDst++ = outLong;
- mask = SPECIAL_MASK_BIT;
- outLong = 0;
- }
- } while (--nPixelsM1 >= 0);
- if (mask != SPECIAL_MASK_BIT) { /* bits left in outLong; write them */
- flip_bits((ilPtr)&outLong, sizeof(outLong));
- *pDst++ = outLong;
- }
- } while (--nLinesM1 >= 0);
- return IL_OK;
- }
- /* Table exported to ilConvert(), declared in /ilc/ilconvert.h . */
- IL_PRIVATE ilConvertRec _ilDiffuseGrayToBitonal = {
- IL_NPF, /* CheckFormat() */
- IL_STD_FORMAT_BYTE, /* srcFormatCode */
- IL_NPF, /* AddElement() */
- IL_DES_BITONAL, /* pDstDes */
- IL_FORMAT_BIT, /* pDstFormat */
- sizeof (ilBiDiffusionPrivRec), /* nBytesPrivate */
- ilInitBiDiffusion, /* Init() */
- ilCleanupBiDiffusion, /* Cleanup() */
- IL_NPF, /* Destroy() */
- ilExecuteBiDiffusion /* Execute() */
- };
- /* =========================== BITONAL THRESHOLD CODE =============================== */
- /* ----------------------- ilThresholdGrayToBitonal ------------------------- */
- /* Convert gray to bitonal using a user-defined threshold.
- Input image: IL_DES_GRAY, IL_FORMAT_BYTE.
- Output image: IL_DES_BITONAL, IL_FORMAT_BIT
- */
- /* Private data for threshold conversion, inited by Init() function. */
- typedef struct {
- CARD32 *pThreshold; /* ptr to threshold for such gray->bi cvts */
- long width; /* width of src/dst images */
- long srcRowBytes; /* bytes/row of src image */
- ilPtr pSrcPixels; /* ptr to start of src pixels */
- long dstRowBytes; /* bytes/row of dst image */
- ilPtr pDstPixels; /* ptr to start of dst pixels */
- ilBool blackIsZero; /* true if 0 is black, else is white */
- } ilThresholdPrivRec, *ilThresholdPrivPtr;
- /* AddElement function: save copy of pThreshold (pOptionData to ilConvert())
- into private. This ptr is dereferenced every time the pipe is run, allowing
- the caller to change the threshold without reforming the pipe.
- */
- static ilError ilAddElementThreshold (
- ilThresholdPrivPtr pPriv,
- unsigned short *pPalette, /* not used */
- CARD32 *pThreshold /* pOptionData to ilConvert() */
- )
- {
- pPriv->pThreshold = pThreshold;
- return IL_OK;
- }
- /* Init() function: init the counter of "y" within private; load image pixel
- address and rowBytes into private for faster reference in Execute().
- */
- static ilError ilInitThreshold (
- ilThresholdPrivPtr pPriv,
- ilImageInfo *pSrcImage,
- ilImageInfo *pDstImage
- )
- {
- pPriv->width = pSrcImage->width;
- pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
- pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
- pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
- pPriv->pDstPixels = pDstImage->plane[0].pPixels;
- pPriv->blackIsZero = pSrcImage->pDes->blackIsZero;
- return IL_OK;
- }
- /* Execute() function: dither and pack the given # of src lines.
- */
- static ilError ilExecuteThreshold (
- ilExecuteData *pData,
- long dstLine,
- long *pNLines /* ignored on input */
- )
- {
- #ifdef LSB_BIT_ORDER
- # define SPECIAL_MASK_BIT 0x00000001 /* for LSB bit order */
- # define SHIFT_MASK(m) ((m) <<= 1)
- #else
- # define SPECIAL_MASK_BIT 0x80000000 /* for MSB bit order */
- # define SHIFT_MASK(m) ((m) >>= 1)
- #endif
- ilThresholdPrivPtr pPriv;
- long nLinesM1, nPixelsM1Init;
- long srcRowBytes, dstRowBytes;
- ilPtr pSrcLine, pDstLine;
- long nPixelsM1;
- ilPtr pSrc;
- CARD32 mask, *pDst;
- CARD32 outLong;
- ilByte threshold;
- pPriv = (ilThresholdPrivPtr)pData->pPrivate;
- threshold = *pPriv->pThreshold;
- srcRowBytes = pPriv->srcRowBytes;
- pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
- dstRowBytes = pPriv->dstRowBytes;
- pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
- nLinesM1 = *pNLines;
- if (nLinesM1 <= 0)
- return IL_OK;;
- nLinesM1--;
- nPixelsM1Init = pPriv->width;
- if (nPixelsM1Init <= 0)
- return IL_OK;
- nPixelsM1Init--;
- /* For each pixel, compare to the threshold and output black if
- < threshold (0 = black) or >= threshold (0 = white).
- */
- do {
- pSrc = pSrcLine;
- pSrcLine += srcRowBytes;
- pDst = (CARD32 *)pDstLine;
- pDstLine += dstRowBytes;
- mask = SPECIAL_MASK_BIT;
- outLong = 0;
- nPixelsM1 = nPixelsM1Init;
- if (pPriv->blackIsZero) {
- do {
- if (*pSrc++ < threshold)
- outLong |= mask;
- if (! SHIFT_MASK(mask)) {
- flip_bits((ilPtr)&outLong, sizeof(outLong));
- *pDst++ = outLong;
- mask = SPECIAL_MASK_BIT;
- outLong = 0;
- }
- } while (--nPixelsM1 >= 0);
- }
- else {
- do {
- if (*pSrc++ >= threshold)
- outLong |= mask;
- if (! SHIFT_MASK(mask)) {
- flip_bits((ilPtr)&outLong, sizeof(outLong));
- *pDst++ = outLong;
- mask = SPECIAL_MASK_BIT;
- outLong = 0;
- }
- } while (--nPixelsM1 >= 0);
- }
- /* If mask != left bit on, some bits in outLong; output them. Next line.
- */
- if (mask != SPECIAL_MASK_BIT) {
- flip_bits((ilPtr)&outLong, sizeof(outLong));
- *pDst++ = outLong;
- }
- } while (--nLinesM1 >= 0);
- return IL_OK;
- }
- /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
- Convert using a user-supplied threshold.
- Input image: IL_DES_GRAY (either form of blackIsZero), IL_FORMAT_BYTE.
- Output image: IL_DES_BITONAL, IL_FORMAT_BIT
- */
- IL_PRIVATE ilConvertRec _ilThresholdGrayToBitonal = {
- IL_NPF, /* CheckFormat() */
- IL_STD_FORMAT_BYTE, /* srcFormatCode */
- ilAddElementThreshold, /* AddElement() */
- IL_DES_BITONAL, /* pDstDes */
- IL_FORMAT_BIT, /* pDstFormat */
- sizeof (ilThresholdPrivRec), /* nBytesPrivate */
- ilInitThreshold, /* Init() */
- IL_NPF, /* Cleanup() */
- IL_NPF, /* Destroy() */
- ilExecuteThreshold /* Execute() */
- };
|