Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtHelp / il / ildecompg3.c
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 librararies 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: ildecompg3.c /main/6 1996/06/19 12:23:58 ageorge $ */
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
40
41 #include <math.h>
42 #include <stdio.h>       
43
44 #include "ilint.h"
45 #include "ilpipelem.h"
46 #include "ilerrors.h"
47 #include "ildecomp.h"
48 #include "ildecompg4.h"
49
50
51 /* ========================================================================
52              
53        -------------------- _ilDeCompressG3Init -------------------
54    Routine defined in ilDecompG3 for initializing CCITT Group3  
55    compression when the pipe gets executed.
56
57    ======================================================================== */
58
59 static ilError _ilDecompG3Init(
60 ilDecompG3G4PrivPtr     pPriv,
61 ilImageInfo            *pSrcImage,
62 ilImageInfo            *pDstImage
63 )
64 {
65         /* Allocate space for Reference line, needed for 2 dimensional coding */
66
67         pPriv->gpRefLine = (ilPtr)IL_MALLOC(pPriv->nDstLineBytes );
68         if (!pPriv->gpRefLine)
69                 return IL_ERROR_MALLOC;
70         return IL_OK;
71
72 }
73 /* ========================================================================
74        -------------------- _ilDeCompressG3Cleanup -------------------
75    Routine defined in ilDecompG3 for Cleaning up CCITT Group3  
76    compression when the pipe gets executed.
77    ======================================================================== */
78
79 static ilError _ilDecompG3Cleanup(
80 ilDecompG3G4PrivPtr     pPriv,
81 ilImageInfo            *pSrcImage,
82 ilImageInfo            *pDstImage
83 )
84 {
85
86         if (pPriv->gpRefLine)
87                 IL_FREE( (ilPtr)pPriv->gpRefLine);
88
89         return IL_OK;
90
91 }
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.
99
100    ======================================================================== */
101
102 static ilError   _ilDecompG3Line(
103 register ilDecompG3G4PrivPtr  pPriv,
104 ilPtr                     dstImageP
105 )
106 {
107
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 */
112
113         long bits ;
114         long width;
115         ilBool Is_Lsb_First ;
116         ilPtr ImageP;
117         int srcpos;
118
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;
125
126         static const unsigned char fillmasks[] =
127         { 
128                 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff       };
129
130         /*  Deccompression Procedure  ....
131
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 .
139
140    */
141
142         width = pPriv->width;
143
144         a0    = 0;
145
146         color        = pPriv->white;
147         Is_Lsb_First =  pPriv->Is_Lsb_First;
148         srcpos       =  pPriv->srcpos;
149         ImageP       =  pPriv->ImageP;
150
151         do {                  /* till a complete Image line is DeCompressed */
152
153                 if (color == pPriv->white) {                 /* white is run is expected first always... */
154                         firstRun = 0;
155                         do {
156                                 if ( Is_Lsb_First )
157                                     GET_VALUE_LSB(bits,ImageP, srcpos,  G4M_WhiteRun)
158                                 else 
159                                     GET_VALUE_MSB(bits,ImageP, srcpos,  G4M_WhiteRun)
160                                 pDecodeTemp = pDecodeWhite+bits;
161
162
163                                 /* if invalid data is found .... */
164                                 if ( ( pDecodeTemp->length == 0 ) && ( pDecodeTemp->value == 0 )
165                                     && ( pDecodeTemp->type == 0  ) )
166                                         return  IL_ERROR_COMPRESSED_DATA ;
167
168                                 srcpos += pDecodeTemp->length;
169                                 firstRun += pDecodeTemp->value;
170
171                         } while (pDecodeTemp->type != G4K_CodetypeTerminator) ;
172
173                 }
174                 else {                                         /* look for black Run         */
175                         firstRun = 0;
176                         do {
177                                 if ( Is_Lsb_First )
178                                         GET_VALUE_LSB(bits,ImageP, srcpos,  G4M_BlackRun)
179                                 else 
180                                     GET_VALUE_MSB(bits,ImageP, srcpos,  G4M_BlackRun)
181                                 pDecodeTemp = pDecodeBlack+bits;
182
183                                 /* if invalid data is found .... */
184                                 if ( ( pDecodeTemp->length == 0 ) && ( pDecodeTemp->value == 0 )
185                                     && ( pDecodeTemp->type == 0  ) )
186                                         return  IL_ERROR_COMPRESSED_DATA ;
187
188                                 srcpos   += pDecodeTemp->length;
189                                 firstRun += pDecodeTemp->value;
190                         } while (pDecodeTemp->type != G4K_CodetypeTerminator) ;
191
192                 }
193
194                 if (a0 + firstRun > width)
195                         firstRun = width - a0;
196
197                 if ( (color)  && (firstRun > 0)  )                   /* fill the dst image with 1's */
198            {
199
200             /* the whole block was written as a function, In-lined later
201                to speedup performance in Hpux     ..                     */
202
203                 /* fill 1's in  the current  Byte */
204             sByte  = dstImageP ;
205             no_of_ones = firstRun; 
206             startPixel = a0 ;
207
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;
212                         goto putones_done;
213                 }
214                 *sByte++ |= 0xff >> startPixel;
215                 no_of_ones -= 8 - startPixel;
216             if (!no_of_ones) 
217                         goto putones_done;
218                 }
219
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 ;
224
225                 /* fill 1's in  the last partial  Byte */
226                 *sByte |= fillmasks[no_of_ones];
227
228            }
229          
230 putones_done:
231                 a0 += firstRun;
232                 color = !color ;
233
234         } while (a0 < width);       /* End of Image line is reached */
235
236         pPriv->srcpos =   srcpos;
237         return IL_OK ;
238 }
239
240 /* ========================================================================    
241     -------------------- ilDecompG3Execute -------------------
242     Routine defined in ilDecompG3 for executing CCITT Group4
243     decompression when the pipe gets executed.
244    ======================================================================== */
245
246 static ilError _ilDecompG3Execute(
247 ilExecuteData      *pData,
248 unsigned long       dstLine,
249 unsigned long      *pNLines
250 )
251 {
252         /* ========================================================================
253    ilDecompG3Execute() definitions
254    ======================================================================== */
255
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         */
260
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;
273
274
275         /* ========================================================================
276    ilDecompG3Execute() set up for decompression algorithm code
277    ======================================================================== */
278
279         pPriv   = (ilDecompG3G4PrivPtr) pData->pPrivate;
280
281         if ( *pNLines <= 0 ) return IL_OK ;
282         if ( pData->compressed.nBytesToRead <= 0 ) return IL_OK ;
283     nLines  = *pNLines;
284
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 */
289
290         pDstPlane           = &pData->pDstImage->plane[0];
291
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 ;
295
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) );
301
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                                              */
305
306     pPriv->maxSrcPos     =  pData->compressed.nBytesToRead * 8 ;
307
308         pPriv->srcpos        =  0;
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);
313
314
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 ;
319
320         /* Allocate space for the Reference line and set to zero Or 1's         */
321         /* if G3 - 2 dimensional Coding is present                              */
322         if ( Is_2DCoding  ) {
323                 if (pPriv->white)
324                         memset(pPriv->gpRefLine,0xff,(pDstPlane->nBytesPerRow ));
325                 else
326                         memset(pPriv->gpRefLine,0x00,(pDstPlane->nBytesPerRow ));
327
328                 pRefLine = pPriv->gpRefLine;
329         }
330
331
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.
339     */
340
341         while ( nLines-- > 0 )
342         {
343
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..  */
347
348                 if ( Is_EOLs ) {
349
350                         do {
351                                 if ( pPriv->Is_Lsb_First )
352                                         GET_VALUE_LSB(bits, pPriv->ImageP, pPriv->srcpos,  G4M_WhiteRun)
353                                 else 
354                                         GET_VALUE_MSB(bits, pPriv->ImageP, pPriv->srcpos,  G4M_WhiteRun)
355                                 pDecodeTemp = pDecodeWhite+bits;
356
357                                 if ( ( pDecodeTemp->length == 12 ) && ( pDecodeTemp->value == 1 )
358                                     && ( pDecodeTemp->type == G4K_CodetypeEol ) )
359                                 {
360                                         pPriv->srcpos += 1 ;
361                                         continue;
362                                 }
363                         } while ( ( pDecodeTemp->length == 12 ) && ( pDecodeTemp->value == 1 )
364                             && ( pDecodeTemp->type == G4K_CodetypeEol ) ) ;
365
366                         pPriv->srcpos += 12 ;
367                 }                                                 /* Block Is_EOLs    */
368
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(...);            
376
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 
379            byte...
380                                                                                              */
381                 if ( Is_2DCoding  )  {
382
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);
386                         else
387                                 tag_bit =  PIXEL(pPriv->ImageP,pPriv->srcpos);
388
389                         if ( tag_bit ) {
390                                 pPriv->srcpos++;
391                                 if (error = _ilDecompG3Line(pPriv,dstImageP) )
392                                         return error;
393                         }
394                         else {
395                                 pPriv->srcpos++;
396                                 if (error = _ilDecompG4Line(pPriv,pRefLine,dstImageP) )
397                                         return error;
398                         }
399
400                 } else {
401
402                         if ( ( !Is_EOLs) && ( ( temp = pPriv->srcpos % 8) != 0 )  )
403                                 pPriv->srcpos += (8-temp) ;
404                         if (error = _ilDecompG3Line(pPriv,dstImageP) )
405                                 return error;
406                 }                                        /* is 2d coding */
407
408                 pRefLine       =   dstImageP;
409                 dstImageP     +=   dstBytesPerRow;
410
411         }
412
413         return IL_OK;
414 }
415 /* End ilDecompG3Execute() */
416
417 /* ========================================================================
418
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.....
425
426    ======================================================================== */
427
428 IL_PRIVATE
429 ilBool _ilDecompG3 (
430 ilPipe              pipe,
431 ilPipeInfo         *pinfo,                              
432 ilImageDes         *pimdes
433 )
434 {
435
436         ilDstElementData    dstdata;
437         ilDecompG3G4PrivPtr pPriv;
438         ilImageDes          des;
439
440         /*  Validate that image is bitonal */
441         if (pimdes->type != IL_BITONAL)
442                 return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
443
444         /*
445         Check for Group3, uncompressed, or any undefined bits on.  These
446         are not supported!
447     */
448         if (pimdes->compInfo.g3.flags & IL_G4M_UNCOMPRESSED )
449                 return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
450
451
452         /* dstdata describes strips being output to next pipe element */
453         dstdata.producerObject  =  (ilObject) NULL;
454         des                     = *pimdes;
455         des.compression         =  IL_UNCOMPRESSED;
456         des.compInfo.g4.flags   =  NULL;
457         dstdata.pDes            =  &des;
458         dstdata.pFormat         =  IL_FORMAT_BIT;
459         dstdata.width           =  pinfo->width;
460         dstdata.height          =  pinfo->height;
461         dstdata.pPalette        =  (unsigned short *)NULL;
462
463         /* set output strip height */
464         dstdata.stripHeight     =  pinfo->stripHeight;
465         dstdata.constantStrip   =  pinfo->constantStrip;
466
467         dstdata.pCompData       =  (ilPtr)NULL;
468
469         pPriv = (ilDecompG3G4PrivPtr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilDecompG3G4PrivRec), 0, (ilSrcElementData
470             *)NULL,
471             &dstdata, _ilDecompG3Init,_ilDecompG3Cleanup ,IL_NPF, _ilDecompG3Execute, NULL, 0);
472
473         if (!pPriv) return FALSE; /* EXIT */
474
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;
480         return TRUE;
481 }