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: ildecompg4.c /main/6 1996/06/19 12:23:48 ageorge $ */
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 ***-------------------------------------------------------------------*/
45 #include "ilpipelem.h"
48 #include "ildecompg4.h"
49 #include "ildecompg4table.h"
51 /* Table containing (array) the number of consecutive zeros
52 from the start (msb first), in chars for 0x00 to 0xff
53 for e.g number of consecutive zeros in 0x00 = 8
56 static unsigned char zeroruns[256] = {
57 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
58 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
59 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
60 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
61 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
62 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
64 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
65 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
76 /* Table containing (array) the number of consecutive ones
77 from the start (msb first), in chars for 0x00 to 0xff
78 for e.g number of consecutive ones in 0x00 = 0
82 static unsigned char oneruns[256] = {
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
90 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
91 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
92 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
93 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
94 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
95 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
96 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
97 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
98 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
102 /* This module G4 Decompression has been totally rewritten ...
103 Earlier module handled images with LSB first only,
104 and failing while handling images Compressed in Strips.
106 The present implementation uses the same tables, and takes care of the
107 above issues. Additionally, it has been designed in such a way as that
108 these decompression can be used for G3 - 2D decompression also.
111 /* ========================================================================
113 -------------------- _ilPutOnes(). --------------------
114 Input : pointer to the current Image Destination line (*sByte)
115 startPixel - from which position 1's are to be put
116 no_of_ones - how many pixels are to be put with ones
119 Utility function to put 1's (no_of_ones) in the string, pointed by
120 *sByte, from the position startPixel; Used to fill the Destination
121 image while De-Compressing. Initially the Destination image is filled
122 with Zeros 0's ; While De-Compressing, 1's are filled appropriately
123 to construct the Image..
125 ** used in G3 & G4 Decompression
127 ======================================================================== */
131 register char *sByte,
132 register int startPixel,
133 register int no_of_ones )
136 static const unsigned char masks[] =
138 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
140 /* fill 1's in the current Byte */
142 sByte += startPixel>>3;
143 if (startPixel &= 7) { /* align to byte boundary */
144 if (no_of_ones < 8 - startPixel) {
145 *sByte++ |= masks[no_of_ones] >> startPixel;
148 *sByte++ |= 0xff >> startPixel;
149 no_of_ones -= 8 - startPixel;
152 /* fill 1's in the consecutive Full Bytes */
153 memset(sByte,0xff,(no_of_ones >> 3));
154 sByte += (no_of_ones >> 3 );
155 no_of_ones = no_of_ones & 7 ;
157 /* fill 1's in the last partial Byte */
158 *sByte |= masks[no_of_ones];
161 /* ========================================================================
163 -------------------- _ilGetAbsDiff(). --------------------
164 Input : the pointer to the pointer to the strings (image Line)
165 startPixel from which the diff. is to be found
166 endPixel i.e upto which the diff can be checked.
167 color of the current pixel (startPixel)
168 nTimes - no. of times the counting is to be repeated i.e for
169 how many changing elements, the operation is to be
173 Calculates the count of pixels of the same color and returns the absolute
174 position of the next changing element and Returns the Absolute Position
177 ** used for G4,G3-2d compression and de-comression
178 ======================================================================== */
181 _ilGetAbsDiff( unsigned char *sByte,
188 register unsigned char *bp;
189 register int ini_diff;
190 register int n, fin_diff;
191 register unsigned char *table ;
195 bp += startPixel>> 3; /* adjust byte offset */
199 if ((startPixel == -1) ) {
206 table = (color ? oneruns : zeroruns );
207 ini_diff = endPixel- startPixel;
209 /* Find difference in the partial byte on the current Byte */
211 if (ini_diff > 0 && (n = (startPixel & 7))) {
212 fin_diff = table[(*bp << n) & 0xff];
214 if (fin_diff > 8-n) /* Consecutive bits extend beyond the current byte */
218 /* return the initial differece, if the current byte happens
219 to be the last byte of the Imageline and cosecutive bits
220 extend beyound that. */
222 if (fin_diff > ini_diff)
225 if (n + fin_diff < 8 ) /* Consecutive bits does not go upto the edge, so return the diff */
227 ini_diff -= fin_diff;
232 /* Count in the bytes, till opp. color is found
233 i.e while the diff >= 8 */
235 while (ini_diff >= 8) {
239 if (n < 8) /* end of run */
245 /* Find difference in the partial byte on RHS */
249 fin_diff += (n > ini_diff ? ini_diff : n);
253 startPixel += fin_diff;
256 } while (--nTimes > 0 );
261 /* --------------- End of _ilGetAbsDiff() ---------------- */
263 /* ========================================================================
264 -------------------- _ilDeCompressG4Init -------------------
265 Routine defined in ilDeCompG4 for initializing CCITT Group3
266 compression when the pipe gets executed.
268 ======================================================================== */
270 static ilError _ilDecompG4Init(
271 ilDecompG3G4PrivPtr pPriv,
272 ilImageInfo *pSrcImage,
273 ilImageInfo *pDstImage
276 /* Allocate space for Reference line, needed for 2 dimensional coding */
278 pPriv->gpRefLine = (ilPtr)IL_MALLOC(pPriv->nDstLineBytes );
279 if (!pPriv->gpRefLine)
280 return IL_ERROR_MALLOC;
284 /* ========================================================================
285 -------------------- _ilDeCompressG4Cleanup -------------------
286 ======================================================================== */
288 static ilError _ilDecompG4Cleanup(
289 ilDecompG3G4PrivPtr pPriv,
290 ilImageInfo *pSrcImage,
291 ilImageInfo *pDstImage
294 /* De-Allocate the space for Reference line */
295 if (pPriv->gpRefLine)
296 IL_FREE( (ilPtr)pPriv->gpRefLine);
302 /* Macros used in _ilDecompG4Line() */
303 /* Macros for Getting the Number of White Runs */
305 #define G4_GET_WHITE_RUN(whiteRun) { \
308 if ( Is_Lsb_First ) \
309 GET_VALUE_LSB(bits,ImageP, srcpos, G4M_WhiteRun) \
311 GET_VALUE_MSB(bits,ImageP, srcpos, G4M_WhiteRun) \
312 pDecodeTemp = pDecodeWhite+bits; \
313 srcpos += pDecodeTemp->length; \
314 whiteRun += pDecodeTemp->value; \
315 } while (pDecodeTemp->type != G4K_CodetypeTerminator) ; \
318 /* Macros for Getting the Number of Black Runs */
320 #define G4_GET_BLACK_RUN(blackRun) { \
323 if ( Is_Lsb_First ) \
324 GET_VALUE_LSB(bits,ImageP, srcpos, G4M_BlackRun) \
326 GET_VALUE_MSB(bits,ImageP, srcpos, G4M_BlackRun) \
327 pDecodeTemp = pDecodeBlack+bits; \
328 srcpos += pDecodeTemp->length; \
329 blackRun += pDecodeTemp->value; \
330 } while (pDecodeTemp->type != G4K_CodetypeTerminator) ; \
333 /* ========================================================================
334 -------------------- _ilDecompG4Line -------------------
335 Input : pointer to the Private data record or decompG3G4
336 pointer to the Reference line
337 pointer to the Destination image
338 Does : Reading the Source Image, De-Compresses One line for the destn.
339 image by Two dimensional coding.
340 ======================================================================== */
341 ilError _ilDecompG4Line(
342 register ilDecompG3G4PrivPtr pPriv,
348 int a0,b1,b2; /* changing elements used while decomressing */
349 short color; /* color of the pixel */
350 int firstRun; /* no. of consecutive pixels for M(a0a1) in Horiz mode */
351 int secondRun; /* no. of consecutive pixels for M(a1a2) in Horiz mode */
355 ilBool Is_Lsb_First ;
359 register ilDecompG4HuffTablePtrConst pDecodeWhite = ilArFax1DDecodeWhite;
360 register ilDecompG4HuffTablePtrConst pDecodeTemp;
361 register ilDecompG4HuffTablePtrConst pDecodeBlack = ilArFax1DDecodeBlack;
364 /* Deccompression Procedure ....
366 From the compressed data from Source Image .. retrieve a long bit; use this as
367 index to determine the 2d coded mode (Pass or Horiz or Vert(-3 to 3) );
368 Depending upon the mode, calculate the changing elements b1,b2 and adjust a0;
369 If 1's have to filled to the destination image, call _ilPutOnes(..);
370 If Horiz. mode is identified, call macros G4_GET_WHITERUN(..) & G4_GETBLACKRUN(..)
371 to estimate the first and second runs and fill 1's;
372 This loop will have to repeated until the value of a0 reaches the ImageWidth.
373 See ilcompressg4.c for more infn. on G4 compression .
377 width = pPriv->width;
380 color = pPriv->white;
381 Is_Lsb_First = pPriv->Is_Lsb_First;
382 srcpos = pPriv->srcpos;
383 ImageP = pPriv->ImageP;
385 do { /* till a complete Image line is DeCompressed */
388 GET_VALUE_LSB(bits,ImageP, srcpos, G4M_Codeword)
390 GET_VALUE_MSB(bits,ImageP, srcpos, G4M_Codeword)
392 if (ilArFax2DDecodeTable[bits].type != G4K_CodetypeTerminator)
393 return IL_ERROR_COMPRESSED_DATA ;
395 srcpos += ilArFax2DDecodeTable[bits].length;
397 switch (ilArFax2DDecodeTable[bits].value) {
399 /* State mode is codeword, codeword type is TERMINATOR,
400 codeword value is PASS */
402 case G4K_CodevaluePass:
404 b2 = _ilGetAbsDiff(pRefLine, a0, width, !color,3);
408 _ilPutOnes((char *)dstImageP, a0, b2 - a0);
413 /* State mode is Codeword, codeword type is TERMINATOR,
414 codeword value is HORIZONTAL */
416 case G4K_CodevalueHoriz:
418 if (color == pPriv->white) {
419 G4_GET_WHITE_RUN(firstRun) ;
420 G4_GET_BLACK_RUN(secondRun);
423 G4_GET_BLACK_RUN(firstRun);
424 G4_GET_WHITE_RUN(secondRun) ;
428 if (a0 + firstRun > width)
429 firstRun = width - a0;
430 if ( (color) && ( firstRun > 0 ) )
431 _ilPutOnes((char *)dstImageP, a0, firstRun);
435 if (a0 + secondRun > width)
436 secondRun = width - a0;
437 if ( (!color) && ( secondRun > 0 ) )
438 _ilPutOnes((char *)dstImageP, a0, secondRun);
443 /* State mode is codeword, codeword type is TERMINATOR,
444 codeword value is VERTICAL */
446 case G4K_CodevalueV0:
447 case G4K_CodevalueVR1:
448 case G4K_CodevalueVL1:
449 case G4K_CodevalueVR2:
450 case G4K_CodevalueVL2:
451 case G4K_CodevalueVR3:
452 case G4K_CodevalueVL3:
454 b1 = _ilGetAbsDiff(pRefLine, a0, width, !color,2);
455 b1 += ilArFax2DDecodeTable[bits].value;
461 _ilPutOnes((char *)dstImageP, a0, b1 - a0);
468 /* found invalid codeword values, return error */
469 return IL_ERROR_COMPRESSED_DATA ;
472 } while (a0 < width); /* End of Image line is reached */
474 pPriv->srcpos = srcpos;
479 /* ========================================================================
481 -------------------- ilDecompG4Execute -------------------
482 Routine defined in ilDecompG4 for executing CCITT Group4
483 decompression when the pipe gets executed.
485 ======================================================================== */
487 static ilError _ilDecompG4Execute(
488 ilExecuteData *pData,
489 unsigned long dstLine,
490 unsigned long *pNLines
493 /* ========================================================================
494 ilDecompG4Execute() definitions
495 ======================================================================== */
497 ilImagePlaneInfo *pSrcPlane; /* Pointer to the Source Image Plane */
498 ilImagePlaneInfo *pDstPlane; /* Pointer to the Source Image Plane */
499 ilPtr pSrcLine; /* Pointer to the Source Image FirstLine */
500 ilDecompG3G4PrivPtr pPriv; /* Pointer to private image data */
502 ilPtr dstImageP; /* Pointer to the Destn. Image */
503 ilPtr pRefLine; /* Pointer to the Reference line */
504 ilError error; /* Returned error */
505 int dstBytesPerRow; /* no.of byte per Row in the dest image */
506 long nLines; /* no. of lines in the current strip */
508 /* ========================================================================
509 ilDecompG4Execute() set up for decompression algorithm code
510 ======================================================================== */
512 pPriv = (ilDecompG3G4PrivPtr) pData->pPrivate;
514 if ( *pNLines <= 0 ) return IL_OK ;
515 if ( pData->compressed.nBytesToRead <= 0 ) return IL_OK ;
518 /* Exit if pointer to pPixels is NULL */
519 pSrcPlane = &pData->pSrcImage->plane[0];
520 if (!pSrcPlane->pPixels) return IL_ERROR_NULL_COMPRESSED_IMAGE;
521 pSrcLine = pSrcPlane->pPixels + pData->compressed.srcOffset; /* image location pointer */
523 pDstPlane = &pData->pDstImage->plane[0];
525 /* The destination image line pointer gets updated at the beginning of each strip */
526 dstImageP = (pDstPlane->pPixels + (dstLine * pDstPlane->nBytesPerRow));
527 dstBytesPerRow = pDstPlane->nBytesPerRow ;
529 /* ========================================================================
530 Zero the output (dst) buffer. _ilPutOnes() writes only ones, and expects
531 that the dst lines have already been zeroed.
532 ======================================================================== */
533 bzero ((char *)dstImageP, (pDstPlane->nBytesPerRow * *pNLines) );
535 /* Allocate space for the Reference line and set to zero Or 1's */
538 memset(pPriv->gpRefLine,0xff,(pDstPlane->nBytesPerRow ));
540 memset(pPriv->gpRefLine,0x00,(pDstPlane->nBytesPerRow ));
542 pRefLine = pPriv->gpRefLine;
545 pPriv->ImageP = pSrcLine;
546 pPriv->Is_Lsb_First = ( ( pPriv->compFlags & IL_G4M_LSB_FIRST) ? 1 : 0 );
548 /* this pPriv->maxSrcPos is set to the bits that could be read, to prevent the
549 program from reading beyond the compressed bytes; this check is done by
550 the macro Get_value_msb & lsb */
552 pPriv->maxSrcPos = pData->compressed.nBytesToRead * 8 ;
554 /* till the Destination Image is filled up , call the decompress from the
555 source line by line.. If any error in reading the compressed data, i.e
556 invalid Code words or invalid Modes are found will retrun the error
557 IL_ERROR_COMPRESSED_DATA .
558 After decompressing each line, the decompressed line is set as reference
559 line for the next line to be decompressed.
560 Destination image size and Pointer are suitably decremented & incremented.
563 while ( nLines-- > 0 )
566 if (error = _ilDecompG4Line(pPriv,pRefLine,dstImageP) )
569 pRefLine = dstImageP;
570 dstImageP += dstBytesPerRow;
576 /* End ilDecompG4Execute() */
578 /* ========================================================================
580 -------------------- ilDecompG4() -------------------
581 Entry point of code for CCITT Group4 decompression. This
582 includes image descriptor parameter error checking and function calls
583 for: strip handler initialization, adding the filter element to the
584 pipe, pipe initialization and execution, decompression algorithm,
585 along with cleanup and destruction of allocated memory.....
587 ======================================================================== */
597 ilDstElementData dstdata;
598 ilDecompG3G4PrivPtr pPriv;
601 /* Validate that image is bitonal */
602 if (pimdes->type != IL_BITONAL)
603 return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
606 Check for Group4, uncompressed, or any undefined bits on. These
609 if (pimdes->compInfo.g4.flags & IL_G4M_UNCOMPRESSED )
610 return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
613 /* dstdata describes strips being output to next pipe element */
614 dstdata.producerObject = (ilObject) NULL;
616 des.compression = IL_UNCOMPRESSED;
617 des.compInfo.g4.flags = NULL;
619 dstdata.pFormat = IL_FORMAT_BIT;
620 dstdata.width = pinfo->width;
621 dstdata.height = pinfo->height;
622 dstdata.pPalette = (unsigned short *)NULL;
624 /* set output strip height */
625 dstdata.stripHeight = pinfo->stripHeight;
626 dstdata.constantStrip = pinfo->constantStrip;
628 dstdata.pCompData = (ilPtr)NULL;
630 pPriv = (ilDecompG3G4PrivPtr) ilAddPipeElement(pipe, IL_FILTER,
631 sizeof(ilDecompG3G4PrivRec), 0,
632 (ilSrcElementData *)NULL,
633 &dstdata, _ilDecompG4Init,_ilDecompG4Cleanup,
634 IL_NPF, _ilDecompG4Execute, NULL, 0);
636 if (!pPriv) return FALSE; /* EXIT */
638 /* save private data */
639 pPriv->width = pinfo->width;
640 pPriv->white = ( des.blackIsZero ? 1 : 0 );
641 pPriv->compFlags = pimdes->compInfo.g4.flags;
642 pPriv->nDstLineBytes = (pPriv->width + 7) / 8;