/* * Created: zov : 22-Apr-1998 : Loads GIF image from file * XW_EXT_IMAGEDATA* Xw_load_gif_image (awindow,aimageinfo,fimage,ppcolors,pncolors) XW_EXT_WINDOW *awindow XW_USERDATA *aimageinfo XColor **ppcolors - address of pointer to array of used colors to return int *pncolors - address of a variable to return length of the array in Gets an image from a file. Note, that the file must be GIF formatted. Returns the image descriptor address if successful; or NULL if failed. */ #define PURIFY /*GG+STT 11/01/99 // Avoid Free memory leak. */ #include #include #define _ADD_PIXEL(idx) \ { \ if (y < height) *(pidata + y*width + x) = ((unsigned char)(idx)); \ if (++x == width) { \ x = 0; \ if (!isInterlace) ++y; \ else switch (pass) { \ case 0: y += 8; if (y >= height) ++pass, y = 4; break; \ case 1: y += 8; if (y >= height) ++pass, y = 2; break; \ case 2: y += 4; if (y >= height) ++pass, y = 1; break; \ default: y += 2; \ } \ } \ } /* Note, ** Portions Copyright (c) of CISIGRAPH SOFTWARE. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ XW_EXT_IMAGEDATA *Xw_load_gif_image (void *awindow,void *aimageinfo,char *filename,int fimage, XColor **ppcolors, int *pncolors) { // XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW *)awindow; XW_EXT_IMAGEDATA *pimage = NULL; // XW_STATUS status; XImage *pximage = NULL; XColor *pcolors = NULL; char *wname = NULL, *pidata = NULL; unsigned char byte, byte1; unsigned *OutCode=NULL, *Prefix=NULL, *Suffix=NULL, BitMask, CodeSize, ClearCode, EOFCode, FreeCode, x, y, pass, width, height, InitCodeSize, MaxCode, ReadMask, FirstFree, OutCount, BitOffset, ByteOffset, Code, CurCode, OldCode=0, FinChar=0, InCode; long lFileSize; // int i, isize, dataSize, ncolors; int i, ncolors; static unsigned char *pchFileStream_start = NULL, *pchFileStream, *ptr1, *rasterPtr = NULL; int isInterlace, hasColormap; if (-1 == (lFileSize = lseek (fimage, 0, SEEK_END)) || NULL == (pchFileStream_start = (unsigned char *) Xw_malloc (lFileSize)) || 0 != lseek (fimage, 0, SEEK_SET) || lFileSize != read (fimage, (char *)pchFileStream_start, lFileSize) ) goto _ExitReadError; pchFileStream = pchFileStream_start + 10; byte = *pchFileStream++; /* Color descriptor byte (M#CR0#BP) */ hasColormap = byte & 0x80; ncolors = hasColormap ? 1<<((byte & 0x07) + 1): 1<<8; BitMask = ncolors - 1; #ifdef DEBUG fprintf (stderr, "\r\nXw_load_gif_image: GIF contains %d colors.", hasColormap? ncolors: 0); #endif /*DEBUG*/ pchFileStream += 2; /* Skip background byte and following zero byte */ if (ncolors > 0) { /* Allocate Color Table entries */ if (! (pcolors = (XColor*) Xw_calloc(ncolors, sizeof(XColor)))) goto _ExitAllocError; for (i=0; i<...><...><0> */ while (*pchFileStream == '!') { pchFileStream += 2; /* skip code byte followed '!' sign */ while (*pchFileStream) pchFileStream += (unsigned)(1 + *(unsigned char *)pchFileStream); pchFileStream ++; } if (*pchFileStream++ != ',') { /* must be an image descriptor */ #ifdef DEB fprintf (stderr, "\r\nXw_load_gif_image: Error: There's no separator" " following the colormap"); #endif /*DEB*/ goto _ExitReadError; } pchFileStream += 2*2; /* Skip image left & top offsets*/ width = (unsigned) *pchFileStream++; width += ((unsigned)*pchFileStream++) << 8; height = (unsigned) *pchFileStream++; height += ((unsigned)*pchFileStream++) << 8; byte = *pchFileStream++; isInterlace = byte & 0x40; if (byte & 0x80) { fprintf (stderr, "\r\nXw_load_gif_image:" " Can't read GIF image with locally defined colormap!\r\n"); goto _ExitReadError; } #ifdef DEBUG fprintf (stderr, "\r\nXw_load_gif_image: Dimensions: %dx%d" " Interlace mode: %s", width, height, isInterlace? "ON": "OFF"); #endif /*DEBUG*/ /* Allocate the pixel buffer */ if (! (rasterPtr = (unsigned char *) Xw_malloc(lFileSize))) goto _ExitAllocError; OutCode = (unsigned *)Xw_malloc(1025 * sizeof (unsigned)); Prefix = (unsigned *)Xw_malloc(4096 * sizeof (unsigned)); Suffix = (unsigned *)Xw_malloc(4096 * sizeof (unsigned)); if (!OutCode || !Prefix || !Suffix) goto _ExitAllocError; /* Decode compressed raster data. */ CodeSize = *pchFileStream++; ClearCode = 1 << CodeSize; EOFCode = ClearCode + 1; FreeCode = FirstFree = EOFCode + 1; ++CodeSize; InitCodeSize = CodeSize; MaxCode = 1 << CodeSize; ReadMask = MaxCode - 1; ptr1 = rasterPtr; /* Read encoded data to a continuous array pointed to by rsterPtr */ do { byte = byte1 = *pchFileStream++; while (byte--) *ptr1++ = *pchFileStream++; if ((long) (ptr1 - rasterPtr) > lFileSize) /* Currupt file */ goto _ExitReadError; } while (byte1); Xw_free (pchFileStream_start); /* The file data has been already read */ pchFileStream_start = NULL; if (! (pidata = (char *) Xw_malloc (width*height))) goto _ExitAllocError; x = y = pass = OutCount = BitOffset = ByteOffset = 0; /* Fetch the next code (3 to 12 bits) from the raster data stream */ Code = rasterPtr[0] + (((unsigned) rasterPtr[1]) << 8); if (CodeSize >= 8) Code += ((unsigned) rasterPtr[2]) << 16; Code >>= BitOffset & 0x7; BitOffset += CodeSize; Code &= ReadMask; while (Code != EOFCode) { if (Code == ClearCode) { /* Read the next code */ CodeSize = InitCodeSize; MaxCode = 1 << CodeSize; ReadMask = MaxCode - 1; FreeCode = FirstFree; ByteOffset = BitOffset >> 3; Code = rasterPtr[ByteOffset]; Code = rasterPtr[ByteOffset] + (((unsigned) rasterPtr[ByteOffset + 1]) << 8); if (CodeSize >= 8) Code += ((unsigned) rasterPtr[ByteOffset + 2]) << 16; Code >>= BitOffset & 0x7; BitOffset += CodeSize; Code &= ReadMask; CurCode = OldCode = Code; FinChar = CurCode & BitMask; _ADD_PIXEL (FinChar); } else { CurCode = InCode = Code; if (CurCode >= FreeCode) { CurCode = OldCode; OutCode[OutCount++] = FinChar; } while (CurCode > BitMask) { if (OutCount > 1024) goto _ExitReadError; OutCode [OutCount++] = Suffix [CurCode]; CurCode = Prefix [CurCode]; } FinChar = CurCode & BitMask; OutCode [OutCount++] = FinChar; for (i = OutCount - 1; i >= 0; --i) _ADD_PIXEL (OutCode [i]); OutCount = 0; Prefix [FreeCode] = OldCode; Suffix [FreeCode] = FinChar; OldCode = InCode; ++FreeCode; if (FreeCode >= MaxCode) { if (CodeSize < 12) { ++CodeSize; MaxCode <<= 1; ReadMask = (1 << CodeSize) - 1; } } } ByteOffset = BitOffset >> 3; Code = (unsigned) rasterPtr[ByteOffset]; Code = (unsigned) rasterPtr[ByteOffset] + (((unsigned) rasterPtr[ByteOffset + 1]) << 8); if (CodeSize >= 8) Code += ((unsigned) rasterPtr[ByteOffset + 2]) << 16; Code >>= (BitOffset & 0x7); BitOffset += CodeSize; Code &= ReadMask; } /* Allocate the Image structure */ if (! (pximage = (XImage*) Xw_malloc(sizeof(XImage)))) goto _ExitAllocError; /* Allocate the Extended Image structure */ if(! (pimage = Xw_add_imagedata_structure (sizeof(XW_EXT_IMAGEDATA)))) goto _ExitError; /* Initialize the input image */ pimage->pimageinfo = aimageinfo; _IIMAGE = pximage; _IIMAGE->data = pidata; _IIMAGE->width = (int) width; _IIMAGE->height = (int) height; _IIMAGE->xoffset = (int) 0; _IIMAGE->format = (int) ZPixmap; _IIMAGE->byte_order = (int) LSBFirst; _IIMAGE->bitmap_unit = (int) 8; _IIMAGE->bitmap_bit_order = (int) LSBFirst; _IIMAGE->bitmap_pad = (int) 8; _IIMAGE->depth = (int) 24; _IIMAGE->bits_per_pixel = (int) 8; _IIMAGE->bytes_per_line = (int) width; _IIMAGE->red_mask = 0; _IIMAGE->green_mask = 0; _IIMAGE->blue_mask = 0; _IIMAGE->obdata = NULL ; _XInitImageFuncPtrs (_IIMAGE); /* Return array of colors */ *ppcolors = pcolors; *pncolors = ncolors; if (wname) Xw_free(wname); #ifdef DEBUG fprintf (stderr, "\r\nXw_load_gif_image: Operation completed successfully.\r\n"); #endif /*DEBUG*/ /* Successfully loaded */ #ifdef PURIFY if (rasterPtr) Xw_free (rasterPtr); if (OutCode) Xw_free (OutCode); if (Prefix) Xw_free (Prefix); if (Suffix) Xw_free (Suffix); #endif return (pimage); _ExitReadError: /*ERROR*Unable to read Image data Xw_set_error(61,"Xw_load_gif_image",filename); */ fprintf (stderr, "\r\nXw_load_gif_image: Error reading %s!", filename); goto _ExitError; _ExitAllocError: /*ERROR*Bad Image allocation Xw_set_error(60,"Xw_load_gif_image",0); */ fprintf (stderr, "\r\nXw_load_gif_image: Error: Out of memory!"); _ExitError: #ifdef DEB fprintf (stderr, "\r\nXw_load_gif_image: An error occured! Returning NULL."); #endif /*DEB*/ if (pchFileStream_start) Xw_free (pchFileStream_start); if (pximage) Xw_free (pximage); if (rasterPtr) Xw_free (rasterPtr); if (pidata) Xw_free (pidata); if (pimage) Xw_free (pidata); if (pcolors) Xw_free (pcolors); if (OutCode) Xw_free (OutCode); if (Prefix) Xw_free (Prefix); if (Suffix) Xw_free (Suffix); return (NULL); } #undef _ADD_PIXEL