0022627: Change OCCT memory management defaults
[occt.git] / src / Xw / Xw_load_gif_image.cxx
1 /*
2  * Created:  zov : 22-Apr-1998  : Loads GIF image from file
3  *
4
5    XW_EXT_IMAGEDATA* Xw_load_gif_image (awindow,aimageinfo,fimage,ppcolors,pncolors)
6    XW_EXT_WINDOW *awindow
7    XW_USERDATA   *aimageinfo
8    XColor **ppcolors - address of pointer to array of used colors to return
9    int *pncolors - address of a variable to return length of the array in
10
11    Gets an image from a file.
12    Note, that the file must be GIF formatted.
13
14    Returns the image descriptor address if successful; or NULL if failed.
15 */
16
17 #define PURIFY  /*GG+STT 11/01/99
18 //              Avoid Free memory leak.
19 */
20
21 #include <Xw_Extension.h>
22 #include <fcntl.h>
23
24
25 #define         _ADD_PIXEL(idx)                                      \
26 {                                                                    \
27   if (y < height)  *(pidata + y*width + x) = ((unsigned char)(idx)); \
28   if (++x == width) {                                                \
29     x = 0;                                                           \
30     if (!isInterlace)  ++y;                                          \
31     else  switch (pass) {                                            \
32     case 0:  y += 8; if (y >= height) ++pass, y = 4; break;          \
33     case 1:  y += 8; if (y >= height) ++pass, y = 2; break;          \
34     case 2:  y += 4; if (y >= height) ++pass, y = 1; break;          \
35     default: y += 2;                                                 \
36     }                                                                \
37   }                                                                  \
38 }
39
40 /* Note,
41 ** Portions Copyright (c) of CISIGRAPH SOFTWARE.
42 **
43 ** Permission to use, copy, modify, and distribute this software and its
44 ** documentation for any purpose and without fee is hereby granted, provided
45 ** that the above copyright notice appear in all copies and that both that
46 ** copyright notice and this permission notice appear in supporting
47 ** documentation.  This software is provided "as is" without express or
48 ** implied warranty.
49 */
50
51 XW_EXT_IMAGEDATA *Xw_load_gif_image (void *awindow,void *aimageinfo,char *filename,int fimage,
52                          XColor **ppcolors, int *pncolors)
53 {
54 //  XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW *)awindow;
55   XW_EXT_IMAGEDATA *pimage = NULL;
56 //  XW_STATUS status;
57   XImage *pximage = NULL;
58   XColor *pcolors = NULL;
59   char *wname = NULL, *pidata = NULL;
60   unsigned char byte, byte1;
61   unsigned *OutCode=NULL, *Prefix=NULL, *Suffix=NULL,
62     BitMask, CodeSize, ClearCode, EOFCode, FreeCode, x, y, pass, width, height,
63     InitCodeSize, MaxCode, ReadMask, FirstFree, OutCount, BitOffset,
64     ByteOffset, Code, CurCode, OldCode=0, FinChar=0, InCode;
65   long lFileSize;
66 //  int i, isize, dataSize, ncolors;
67   int i, ncolors;
68 static  unsigned char *pchFileStream_start = NULL,
69                 *pchFileStream, *ptr1, *rasterPtr = NULL;
70   int isInterlace, hasColormap;
71
72
73   if (-1 == (lFileSize = lseek (fimage, 0, SEEK_END))
74       || NULL == (pchFileStream_start = (unsigned char *) Xw_malloc (lFileSize))
75       || 0 != lseek (fimage, 0, SEEK_SET)
76       || lFileSize != read (fimage, (char *)pchFileStream_start, lFileSize)
77       ) 
78     goto _ExitReadError;
79
80   pchFileStream = pchFileStream_start + 10;
81
82
83   byte = *pchFileStream++; /* Color descriptor byte (M#CR0#BP) */
84   hasColormap = byte & 0x80;
85   ncolors = hasColormap ? 1<<((byte & 0x07) + 1): 1<<8;
86   BitMask = ncolors - 1;
87
88 #ifdef DEBUG
89   fprintf (stderr, "\r\nXw_load_gif_image: GIF contains %d colors.",
90            hasColormap? ncolors: 0);
91 #endif /*DEBUG*/
92
93   pchFileStream += 2; /* Skip background byte and following zero byte */
94
95   if (ncolors > 0) { /* Allocate Color Table entries */
96
97     if (! (pcolors = (XColor*) Xw_calloc(ncolors, sizeof(XColor))))
98       goto _ExitAllocError;
99
100     for (i=0; i<ncolors; i++) { /* Fill in array of XColor's used */
101
102       /* Note, that if there's no colormap specified then I use green scale */
103       pcolors[i].red = ((int)(hasColormap ? *pchFileStream++: i)) << 8; /*map to 0:ffff*/
104       pcolors[i].green = ((int)(hasColormap ? *pchFileStream++: i)) << 8;
105       pcolors[i].blue = ((int)(hasColormap ? *pchFileStream++: i)) << 8;
106
107       pcolors[i].flags = DoRed|DoGreen|DoBlue;
108
109       pcolors[i].pixel = i;
110       pcolors[i].pad = 0;
111     }
112   }
113
114
115 #ifdef DEBUG
116   if (*pchFileStream == '!')
117     fprintf (stderr, "\r\nXw_load_gif_image: GIF contains extension blocks"
118              " (code: %x).", (int)*(pchFileStream + 1));
119   else 
120     fprintf (stderr, "\r\nXw_load_gif_image: GIF has no extension blocks.");
121 #endif /*DEBUG*/
122
123
124   /* Skip extension blocks if any.
125    * Format:  <'!'><size><...><size><...><0>
126    */
127   while (*pchFileStream == '!') {
128
129     pchFileStream += 2;  /* skip code byte followed '!' sign */
130
131     while (*pchFileStream)
132       pchFileStream += (unsigned)(1 + *(unsigned char *)pchFileStream);
133
134     pchFileStream ++;
135   }
136  
137
138
139   if (*pchFileStream++ != ',') { /* must be an image descriptor */
140
141 #ifdef DEB
142     fprintf (stderr, "\r\nXw_load_gif_image: Error: There's no separator"
143              " following the colormap");
144 #endif /*DEB*/
145
146     goto _ExitReadError;
147   }
148
149
150   pchFileStream += 2*2; /* Skip image left & top offsets*/
151   width = (unsigned) *pchFileStream++;
152   width += ((unsigned)*pchFileStream++) << 8;
153   height = (unsigned) *pchFileStream++;
154   height += ((unsigned)*pchFileStream++) << 8;
155
156     
157   byte = *pchFileStream++;
158
159   isInterlace = byte & 0x40;
160
161   if (byte & 0x80) {
162
163     fprintf (stderr, "\r\nXw_load_gif_image:"
164              " Can't read GIF image with locally defined colormap!\r\n");
165     goto _ExitReadError;
166   }
167
168   
169 #ifdef DEBUG
170     fprintf (stderr, "\r\nXw_load_gif_image: Dimensions: %dx%d"
171              "  Interlace mode: %s",
172              width, height, isInterlace? "ON": "OFF");
173 #endif /*DEBUG*/
174
175
176
177   /* Allocate the pixel buffer */
178   if (! (rasterPtr = (unsigned char *) Xw_malloc(lFileSize)))
179     goto _ExitAllocError;
180
181
182   OutCode = (unsigned *)Xw_malloc(1025 * sizeof (unsigned));
183   Prefix  = (unsigned *)Xw_malloc(4096 * sizeof (unsigned));
184   Suffix  = (unsigned *)Xw_malloc(4096 * sizeof (unsigned));
185
186   if (!OutCode || !Prefix || !Suffix)
187     goto _ExitAllocError;
188
189
190
191   /* Decode compressed raster data. */
192   CodeSize  = *pchFileStream++;
193   ClearCode = 1 << CodeSize;
194   EOFCode   = ClearCode + 1;
195   FreeCode  = FirstFree = EOFCode + 1;
196
197   ++CodeSize;
198
199   InitCodeSize = CodeSize;
200   MaxCode      = 1 << CodeSize;
201   ReadMask     = MaxCode - 1;
202
203   ptr1 = rasterPtr;
204
205   /* Read encoded data to a continuous array pointed to by rsterPtr */
206   do {
207     byte = byte1 = *pchFileStream++;
208
209     while (byte--)
210       *ptr1++ = *pchFileStream++;
211
212     if ((long) (ptr1 - rasterPtr) > lFileSize)  /* Currupt file */
213       goto _ExitReadError;
214   }
215   while (byte1);
216
217   Xw_free (pchFileStream_start); /* The file data has been already read */
218   pchFileStream_start = NULL;
219
220
221
222   if (! (pidata = (char *) Xw_malloc (width*height)))
223     goto _ExitAllocError;
224
225
226   x = y = pass = OutCount = BitOffset = ByteOffset = 0;
227
228   /* Fetch the next code (3 to 12 bits) from the raster data stream */
229   Code = rasterPtr[0] + (((unsigned) rasterPtr[1]) << 8);
230   if (CodeSize >= 8)
231     Code += ((unsigned) rasterPtr[2]) << 16;
232
233   Code >>= BitOffset & 0x7;
234   BitOffset += CodeSize;
235   Code      &= ReadMask;
236
237
238   while (Code != EOFCode) {
239
240   
241     if (Code == ClearCode) {
242    
243       /* Read the next code */
244       CodeSize   = InitCodeSize;
245       MaxCode    = 1 << CodeSize;
246       ReadMask   = MaxCode - 1;
247       FreeCode   = FirstFree;
248       ByteOffset = BitOffset >> 3;
249       Code       = rasterPtr[ByteOffset];
250
251       Code       = rasterPtr[ByteOffset]
252                    + (((unsigned) rasterPtr[ByteOffset + 1]) << 8);
253       if (CodeSize >= 8)
254         Code += ((unsigned) rasterPtr[ByteOffset + 2]) << 16;
255
256       Code      >>= BitOffset & 0x7;
257       BitOffset +=  CodeSize;
258       Code      &=  ReadMask;
259
260       CurCode = OldCode = Code;
261       FinChar = CurCode & BitMask;
262
263       _ADD_PIXEL (FinChar);
264     }
265     else {
266    
267       CurCode = InCode = Code;
268
269       if (CurCode >= FreeCode) {
270         
271         CurCode = OldCode;
272         OutCode[OutCount++] = FinChar;
273       }
274
275       while (CurCode > BitMask) {
276         
277         if (OutCount > 1024)
278           goto _ExitReadError;
279
280         OutCode [OutCount++] = Suffix [CurCode];
281         CurCode = Prefix [CurCode];
282       }
283
284       FinChar = CurCode & BitMask;
285       OutCode [OutCount++] = FinChar;
286
287       for (i = OutCount - 1; i >= 0; --i)
288         _ADD_PIXEL (OutCode [i]);
289
290       OutCount = 0;
291       Prefix [FreeCode] = OldCode;
292       Suffix [FreeCode] = FinChar;
293       OldCode = InCode;
294       ++FreeCode;
295
296       if (FreeCode >= MaxCode) {
297         
298         if (CodeSize < 12) {
299      
300           ++CodeSize;
301           MaxCode <<= 1;
302           ReadMask = (1 << CodeSize) - 1;
303         }
304       }
305     }
306
307     ByteOffset = BitOffset >> 3;
308     Code = (unsigned) rasterPtr[ByteOffset];
309     Code = (unsigned) rasterPtr[ByteOffset]
310            + (((unsigned) rasterPtr[ByteOffset + 1]) << 8);
311     if (CodeSize >= 8)
312       Code += ((unsigned) rasterPtr[ByteOffset + 2]) << 16;
313
314     Code >>= (BitOffset & 0x7);
315     BitOffset += CodeSize;
316     Code &=  ReadMask;
317   }
318   
319
320   /* Allocate the Image structure */
321   if (! (pximage = (XImage*) Xw_malloc(sizeof(XImage))))
322     goto _ExitAllocError;
323
324   /* Allocate the Extended Image structure */
325   if(! (pimage = Xw_add_imagedata_structure (sizeof(XW_EXT_IMAGEDATA))))
326     goto _ExitError;
327
328
329   /* Initialize the input image */
330   pimage->pimageinfo = aimageinfo;
331   _IIMAGE = pximage;
332   _IIMAGE->data = pidata;
333   _IIMAGE->width = (int) width;
334   _IIMAGE->height = (int) height;
335   _IIMAGE->xoffset = (int) 0;
336   _IIMAGE->format = (int) ZPixmap;
337   _IIMAGE->byte_order = (int) LSBFirst;
338   _IIMAGE->bitmap_unit = (int) 8;
339   _IIMAGE->bitmap_bit_order = (int) LSBFirst;
340   _IIMAGE->bitmap_pad = (int) 8;
341   _IIMAGE->depth = (int) 24;
342   _IIMAGE->bits_per_pixel = (int) 8;
343   _IIMAGE->bytes_per_line = (int) width;
344   _IIMAGE->red_mask = 0;
345   _IIMAGE->green_mask = 0;
346   _IIMAGE->blue_mask = 0;
347   _IIMAGE->obdata = NULL ;
348   _XInitImageFuncPtrs (_IIMAGE);
349
350
351   /* Return array of colors */
352   *ppcolors = pcolors;
353   *pncolors = ncolors;
354
355   if (wname) Xw_free(wname);
356
357
358 #ifdef DEBUG
359   fprintf (stderr, "\r\nXw_load_gif_image: Operation completed successfully.\r\n");
360 #endif /*DEBUG*/
361
362
363   /* Successfully loaded */
364
365 #ifdef PURIFY
366   if (rasterPtr) Xw_free (rasterPtr);
367   if (OutCode) Xw_free (OutCode);
368   if (Prefix) Xw_free (Prefix);
369   if (Suffix) Xw_free (Suffix);
370 #endif
371   return (pimage);
372
373
374
375 _ExitReadError:
376
377   /*ERROR*Unable to read Image data
378   Xw_set_error(61,"Xw_load_gif_image",filename);
379   */
380   fprintf (stderr, "\r\nXw_load_gif_image: Error reading %s!", filename);
381   goto _ExitError;
382
383
384 _ExitAllocError:
385   /*ERROR*Bad Image allocation
386   Xw_set_error(60,"Xw_load_gif_image",0);
387   */
388   fprintf (stderr, "\r\nXw_load_gif_image: Error: Out of memory!");
389
390
391 _ExitError:
392
393 #ifdef DEB
394   fprintf (stderr, "\r\nXw_load_gif_image: An error occured! Returning NULL.");
395 #endif /*DEB*/
396
397   if (pchFileStream_start) Xw_free (pchFileStream_start);
398   if (pximage) Xw_free (pximage);
399   if (rasterPtr) Xw_free (rasterPtr);
400   if (pidata) Xw_free (pidata);
401   if (pimage) Xw_free (pidata);
402   if (pcolors) Xw_free (pcolors);
403   if (OutCode) Xw_free (OutCode);
404   if (Prefix) Xw_free (Prefix);
405   if (Suffix) Xw_free (Suffix);
406   
407   return (NULL);
408 }
409
410 #undef _ADD_PIXEL