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: ildecompg3.c /main/6 1996/06/19 12:23:58 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"
51 /* ========================================================================
53 -------------------- _ilDeCompressG3Init -------------------
54 Routine defined in ilDecompG3 for initializing CCITT Group3
55 compression when the pipe gets executed.
57 ======================================================================== */
59 static ilError _ilDecompG3Init(
60 ilDecompG3G4PrivPtr pPriv,
61 ilImageInfo *pSrcImage,
62 ilImageInfo *pDstImage
65 /* Allocate space for Reference line, needed for 2 dimensional coding */
67 pPriv->gpRefLine = (ilPtr)IL_MALLOC(pPriv->nDstLineBytes );
68 if (!pPriv->gpRefLine)
69 return IL_ERROR_MALLOC;
73 /* ========================================================================
74 -------------------- _ilDeCompressG3Cleanup -------------------
75 Routine defined in ilDecompG3 for Cleaning up CCITT Group3
76 compression when the pipe gets executed.
77 ======================================================================== */
79 static ilError _ilDecompG3Cleanup(
80 ilDecompG3G4PrivPtr pPriv,
81 ilImageInfo *pSrcImage,
82 ilImageInfo *pDstImage
87 IL_FREE( (ilPtr)pPriv->gpRefLine);
92 /* ======================================================================== */
93 /* ========================================================================
94 -------------------- _ilDecompG3Line -------------------
95 Input : pointer to the Private data record or decompG3G4
96 pointer to the Destination image
97 Does : Reading the Source Image, De-Compresses One line for the destn.
98 image by One dimensional coding.
100 ======================================================================== */
102 static ilError _ilDecompG3Line(
103 register ilDecompG3G4PrivPtr pPriv,
108 int a0; /* changing elements used while decomressing */
109 short color; /* color of the pixel */
110 int firstRun; /* no. of consecutive pixels for M(a0a1) in Horiz mode */
111 /* int secondRun; no. of consecutive pixels for M(a1a2) in Horiz mode */
115 ilBool Is_Lsb_First ;
119 register ilDecompG4HuffTablePtrConst pDecodeWhite = ilArFax1DDecodeWhite;
120 register ilDecompG4HuffTablePtrConst pDecodeTemp;
121 register ilDecompG4HuffTablePtrConst pDecodeBlack = ilArFax1DDecodeBlack;
122 register ilPtr sByte;
123 register int no_of_ones;
124 register int startPixel;
126 static const unsigned char fillmasks[] =
128 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
130 /* Deccompression Procedure ....
132 From the compressed data from Source Image .. retrieve a long bit; use this as
133 index to determine the number of White Pixels and then the number of
134 Black Pixels... Keep retrieving, till the end of line is reached..
135 ( Until the value of a0 reaches the ImageWidth. )
136 The new line would have always started with a White Pixel code.
137 Until the value of a0 reaches the ImageWidth.
138 See ilcompressg3.c for more infn. on G3 compression .
142 width = pPriv->width;
146 color = pPriv->white;
147 Is_Lsb_First = pPriv->Is_Lsb_First;
148 srcpos = pPriv->srcpos;
149 ImageP = pPriv->ImageP;
151 do { /* till a complete Image line is DeCompressed */
153 if (color == pPriv->white) { /* white is run is expected first always... */
157 GET_VALUE_LSB(bits,ImageP, srcpos, G4M_WhiteRun)
159 GET_VALUE_MSB(bits,ImageP, srcpos, G4M_WhiteRun)
160 pDecodeTemp = pDecodeWhite+bits;
163 /* if invalid data is found .... */
164 if ( ( pDecodeTemp->length == 0 ) && ( pDecodeTemp->value == 0 )
165 && ( pDecodeTemp->type == 0 ) )
166 return IL_ERROR_COMPRESSED_DATA ;
168 srcpos += pDecodeTemp->length;
169 firstRun += pDecodeTemp->value;
171 } while (pDecodeTemp->type != G4K_CodetypeTerminator) ;
174 else { /* look for black Run */
178 GET_VALUE_LSB(bits,ImageP, srcpos, G4M_BlackRun)
180 GET_VALUE_MSB(bits,ImageP, srcpos, G4M_BlackRun)
181 pDecodeTemp = pDecodeBlack+bits;
183 /* if invalid data is found .... */
184 if ( ( pDecodeTemp->length == 0 ) && ( pDecodeTemp->value == 0 )
185 && ( pDecodeTemp->type == 0 ) )
186 return IL_ERROR_COMPRESSED_DATA ;
188 srcpos += pDecodeTemp->length;
189 firstRun += pDecodeTemp->value;
190 } while (pDecodeTemp->type != G4K_CodetypeTerminator) ;
194 if (a0 + firstRun > width)
195 firstRun = width - a0;
197 if ( (color) && (firstRun > 0) ) /* fill the dst image with 1's */
200 /* the whole block was written as a function, In-lined later
201 to speedup performance in Hpux .. */
203 /* fill 1's in the current Byte */
205 no_of_ones = firstRun;
208 sByte += startPixel>>3;
209 if (startPixel &= 7) { /* align to byte boundary */
210 if (no_of_ones < 8 - startPixel) {
211 *sByte++ |= fillmasks[no_of_ones] >> startPixel;
214 *sByte++ |= 0xff >> startPixel;
215 no_of_ones -= 8 - startPixel;
220 /* fill 1's in the consecutive Full Bytes */
221 memset(sByte,0xff,(no_of_ones >> 3));
222 sByte += (no_of_ones >> 3 );
223 no_of_ones = no_of_ones & 7 ;
225 /* fill 1's in the last partial Byte */
226 *sByte |= fillmasks[no_of_ones];
234 } while (a0 < width); /* End of Image line is reached */
236 pPriv->srcpos = srcpos;
240 /* ========================================================================
241 -------------------- ilDecompG3Execute -------------------
242 Routine defined in ilDecompG3 for executing CCITT Group4
243 decompression when the pipe gets executed.
244 ======================================================================== */
246 static ilError _ilDecompG3Execute(
247 ilExecuteData *pData,
248 unsigned long dstLine,
249 unsigned long *pNLines
252 /* ========================================================================
253 ilDecompG3Execute() definitions
254 ======================================================================== */
256 ilImagePlaneInfo *pSrcPlane; /* Pointer to the Source Image Plane */
257 ilImagePlaneInfo *pDstPlane; /* Pointer to the Source Image Plane */
258 ilPtr pSrcLine; /* Pointer to the Source Image FirstLine */
259 ilDecompG3G4PrivPtr pPriv; /* Pointer to private image data */
261 ilPtr dstImageP; /* Pointer to the Destn. Image */
262 ilPtr pRefLine; /* Pointer to the Reference line */
263 ilError error; /* Returned error */
264 int dstBytesPerRow; /* no.of byte per Row in the dest image */
265 ilBool Is_2DCoding; /* G3 2 D coding is present, if True */
266 ilBool Is_EOLs; /* EOL markers are set, and will have to be decoded */
267 int bits; /* to store the current bit from the source image */
268 int temp; /* some temp var.. */
269 ilBool tag_bit; /* True or 1 for G3 1D coded line ,else G3 2d */
270 long nLines; /* no. of lines in the current strip */
271 register ilDecompG4HuffTablePtrConst pDecodeWhite = ilArFax1DDecodeWhite;
272 register ilDecompG4HuffTablePtrConst pDecodeTemp;
275 /* ========================================================================
276 ilDecompG3Execute() set up for decompression algorithm code
277 ======================================================================== */
279 pPriv = (ilDecompG3G4PrivPtr) pData->pPrivate;
281 if ( *pNLines <= 0 ) return IL_OK ;
282 if ( pData->compressed.nBytesToRead <= 0 ) return IL_OK ;
285 /* Exit if pointer to pPixels is NULL */
286 pSrcPlane = &pData->pSrcImage->plane[0];
287 if (!pSrcPlane->pPixels) return IL_ERROR_NULL_COMPRESSED_IMAGE;
288 pSrcLine = pSrcPlane->pPixels + pData->compressed.srcOffset; /* image location pointer */
290 pDstPlane = &pData->pDstImage->plane[0];
292 /* The destination image line pointer gets updated at the beginning of each strip */
293 dstImageP = (pDstPlane->pPixels + (dstLine * pDstPlane->nBytesPerRow));
294 dstBytesPerRow = pDstPlane->nBytesPerRow ;
296 /* ========================================================================
297 Zero the output (dst) buffer. _ilPutOnes() writes only ones, and expects
298 that the dst lines have already been zeroed.
299 ======================================================================== */
300 bzero ((char *)dstImageP, (pDstPlane->nBytesPerRow * *pNLines) );
302 /* this pPriv->maxSrcPos is set to the bits that could be read, to prevent the
303 program from reading beyond the compressed bytes; this check is done by
304 the macro Get_value_msb & lsb */
306 pPriv->maxSrcPos = pData->compressed.nBytesToRead * 8 ;
309 pPriv->ImageP = pSrcLine;
310 pPriv->Is_Lsb_First = ( pPriv->compFlags & IL_G3M_LSB_FIRST);
311 Is_2DCoding = ( pPriv->compFlags & IL_G3M_2D);
312 Is_EOLs = ( pPriv->compFlags & IL_G3M_EOL_MARKERS);
315 /* For G3 - 2D files, EOLs must be present, if not Error in the Compressed
316 file... so check for that */
317 if ( (Is_2DCoding) && (!(Is_EOLs)) )
318 return IL_ERROR_COMPRESSED_DATA ;
320 /* Allocate space for the Reference line and set to zero Or 1's */
321 /* if G3 - 2 dimensional Coding is present */
324 memset(pPriv->gpRefLine,0xff,(pDstPlane->nBytesPerRow ));
326 memset(pPriv->gpRefLine,0x00,(pDstPlane->nBytesPerRow ));
328 pRefLine = pPriv->gpRefLine;
332 /* till the Destination Image is filled up , call the decompress from the
333 source line by line.. If any error in reading the compressed data, i.e
334 invalid Code words or invalid Modes are found will retrun the error
335 IL_ERROR_COMPRESSED_DATA .
336 After decompressing each line, the decompressed line is set as reference
337 line for the next line to be decompressed.
338 Destination image size and Pointer are suitably decremented & incremented.
341 while ( nLines-- > 0 )
344 /* If EOLs are present in the compressed Image, (they will be there at the begining
345 of Each line, not at the end contrary to the meaning of EOL !! ), they have to be
346 skipped... ; This loop takes care of this whether the EOL's are aligned or Not.. */
351 if ( pPriv->Is_Lsb_First )
352 GET_VALUE_LSB(bits, pPriv->ImageP, pPriv->srcpos, G4M_WhiteRun)
354 GET_VALUE_MSB(bits, pPriv->ImageP, pPriv->srcpos, G4M_WhiteRun)
355 pDecodeTemp = pDecodeWhite+bits;
357 if ( ( pDecodeTemp->length == 12 ) && ( pDecodeTemp->value == 1 )
358 && ( pDecodeTemp->type == G4K_CodetypeEol ) )
363 } while ( ( pDecodeTemp->length == 12 ) && ( pDecodeTemp->value == 1 )
364 && ( pDecodeTemp->type == G4K_CodetypeEol ) ) ;
366 pPriv->srcpos += 12 ;
367 } /* Block Is_EOLs */
369 /* If 2D compressed Image, then, after EOL look for the tag bit, which indicates
370 the mode of compression for the next line;
371 PIXEL(...), retrieves the next bit i.e tag bit, and if it is equal to 1, then
372 next line sholud be decompressed 1 dimesionally...;
373 so, call _ilDecompG3Line(...);
374 else, next line sholud be decompressed 2 dimesionally...and call
375 _ilDecompG4Line(...);
377 If not 2D compressed Image, and if Not EOLs, then, the next row of image, will
378 be from the start of the next byte, so check for that and skip to the next
383 /* Retrieve the tag_bit, depending on the bit Order */
384 if ( pPriv->Is_Lsb_First )
385 tag_bit = PIXEL_LSB(pPriv->ImageP,pPriv->srcpos);
387 tag_bit = PIXEL(pPriv->ImageP,pPriv->srcpos);
391 if (error = _ilDecompG3Line(pPriv,dstImageP) )
396 if (error = _ilDecompG4Line(pPriv,pRefLine,dstImageP) )
402 if ( ( !Is_EOLs) && ( ( temp = pPriv->srcpos % 8) != 0 ) )
403 pPriv->srcpos += (8-temp) ;
404 if (error = _ilDecompG3Line(pPriv,dstImageP) )
408 pRefLine = dstImageP;
409 dstImageP += dstBytesPerRow;
415 /* End ilDecompG3Execute() */
417 /* ========================================================================
419 -------------------- ilDecompG3() -------------------
420 Entry point of code for CCITT Group3 decompression. This
421 includes image descriptor parameter error checking and function calls
422 for: strip handler initialization, adding the filter element to the
423 pipe, pipe initialization and execution, decompression algorithm,
424 along with cleanup and destruction of allocated memory.....
426 ======================================================================== */
436 ilDstElementData dstdata;
437 ilDecompG3G4PrivPtr pPriv;
440 /* Validate that image is bitonal */
441 if (pimdes->type != IL_BITONAL)
442 return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
445 Check for Group3, uncompressed, or any undefined bits on. These
448 if (pimdes->compInfo.g3.flags & IL_G4M_UNCOMPRESSED )
449 return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
452 /* dstdata describes strips being output to next pipe element */
453 dstdata.producerObject = (ilObject) NULL;
455 des.compression = IL_UNCOMPRESSED;
456 des.compInfo.g4.flags = NULL;
458 dstdata.pFormat = IL_FORMAT_BIT;
459 dstdata.width = pinfo->width;
460 dstdata.height = pinfo->height;
461 dstdata.pPalette = (unsigned short *)NULL;
463 /* set output strip height */
464 dstdata.stripHeight = pinfo->stripHeight;
465 dstdata.constantStrip = pinfo->constantStrip;
467 dstdata.pCompData = (ilPtr)NULL;
469 pPriv = (ilDecompG3G4PrivPtr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilDecompG3G4PrivRec), 0, (ilSrcElementData
471 &dstdata, _ilDecompG3Init,_ilDecompG3Cleanup ,IL_NPF, _ilDecompG3Execute, NULL, 0);
473 if (!pPriv) return FALSE; /* EXIT */
475 /* save private data */
476 pPriv->width = pinfo->width;
477 pPriv->white = ( des.blackIsZero ? 1 : 0 );
478 pPriv->compFlags = pimdes->compInfo.g4.flags;
479 pPriv->nDstLineBytes = (pPriv->width + 7) / 8;