/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % DDDD EEEEE CCCC OOO DDDD EEEEE % % D D E C O O D D E % % D D EEE C O O D D EEE % % D D E C O O D D E % % DDDD EEEEE CCCC OOO DDDD EEEEE % % % % % % Utility Routines to Read Image Formats % % % % % % Software Design % % John Cristy % % January 1992 % % % % % % Copyright 1997 E. I. du Pont de Nemours and Company % % % % Permission to use, copy, modify, distribute, and sell this software and % % its documentation for any purpose is hereby granted without fee, % % provided that the above Copyright notice appear in all copies and that % % both that Copyright notice and this permission notice appear in % % supporting documentation, and that the name of E. I. du Pont de Nemours % % and Company not be used in advertising or publicity pertaining to % % distribution of the software without specific, written prior % % permission. E. I. du Pont de Nemours and Company makes no representations % % about the suitability of this software for any purpose. It is provided % % "as is" without express or implied warranty. % % % % E. I. du Pont de Nemours and Company disclaims all warranties with regard % % to this software, including all implied warranties of merchantability % % and fitness, in no event shall E. I. du Pont de Nemours and Company be % % liable for any special, indirect or consequential damages or any % % damages whatsoever resulting from loss of use, data or profits, whether % % in an action of contract, negligence or other tortious action, arising % % out of or in connection with the use or performance of this software. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Functions in this library convert to and from `alien' image formats to the % MIFF image format. % % */ /* Include declarations. */ #include "magick.h" #include "XWDFile.h" #include "plug-ins.h" /* Define declarations. */ #define LoadImageText " Loading image... " #define PrematureExit(message,image) \ { \ Warning(message,image->filename); \ DestroyImages(image); \ return((Image *) NULL); \ } /* Function prototypes. */ static Image *ReadMIFFImage(const ImageInfo *), *ReadPNMImage(const ImageInfo *), *ReadPSImage(const ImageInfo *), *ReadXCImage(const ImageInfo *); /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d A V S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadAVSImage reads a AVS X image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadAVSImage routine is: % % image=ReadAVSImage(image_info) % % A description of each parameter follows: % % o image: Function ReadAVSImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or if % the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadAVSImage(const ImageInfo *image_info) { Image *image; Quantum blue, green, red; register int x, y; register RunlengthPacket *q; unsigned int packets; unsigned long height, width; unsigned short index; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Read AVS image. */ width=MSBFirstReadLong(image->file); height=MSBFirstReadLong(image->file); if ((width == (unsigned long) ~0) || (height == (unsigned long) ~0)) PrematureExit("Not a AVS image file",image); do { /* Initialize image structure. */ image->columns=width; image->rows=height; image->packets=0; packets=Max((image->columns*image->rows+4) >> 3,1); image->pixels=(RunlengthPacket *) malloc(packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Unable to allocate memory",image); /* Convert AVS raster image to runlength-encoded packets. */ q=image->pixels; q->length=MaxRunlength; for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { index=UpScale(fgetc(image->file)); image->matte|=index != Transparent; red=UpScale(fgetc(image->file)); green=UpScale(fgetc(image->file)); blue=UpScale(fgetc(image->file)); if ((red == q->red) && (green == q->green) && (blue == q->blue) && (index == q->index) && ((int) q->length < MaxRunlength)) q->length++; else { if (image->packets != 0) q++; image->packets++; if (image->packets == packets) { packets<<=1; image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Unable to allocate memory",image); q=image->pixels+image->packets-1; } q->red=red; q->green=green; q->blue=blue; q->index=index; q->length=0; } } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,y,image->rows); } image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket)); width=MSBFirstReadLong(image->file); height=MSBFirstReadLong(image->file); if ((width != (unsigned long) ~0) && (height != (unsigned long) ~0)) { /* Allocate next image structure. */ AllocateNextImage(image_info,image); if (image->next == (Image *) NULL) { DestroyImages(image); return((Image *) NULL); } image=image->next; ProgressMonitor(LoadImageText,(unsigned int) ftell(image->file), (unsigned int) image->filesize); } } while ((width != (unsigned long) ~0) && (height != (unsigned long) ~0)); while (image->previous != (Image *) NULL) image=image->previous; CloseImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d B M P I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadBMPImage reads a Microsoft Windows bitmap image file and % returns it. It allocates the memory necessary for the new Image structure % and returns a pointer to the new image. % % The format of the ReadBMPImage routine is: % % image=ReadBMPImage(image_info) % % A description of each parameter follows: % % o image: Function ReadBMPImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadBMPImage(const ImageInfo *image_info) { typedef struct _BMPHeader { unsigned long file_size; unsigned short reserved[2]; unsigned long offset_bits, size, width, height; unsigned short planes, bit_count; unsigned long compression, image_size, x_pixels, y_pixels, number_colors, colors_important; } BMPHeader; BMPHeader bmp_header; Image *image; long start_position; register int bit, i, x, y; register RunlengthPacket *q; register unsigned char *p; unsigned char *bmp_data, *bmp_pixels, magick[12]; unsigned int bytes_per_line, image_size, status; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Determine if this is a BMP file. */ status=ReadData((char *) magick,1,2,image->file); do { /* Verify BMP identifier. */ start_position=ftell(image->file)-2; if ((status == False) || (strncmp((char *) magick,"BM",2) != 0)) PrematureExit("Not a BMP image file",image); bmp_header.file_size=LSBFirstReadLong(image->file); bmp_header.reserved[0]=LSBFirstReadShort(image->file); bmp_header.reserved[1]=LSBFirstReadShort(image->file); bmp_header.offset_bits=LSBFirstReadLong(image->file); bmp_header.size=LSBFirstReadLong(image->file); if (bmp_header.size == 12) { /* OS/2 BMP image file. */ bmp_header.width=(unsigned long) LSBFirstReadShort(image->file); bmp_header.height=(unsigned long) LSBFirstReadShort(image->file); bmp_header.planes=LSBFirstReadShort(image->file); bmp_header.bit_count=LSBFirstReadShort(image->file); bmp_header.x_pixels=0; bmp_header.y_pixels=0; bmp_header.number_colors=0; bmp_header.compression=0; bmp_header.image_size=0; } else { /* Microsoft Windows BMP image file. */ bmp_header.width=LSBFirstReadLong(image->file); bmp_header.height=LSBFirstReadLong(image->file); bmp_header.planes=LSBFirstReadShort(image->file); bmp_header.bit_count=LSBFirstReadShort(image->file); bmp_header.compression=LSBFirstReadLong(image->file); bmp_header.image_size=LSBFirstReadLong(image->file); bmp_header.x_pixels=LSBFirstReadLong(image->file); bmp_header.y_pixels=LSBFirstReadLong(image->file); bmp_header.number_colors=LSBFirstReadLong(image->file); bmp_header.colors_important=LSBFirstReadLong(image->file); for (i=0; i < ((int) bmp_header.size-40); i++) (void) fgetc(image->file); } if (bmp_header.bit_count < 24) { unsigned char *bmp_colormap; unsigned int packet_size; /* Read BMP raster colormap. */ image->class=PseudoClass; image->colors=(unsigned int) bmp_header.number_colors; if (image->colors == 0) image->colors=1 << bmp_header.bit_count; image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); bmp_colormap=(unsigned char *) malloc(4*image->colors*sizeof(unsigned char)); if ((image->colormap == (ColorPacket *) NULL) || (bmp_colormap == (unsigned char *) NULL)) PrematureExit("Unable to allocate memory",image); packet_size=4; if (bmp_header.size == 12) packet_size=3; (void) ReadData((char *) bmp_colormap,packet_size,image->colors, image->file); p=bmp_colormap; for (i=0; i < image->colors; i++) { image->colormap[i].blue=UpScale(*p++); image->colormap[i].green=UpScale(*p++); image->colormap[i].red=UpScale(*p++); if (bmp_header.size != 12) p++; } free((char *) bmp_colormap); } /* Read image data. */ while (ftell(image->file) < (start_position+bmp_header.offset_bits)) (void) fgetc(image->file); image_size= ((bmp_header.width*bmp_header.bit_count+31)/32)*4*bmp_header.height; if ((bmp_header.image_size == 0) || (bmp_header.image_size > image_size)) bmp_header.image_size=image_size; bmp_data=(unsigned char *) malloc(bmp_header.image_size*sizeof(unsigned char)); if (bmp_data == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); (void) ReadData((char *) bmp_data,1,(unsigned int) bmp_header.image_size, image->file); bmp_pixels=bmp_data; if (bmp_header.compression != 0) { unsigned int packets; /* Convert run-length encoded raster pixels. */ packets=(unsigned int) (((bmp_header.width*bmp_header.bit_count+31)/32)*4*bmp_header.height); if (bmp_header.compression == 2) packets<<=1; bmp_pixels=(unsigned char *) malloc(packets*sizeof(unsigned char)); if (bmp_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); (void) BMPDecodeImage(bmp_data,bmp_pixels, (unsigned int) bmp_header.compression,(unsigned int) bmp_header.width, (unsigned int) bmp_header.height); if (bmp_header.compression == 2) bmp_header.bit_count<<=1; free((char *) bmp_data); } /* Initialize image structure. */ image->columns=(unsigned int) bmp_header.width; image->rows=(unsigned int) bmp_header.height; image->units=PixelsPerCentimeterResolution; image->x_resolution=bmp_header.x_pixels/100.0; image->y_resolution=bmp_header.y_pixels/100.0; image->packets=image->columns*image->rows; image->pixels=(RunlengthPacket *) malloc(image->packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Unable to allocate memory",image); /* Convert BMP raster image to runlength-encoded packets. */ bytes_per_line=((image->columns*bmp_header.bit_count+31)/32)*4; switch (bmp_header.bit_count) { case 1: { /* Convert bitmap scanline to runlength-encoded color packets. */ for (y=image->rows-1; y >= 0; y--) { p=bmp_pixels+(image->rows-y-1)*bytes_per_line; q=image->pixels+(y*image->columns); for (x=0; x < ((int) image->columns-7); x+=8) { for (bit=0; bit < 8; bit++) { q->index=((*p) & (0x80 >> bit) ? 0x01 : 0x00); q->length=0; q++; } p++; } if ((image->columns % 8) != 0) { for (bit=0; bit < (image->columns % 8); bit++) { q->index=((*p) & (0x80 >> bit) ? 0x01 : 0x00); q->length=0; q++; } p++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); } SyncImage(image); break; } case 4: { /* Convert PseudoColor scanline to runlength-encoded color packets. */ for (y=image->rows-1; y >= 0; y--) { p=bmp_pixels+(image->rows-y-1)*bytes_per_line; q=image->pixels+(y*image->columns); for (x=0; x < ((int) image->columns-1); x+=2) { q->index=(*p >> 4) & 0xf; q->length=0; q++; q->index=(*p) & 0xf; q->length=0; p++; q++; } if ((image->columns % 2) != 0) { q->index=(*p >> 4) & 0xf; q->length=0; q++; p++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); } SyncImage(image); break; } case 8: { /* Convert PseudoColor scanline to runlength-encoded color packets. */ if (bmp_header.compression == 1) bytes_per_line=image->columns; for (y=image->rows-1; y >= 0; y--) { p=bmp_pixels+(image->rows-y-1)*bytes_per_line; q=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { q->index=(*p++); q->length=0; q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); } SyncImage(image); break; } case 24: { /* Convert DirectColor scanline to runlength-encoded color packets. */ for (y=image->rows-1; y >= 0; y--) { p=bmp_pixels+(image->rows-y-1)*bytes_per_line; q=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { q->index=0; if (image->matte) q->index=UpScale(*p++); q->blue=UpScale(*p++); q->green=UpScale(*p++); q->red=UpScale(*p++); q->length=0; q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); } break; } default: PrematureExit("Not a BMP image file",image); } free((char *) bmp_pixels); CompressImage(image); /* Proceed to next image. */ status=ReadData((char *) magick,1,2,image->file); if ((status == True) && (strncmp((char *) magick,"BM",2) == 0)) { /* Allocate next image structure. */ AllocateNextImage(image_info,image); if (image->next == (Image *) NULL) { DestroyImages(image); return((Image *) NULL); } image=image->next; ProgressMonitor(LoadImageText,(unsigned int) ftell(image->file), (unsigned int) image->filesize); } } while ((status == True) && (strncmp((char *) magick,"BM",2) == 0)); while (image->previous != (Image *) NULL) image=image->previous; CloseImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d C G M I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadCGMImage reads a Computer Graphic Meta image file % and returns it. It allocates the memory necessary for the new Image % structure and returns a pointer to the new image. % % The format of the ReadCGMImage routine is: % % image=ReadCGMImage(image_info) % % A description of each parameter follows: % % o image: Function ReadCGMImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadCGMImage(const ImageInfo *image_info) { char filename[MaxTextExtent]; Image *image, *next_image, *proxy_image; /* Allocate image structure. */ proxy_image=AllocateImage(image_info); if (proxy_image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,proxy_image,ReadBinaryType); if (proxy_image->file == (FILE *) NULL) PrematureExit("Unable to open file",proxy_image); CloseImage(proxy_image); DestroyImage(proxy_image); /* Use ralcgm to convert Macintosh CGM image. */ (void) strcpy(filename,image_info->filename); (void) sprintf(image_info->filename,CGMCommand,filename); image=ReadPSImage(image_info); if (image == (Image *) NULL) { Warning("CGM translation failed",image_info->filename); return((Image *) NULL); } /* Assign proper filename. */ do { (void) strcpy(image->filename,filename); next_image=image->next; if (next_image != (Image *) NULL) image=next_image; } while (next_image != (Image *) NULL); while (image->previous != (Image *) NULL) image=image->previous; return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d C M Y K I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadCMYKImage reads an image of raw cyan, magenta, yellow, and % black bytes and returns it. It allocates the memory necessary for the new % Image structure and returns a pointer to the new image. % % The format of the ReadCMYKImage routine is: % % image=ReadCMYKImage(image_info) % % A description of each parameter follows: % % o image: Function ReadCMYKImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadCMYKImage(const ImageInfo *image_info) { Image *image; int count, x, x_offset, y, y_offset; register int i; register RunlengthPacket *q; register unsigned char *p; unsigned char *scanline; unsigned int black, cyan, height, magenta, packet_size, yellow, width; unsigned short value; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Determine width and height, e.g. 640x512. */ width=512; height=512; x_offset=0; y_offset=0; x=0; if (image_info->size != (char *) NULL) (void) XParseGeometry(image_info->size,&x,&y,&width,&height); if (image_info->interlace != PartitionInterlace) { /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); for (i=0; i < x; i++) (void) fgetc(image->file); } /* Allocate memory for a scanline. */ packet_size=4*(QuantumDepth >> 3); scanline=(unsigned char *) malloc(packet_size*width*sizeof(unsigned char)); if (scanline == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); if (image_info->subrange != 0) while (image->scene < image_info->subimage) { /* Skip to next image. */ image->scene++; for (y=0; y < height; y++) (void) ReadData((char *) scanline,packet_size,width,image->file); } do { /* Initialize image structure. */ image->columns=width; image->rows=height; if (image_info->subrange == 0) if (image_info->tile != (char *) NULL) (void) XParseGeometry(image_info->tile,&x_offset,&y_offset, &image->columns,&image->rows); image->packets=image->columns*image->rows; image->pixels=(RunlengthPacket *) malloc(image->packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Unable to allocate memory",image); /* Convert raster image to runlength-encoded packets. */ switch (image_info->interlace) { case NoneInterlace: default: { /* No interlacing: CMYKCMYKCMYKCMYKCMYK... */ for (y=0; y < y_offset; y++) (void) ReadData((char *) scanline,packet_size,width,image->file); q=image->pixels; for (y=0; y < image->rows; y++) { if ((y > 0) || (image->previous == (Image *) NULL)) (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; for (x=0; x < image->columns; x++) { ReadQuantum(q->red,p); ReadQuantum(q->green,p); ReadQuantum(q->blue,p); ReadQuantum(q->index,p); q->length=0; q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,y,image->rows); } break; } case LineInterlace: { /* Line interlacing: CCC...MMM...YYY...KKK...CCC...MMM...YYY...KKK... */ packet_size=image->depth >> 3; for (y=0; y < y_offset; y++) (void) ReadData((char *) scanline,packet_size,width,image->file); for (y=0; y < image->rows; y++) { if ((y > 0) || (image->previous == (Image *) NULL)) (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; q=image->pixels+y*image->columns; for (x=0; x < image->columns; x++) { ReadQuantum(q->red,p); q->length=0; q++; } (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; q=image->pixels+y*image->columns; for (x=0; x < image->columns; x++) { ReadQuantum(q->green,p); q++; } (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; q=image->pixels+y*image->columns; for (x=0; x < image->columns; x++) { ReadQuantum(q->blue,p); q++; } (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; q=image->pixels+y*image->columns; for (x=0; x < image->columns; x++) { ReadQuantum(q->index,p); q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,y,image->rows); } break; } case PlaneInterlace: case PartitionInterlace: { /* Plane interlacing: CCCCCC...MMMMMM...YYYYYY...KKKKKK... */ if (image_info->interlace == PartitionInterlace) { AppendImageFormat("C",image->filename); OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } packet_size=image->depth >> 3; for (y=0; y < y_offset; y++) (void) ReadData((char *) scanline,packet_size,width,image->file); i=0; q=image->pixels; for (y=0; y < image->rows; y++) { if ((y > 0) || (image->previous == (Image *) NULL)) (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; for (x=0; x < image->columns; x++) { ReadQuantum(q->red,p); q->length=0; q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,i++,image->rows << 2); } if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("M",image->filename); OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } q=image->pixels; for (y=0; y < (height-image->rows); y++) (void) ReadData((char *) scanline,packet_size,width,image->file); for (y=0; y < image->rows; y++) { (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; for (x=0; x < image->columns; x++) { ReadQuantum(q->green,p); q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,i++,image->rows << 2); } if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("Y",image->filename); OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } q=image->pixels; for (y=0; y < (height-image->rows); y++) (void) ReadData((char *) scanline,packet_size,width,image->file); for (y=0; y < image->rows; y++) { (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; for (x=0; x < image->columns; x++) { ReadQuantum(q->blue,p); q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,i++,image->rows << 2); } if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("K",image->filename); OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } q=image->pixels; for (y=0; y < (height-image->rows); y++) (void) ReadData((char *) scanline,packet_size,width,image->file); for (y=0; y < image->rows; y++) { (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; for (x=0; x < image->columns; x++) { ReadQuantum(q->index,p); q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,i++,image->rows << 2); } if (image_info->interlace == PartitionInterlace) (void) strcpy(image->filename,image_info->filename); break; } } /* Transform image from CMYK to RGB. */ q=image->pixels; for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { cyan=q->red; magenta=q->green; yellow=q->blue; black=q->index; if ((cyan+black) > MaxRGB) q->red=0; else q->red=MaxRGB-(cyan+black); if ((magenta+black) > MaxRGB) q->green=0; else q->green=MaxRGB-(magenta+black); if ((yellow+black) > MaxRGB) q->blue=0; else q->blue=MaxRGB-(yellow+black); q->index=0; q->length=0; q++; } } CompressImage(image); if (image_info->subrange != 0) if (image->scene >= (image_info->subimage+image_info->subrange-1)) break; /* Proceed to next image. */ count=ReadData((char *) scanline,packet_size,width,image->file); if (count > 0) { /* Allocate next image structure. */ AllocateNextImage(image_info,image); if (image->next == (Image *) NULL) { DestroyImages(image); return((Image *) NULL); } image=image->next; ProgressMonitor(LoadImageText,(unsigned int) ftell(image->file), (unsigned int) image->filesize); } } while (count > 0); while (image->previous != (Image *) NULL) image=image->previous; free((char *) scanline); CloseImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d D P S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadDPSImage reads a Adobe Postscript image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadDPSImage routine is: % % image=ReadDPSImage(image_info) % % A description of each parameter follows: % % o image: Function ReadDPSImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ #ifdef HasDPS static Image *ReadDPSImage(const ImageInfo *image_info) { Display *display; float pixels_per_point; Image *image; int sans, status, x, y; Pixmap pixmap; register int i; register RunlengthPacket *p; register unsigned long pixel; Screen *screen; XColor *colors; XImage *dps_image; XRectangle bounding_box, pixel_size; XResourceInfo resource_info; XrmDatabase resource_database; XStandardColormap *map_info; XVisualInfo *visual_info; /* Open X server connection. */ display=XOpenDisplay(image_info->server_name); if (display == (Display *) NULL) return((Image *) NULL); /* Set our forgiving error handler. */ XSetErrorHandler(XError); /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) return((Image *) NULL); /* Get user defaults from X resource database. */ resource_database=XGetResourceDatabase(display,client_name); XGetResourceInfo(resource_database,client_name,&resource_info); /* Allocate standard colormap. */ map_info=XAllocStandardColormap(); if (map_info == (XStandardColormap *) NULL) Warning("Unable to create standard colormap","Memory allocation failed"); else { /* Initialize visual info. */ resource_info.visual_type="default"; visual_info=XBestVisualInfo(display,map_info,&resource_info); map_info->colormap=(Colormap) NULL; } if ((map_info == (XStandardColormap *) NULL) || (visual_info == (XVisualInfo *) NULL)) { DestroyImage(image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } /* Create a pixmap the appropriate size for the image. */ screen=ScreenOfDisplay(display,visual_info->screen); pixels_per_point=XDPSPixelsPerPoint(screen); if (image_info->density != (char *) NULL) { float x_resolution, y_resolution; int count; x_resolution=72.0*XDPSPixelsPerPoint(screen); count=sscanf(image_info->density,"%fx%f",&x_resolution,&y_resolution); if (count != 2) y_resolution=x_resolution; pixels_per_point=Min(x_resolution,y_resolution)/72.0; } status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen,image->file, visual_info->depth,pixels_per_point,&pixmap,&pixel_size,&bounding_box); if ((status == dps_status_failure) || (status == dps_status_no_extension)) { DestroyImage(image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } /* Rasterize the file into the pixmap. */ status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap,image->file, pixel_size.height,visual_info->depth,&bounding_box,-bounding_box.x, -bounding_box.y,pixels_per_point,True,False,True,&sans); if (status != dps_status_success) { DestroyImage(image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } /* Initialize DPS X image. */ dps_image=XGetImage(display,pixmap,0,0,pixel_size.width,pixel_size.height, AllPlanes,ZPixmap); XFreePixmap(display,pixmap); if (dps_image == (XImage *) NULL) { DestroyImage(image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } /* Get the colormap colors. */ colors=(XColor *) malloc(visual_info->colormap_size*sizeof(XColor)); if (colors == (XColor *) NULL) { DestroyImage(image); XDestroyImage(dps_image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } if ((visual_info->class != DirectColor) && (visual_info->class != TrueColor)) for (i=0; i < visual_info->colormap_size; i++) { colors[i].pixel=i; colors[i].pad=0; } else { unsigned long blue, blue_bit, green, green_bit, red, red_bit; /* DirectColor or TrueColor visual. */ red=0; green=0; blue=0; red_bit=visual_info->red_mask & (~(visual_info->red_mask)+1); green_bit=visual_info->green_mask & (~(visual_info->green_mask)+1); blue_bit=visual_info->blue_mask & (~(visual_info->blue_mask)+1); for (i=0; i < visual_info->colormap_size; i++) { colors[i].pixel=red | green | blue; colors[i].pad=0; red+=red_bit; if (red > visual_info->red_mask) red=0; green+=green_bit; if (green > visual_info->green_mask) green=0; blue+=blue_bit; if (blue > visual_info->blue_mask) blue=0; } } XQueryColors(display,XDefaultColormap(display,visual_info->screen),colors, visual_info->colormap_size); /* Convert X image to MIFF format. */ if ((visual_info->class != TrueColor) && (visual_info->class != DirectColor)) image->class=PseudoClass; image->columns=dps_image->width; image->rows=dps_image->height; image->packets=image->columns*image->rows; image->pixels=(RunlengthPacket *) malloc(image->packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) { DestroyImage(image); free((char *) colors); XDestroyImage(dps_image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } p=image->pixels; switch (image->class) { case DirectClass: default: { register unsigned long color, index; unsigned long blue_mask, blue_shift, green_mask, green_shift, red_mask, red_shift; /* Determine shift and mask for red, green, and blue. */ red_mask=visual_info->red_mask; red_shift=0; while ((red_mask & 0x01) == 0) { red_mask>>=1; red_shift++; } green_mask=visual_info->green_mask; green_shift=0; while ((green_mask & 0x01) == 0) { green_mask>>=1; green_shift++; } blue_mask=visual_info->blue_mask; blue_shift=0; while ((blue_mask & 0x01) == 0) { blue_mask>>=1; blue_shift++; } /* Convert X image to DirectClass packets. */ if ((visual_info->colormap_size > 0) && (visual_info->class == DirectColor)) for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { pixel=XGetPixel(dps_image,x,y); index=(pixel >> red_shift) & red_mask; p->red=XDownScale(colors[index].red); index=(pixel >> green_shift) & green_mask; p->green=XDownScale(colors[index].green); index=(pixel >> blue_shift) & blue_mask; p->blue=XDownScale(colors[index].blue); p->index=0; p->length=0; p++; } ProgressMonitor(LoadImageText,y,image->rows); } else for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { pixel=XGetPixel(dps_image,x,y); color=(pixel >> red_shift) & red_mask; p->red=XDownScale((color*65535L)/red_mask); color=(pixel >> green_shift) & green_mask; p->green=XDownScale((color*65535L)/green_mask); color=(pixel >> blue_shift) & blue_mask; p->blue=XDownScale((color*65535L)/blue_mask); p->index=0; p->length=0; p++; } ProgressMonitor(LoadImageText,y,image->rows); } break; } case PseudoClass: { /* Create colormap. */ image->colors=visual_info->colormap_size; image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); if (image->colormap == (ColorPacket *) NULL) { DestroyImage(image); free((char *) colors); XDestroyImage(dps_image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } for (i=0; i < image->colors; i++) { image->colormap[colors[i].pixel].red=XDownScale(colors[i].red); image->colormap[colors[i].pixel].green=XDownScale(colors[i].green); image->colormap[colors[i].pixel].blue=XDownScale(colors[i].blue); } /* Convert X image to PseudoClass packets. */ for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { p->index=(unsigned short) XGetPixel(dps_image,x,y); p->length=0; p++; } ProgressMonitor(LoadImageText,y,image->rows); } SyncImage(image); break; } } if (image->class == PseudoClass) CompressColormap(image); free((char *) colors); XDestroyImage(dps_image); /* Rasterize matte image. */ status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen,image->file,1, pixels_per_point,&pixmap,&pixel_size,&bounding_box); if ((status != dps_status_failure) && (status != dps_status_no_extension)) { status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap, image->file,pixel_size.height,1,&bounding_box,-bounding_box.x, -bounding_box.y,pixels_per_point,True,True,True,&sans); if (status == dps_status_success) { XImage *matte_image; /* Initialize image matte. */ matte_image=XGetImage(display,pixmap,0,0,pixel_size.width, pixel_size.height,AllPlanes,ZPixmap); XFreePixmap(display,pixmap); if (matte_image != (XImage *) NULL) { image->class=DirectClass; image->matte=True; p=image->pixels; for (y=0; y < image->rows; y++) for (x=0; x < image->columns; x++) { p->index=Opaque; if (!XGetPixel(matte_image,x,y)) p->index=Transparent; p++; } XDestroyImage(matte_image); } } } /* Free resources. */ XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); CompressImage(image); CloseImage(image); return(image); } #else static Image *ReadDPSImage(const ImageInfo *image_info) { Warning("Cannot read DPS images",image_info->filename); return((Image *) NULL); } #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d F A X I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadFAXImage reads a Group 3 FAX image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadFAXImage routine is: % % image=ReadFAXImage(image_info) % % A description of each parameter follows: % % o image: Function ReadFAXImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadFAXImage(const ImageInfo *image_info) { Image *image; int x, y; unsigned int height, status, width; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Determine width and height, e.g. 640x512. */ width=2592; height=3508; if (image_info->size != (char *) NULL) (void) XParseGeometry(image_info->size,&x,&y,&width,&height); /* Initialize image structure. */ image->class=PseudoClass; image->columns=width; image->rows=height; image->packets=Max((image->columns*image->rows+8) >> 4,1); image->pixels=(RunlengthPacket *) malloc(image->packets*sizeof(RunlengthPacket)); image->colors=2; image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); if ((image->pixels == (RunlengthPacket *) NULL) || (image->colormap == (ColorPacket *) NULL)) PrematureExit("Unable to allocate memory",image); /* Monochrome colormap. */ image->colormap[0].red=MaxRGB; image->colormap[0].green=MaxRGB; image->colormap[0].blue=MaxRGB; image->colormap[1].red=0; image->colormap[1].green=0; image->colormap[1].blue=0; status=HuffmanDecodeImage(image); if (status == False) PrematureExit("Unable to read image data",image); CloseImage(image); TransformImage(&image,"0x0",(char *) NULL); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d F I T S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadFITSImage reads a FITS image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadFITSImage routine is: % % image=ReadFITSImage(image_info) % % A description of each parameter follows: % % o image: Function ReadFITSImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or if % the image cannot be read. % % o filename: Specifies the name of the image to read. % % */ static Image *ReadFITSImage(const ImageInfo *image_info) { typedef struct _FITSHeader { unsigned int simple; int bits_per_pixel; unsigned int number_of_axis, columns, rows, depth; double min_data, max_data, zero, scale; } FITSHeader; char long_quantum[8], keyword[MaxTextExtent], value[MaxTextExtent]; double pixel, scale, scaled_pixel; FITSHeader fits_header; Image *image; int j, packet_size, y; long count, quantum; register int c, i, x; register RunlengthPacket *q; register unsigned char *p; unsigned char *fits_pixels; unsigned int status, value_expected; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Initialize image header. */ fits_header.simple=False; fits_header.bits_per_pixel=8; fits_header.columns=1; fits_header.rows=1; fits_header.depth=1; fits_header.min_data=0.0; fits_header.max_data=0.0; fits_header.zero=0.0; fits_header.scale=1.0; /* Decode image header. */ c=fgetc(image->file); count=1; if (c == EOF) { DestroyImage(image); return((Image *) NULL); } for ( ; ; ) { if (!isalnum(c)) { c=fgetc(image->file); count++; } else { register char *p; /* Determine a keyword and its value. */ p=keyword; do { if ((p-keyword) < (MaxTextExtent-1)) *p++=(char) c; c=fgetc(image->file); count++; } while (isalnum(c) || (c == '_')); *p='\0'; if (strcmp(keyword,"END") == 0) break; value_expected=False; while (isspace(c) || (c == '=')) { if (c == '=') value_expected=True; c=fgetc(image->file); count++; } if (value_expected == False) continue; p=value; while (isalnum(c) || (c == '-') || (c == '+') || (c == '.')) { if ((p-value) < (MaxTextExtent-1)) *p++=(char) c; c=fgetc(image->file); count++; } *p='\0'; /* Assign a value to the specified keyword. */ if (strcmp(keyword,"SIMPLE") == 0) fits_header.simple=(*value == 'T') || (*value == 't'); if (strcmp(keyword,"BITPIX") == 0) fits_header.bits_per_pixel=(unsigned int) atoi(value); if (strcmp(keyword,"NAXIS") == 0) fits_header.number_of_axis=(unsigned int) atoi(value); if (strcmp(keyword,"NAXIS1") == 0) fits_header.columns=(unsigned int) atoi(value); if (strcmp(keyword,"NAXIS2") == 0) fits_header.rows=(unsigned int) atoi(value); if (strcmp(keyword,"NAXIS3") == 0) fits_header.depth=(unsigned int) atoi(value); if (strcmp(keyword,"DATAMAX") == 0) fits_header.max_data=atof(value); if (strcmp(keyword,"DATAMIN") == 0) fits_header.min_data=atof(value); if (strcmp(keyword,"BZERO") == 0) fits_header.zero=atof(value); if (strcmp(keyword,"BSCALE") == 0) fits_header.scale=atof(value); } while (isspace(c)) { c=fgetc(image->file); count++; } } while (count > 2880) count-=2880; for ( ; count < 2880; count++) (void) fgetc(image->file); /* Verify that required image information is defined. */ if ((!fits_header.simple) || (fits_header.number_of_axis < 1) || (fits_header.number_of_axis > 4) || (fits_header.columns*fits_header.rows) == 0) PrematureExit("image type not supported",image); /* Create linear colormap. */ image->columns=fits_header.columns; image->rows=fits_header.rows; image->class=PseudoClass; image->colors=MaxRGB+1; image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); if (image->colormap == (ColorPacket *) NULL) PrematureExit("Unable to open file",image); for (i=0; i < image->colors; i++) { image->colormap[i].red=(Quantum) UpScale(i); image->colormap[i].green=(Quantum) UpScale(i); image->colormap[i].blue=(Quantum) UpScale(i); } /* Initialize image structure. */ image->packets=image->columns*image->rows; image->pixels=(RunlengthPacket *) malloc(image->packets*sizeof(RunlengthPacket)); packet_size=fits_header.bits_per_pixel/8; if (packet_size < 0) packet_size=(-packet_size); fits_pixels=(unsigned char *) malloc(image->packets*packet_size*sizeof(unsigned char)); if ((image->pixels == (RunlengthPacket *) NULL) || (fits_pixels == (unsigned char *) NULL)) PrematureExit("Unable to allocate memory",image); /* Convert FITS pixels to runlength-encoded packets. */ status=ReadData((char *) fits_pixels,(unsigned int) packet_size, image->packets,image->file); if (status == False) Warning("Insufficient image data in file",image->filename); if ((fits_header.min_data == 0.0) && (fits_header.max_data == 0.0)) { /* Determine minimum and maximum intensity. */ p=fits_pixels; long_quantum[0]=(*p); quantum=(*p++); for (j=0; j < (packet_size-1); j++) { long_quantum[j+1]=(*p); quantum=(quantum << 8) | (*p++); } pixel=(double) quantum; if (fits_header.bits_per_pixel == -32) pixel=(double) (*((float *) &quantum)); if (fits_header.bits_per_pixel == -64) pixel=(double) (*((double *) long_quantum)); fits_header.min_data=pixel*fits_header.scale+fits_header.zero; fits_header.max_data=pixel*fits_header.scale+fits_header.zero; for (i=1; i < image->packets; i++) { long_quantum[0]=(*p); quantum=(*p++); for (j=0; j < (packet_size-1); j++) { long_quantum[j+1]=(*p); quantum=(quantum << 8) | (*p++); } pixel=(double) quantum; if (fits_header.bits_per_pixel == -32) pixel=(double) (*((float *) &quantum)); if (fits_header.bits_per_pixel == -64) pixel=(double) (*((double *) long_quantum)); scaled_pixel=pixel*fits_header.scale+fits_header.zero; if (scaled_pixel < fits_header.min_data) fits_header.min_data=scaled_pixel; if (scaled_pixel > fits_header.max_data) fits_header.max_data=scaled_pixel; } } /* Convert FITS pixels to runlength-encoded packets. */ scale=1.0; if (fits_header.min_data != fits_header.max_data) scale=(MaxRGB+1)/(fits_header.max_data-fits_header.min_data); p=fits_pixels; q=image->pixels; for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { long_quantum[0]=(*p); quantum=(*p++); for (j=0; j < (packet_size-1); j++) { long_quantum[j+1]=(*p); quantum=(quantum << 8) | (*p++); } pixel=(double) quantum; if (fits_header.bits_per_pixel == -32) pixel=(double) (*((float *) &quantum)); if (fits_header.bits_per_pixel == -64) pixel=(double) (*((double *) long_quantum)); scaled_pixel=scale* (pixel*fits_header.scale+fits_header.zero-fits_header.min_data); while (scaled_pixel < 0) scaled_pixel+=(MaxRGB+1); while (scaled_pixel > MaxRGB) scaled_pixel-=(MaxRGB+1); q->index=(unsigned short) scaled_pixel; q->length=0; q++; } ProgressMonitor(LoadImageText,y,image->rows); } free((char *) fits_pixels); SyncImage(image); CompressColormap(image); CompressImage(image); CloseImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d G I F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadGIFImage reads a Compuserve Graphics image file and returns it. % It allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadGIFImage routine is: % % image=ReadGIFImage(image_info) % % A description of each parameter follows: % % o image: Function ReadGIFImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % an error occurs. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadGIFImage(ImageInfo *image_info) { #define BitSet(byte,bit) (((byte) & (bit)) == (bit)) #define LSBFirstOrder(x,y) (((y) << 8) | (x)) char geometry[MaxTextExtent]; Image *image; int status, x, y; RectangleInfo page_info; register int i; register RunlengthPacket *q; register unsigned char *p; short int transparency_index; unsigned char background, c, flag, *global_colormap, header[MaxTextExtent], magick[12]; unsigned int delay, dispose, global_colors, image_count, iterations; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Determine if this is a GIF file. */ status=ReadData((char *) magick,1,6,image->file); if ((status == False) || ((strncmp((char *) magick,"GIF87",5) != 0) && (strncmp((char *) magick,"GIF89",5) != 0))) PrematureExit("Not a GIF image file",image); global_colors=0; global_colormap=(unsigned char *) NULL; page_info.width=LSBFirstReadShort(image->file); page_info.height=LSBFirstReadShort(image->file); (void) ReadData((char *) &flag,1,1,image->file); (void) ReadData((char *) &background,1,1,image->file); (void) ReadData((char *) &c,1,1,image->file); /* reserved */ if (BitSet(flag,0x80)) { /* Read global colormap. */ global_colors=1 << ((flag & 0x07)+1); global_colormap=(unsigned char *) malloc(3*global_colors*sizeof(unsigned char)); if (global_colormap == (unsigned char *) NULL) PrematureExit("Unable to read image colormap file",image); (void) ReadData((char *) global_colormap,3,global_colors,image->file); } delay=0; dispose=0; iterations=1; transparency_index=(-1); image_count=0; for ( ; ; ) { status=ReadData((char *) &c,1,1,image->file); if (status == False) break; if (c == ';') break; /* terminator */ if (c == '!') { /* GIF Extension block. */ status=ReadData((char *) &c,1,1,image->file); if (status == False) PrematureExit("Unable to read extention block",image); switch (c) { case 0xf9: { /* Read Graphics Control extension. */ while (ReadDataBlock((char *) header,image->file) > 0); dispose=header[0] >> 2; delay=(header[2] << 8) | header[1]; if ((header[0] & 0x01) == 1) transparency_index=header[3]; break; } case 0xfe: { int length; /* Read Comment extension. */ for ( ; ; ) { length=ReadDataBlock((char *) header,image->file); if (length <= 0) break; if (image->comments != (char *) NULL) image->comments=(char *) realloc((char *) image->comments, (Extent(image->comments)+length+1)*sizeof(char)); else { image->comments=(char *) malloc((length+1)*sizeof(char)); if (image->comments != (char *) NULL) *image->comments='\0'; } if (image->comments == (char *) NULL) PrematureExit("Unable to allocate memory",image); header[length]='\0'; (void) strcat(image->comments,(char *) header); } break; } case 0xff: { /* Read Netscape Loop extension. */ while (ReadDataBlock((char *) header,image->file) > 0); iterations=(header[2] << 8) | header[1]; break; } default: { while (ReadDataBlock((char *) header,image->file) > 0); break; } } } if (c != ',') continue; if (image_count != 0) { /* Allocate next image structure. */ AllocateNextImage(image_info,image); if (image->next == (Image *) NULL) { DestroyImages(image); return((Image *) NULL); } image=image->next; ProgressMonitor(LoadImageText,(unsigned int) ftell(image->file), (unsigned int) image->filesize); } image_count++; /* Read image attributes. */ image->class=PseudoClass; page_info.x=LSBFirstReadShort(image->file); page_info.y=LSBFirstReadShort(image->file); image->columns=LSBFirstReadShort(image->file); image->rows=LSBFirstReadShort(image->file); image->packets=image->columns*image->rows; if (image->packets == 0) PrematureExit("image size is 0",image); /* Allocate image. */ if (image->pixels != (RunlengthPacket *) NULL) free((char *) image->pixels); image->pixels=(RunlengthPacket *) malloc(image->packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Unable to allocate memory",image); (void) sprintf(geometry,"%ux%u%+d%+d",page_info.width,page_info.height, page_info.x,page_info.y); image->page=PostscriptGeometry(geometry); image->delay=delay; image->dispose=dispose; image->iterations=iterations; delay=0; dispose=0; iterations=1; /* Inititialize colormap. */ (void) ReadData((char *) &flag,1,1,image->file); image->interlace=BitSet(flag,0x40) ? PlaneInterlace : NoneInterlace; image->colors=!BitSet(flag,0x80) ? global_colors : 1 << ((flag & 0x07)+1); image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); if (image->colormap == (ColorPacket *) NULL) PrematureExit("Unable to allocate memory",image); if (!BitSet(flag,0x80)) { /* Use global colormap. */ p=global_colormap; for (i=0; i < image->colors; i++) { image->colormap[i].red=UpScale(*p++); image->colormap[i].green=UpScale(*p++); image->colormap[i].blue=UpScale(*p++); } image->background_color=image->colormap[background]; } else { unsigned char *colormap; /* Read local colormap. */ colormap=(unsigned char *) malloc(3*image->colors*sizeof(unsigned char)); if (colormap == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); (void) ReadData((char *) colormap,3,image->colors,image->file); p=colormap; for (i=0; i < image->colors; i++) { image->colormap[i].red=UpScale(*p++); image->colormap[i].green=UpScale(*p++); image->colormap[i].blue=UpScale(*p++); } free((char *) colormap); } /* Decode image. */ status=GIFDecodeImage(image); if (image->interlace != NoneInterlace) { Image *interlaced_image; int pass; register RunlengthPacket *p; static int interlace_rate[4] = { 8, 8, 4, 2 }, interlace_start[4] = { 0, 4, 2, 1 }; /* Interlace image. */ image_info->interlace=LineInterlace; image->orphan=True; interlaced_image=CloneImage(image,image->columns,image->rows,True); image->orphan=False; if (interlaced_image == (Image *) NULL) PrematureExit("Unable to allocate memory",image); p=interlaced_image->pixels; q=image->pixels; for (pass=0; pass < 4; pass++) { y=interlace_start[pass]; while (y < image->rows) { q=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { *q=(*p); p++; q++; } y+=interlace_rate[pass]; } } DestroyImage(interlaced_image); } if (transparency_index >= 0) { /* Create matte channel. */ q=image->pixels; for (i=0; i < image->packets; i++) { if (q->index != (unsigned short) transparency_index) q->index=Opaque; else q->index=Transparent; q++; } transparency_index=(-1); image->class=DirectClass; image->matte=True; } if (status == False) { Warning("Corrupt GIF image",image->filename); break; } CompressImage(image); if (image_info->subrange != 0) if ((image->scene+1) < image_info->subimage) { Image subimage; /* Destroy image. */ subimage=(*image); image->file=(FILE *) NULL; DestroyImage(image); image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); image->file=subimage.file; image->scene=subimage.scene+1; image_count=0; } else if ((image->scene+1) > (image_info->subimage+image_info->subrange-1)) break; } if (global_colormap != (unsigned char *) NULL) free((char *) global_colormap); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Corrupt GIF image or subimage not found",image); while (image->previous != (Image *) NULL) image=image->previous; CloseImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d G R A D A T I O N I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadGRADATIONImage creates a gradation image and initializes it to % the X server color range as specified by the filename. It allocates the % memory necessary for the new Image structure and returns a pointer to the % new image. % % The format of the ReadGRADATIONImage routine is: % % image=ReadGRADATIONImage(image_info) % % A description of each parameter follows: % % o image: Function ReadGRADATIONImage returns a pointer to the image after % creating it. A null image is returned if there is a a memory shortage % or if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadGRADATIONImage(const ImageInfo *image_info) { char colorname[MaxTextExtent]; double brightness, brightness_step, hue, hue_step, saturation, saturation_step; Image *image; int x, y; register RunlengthPacket *q; unsigned int height, width; XColor color; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Determine width and height, e.g. 640x512. */ width=512; height=512; if (image_info->size != (char *) NULL) (void) XParseGeometry(image_info->size,&x,&y,&width,&height); /* Initialize Image structure. */ (void) strcpy(image->filename,image_info->filename); image->columns=width; image->rows=height; image->packets=image->columns*image->rows; image->pixels=(RunlengthPacket *) malloc(image->packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Unable to allocate memory",image); /* Determine (Hue, Saturation, Brightness) gradient. */ (void) strcpy(colorname,image_info->filename); (void) sscanf(image_info->filename,"%[^-]",colorname); (void) XQueryColorDatabase(colorname,&color); TransformHSL(XDownScale(color.red),XDownScale(color.green), XDownScale(color.blue),&hue,&saturation,&brightness); (void) strcpy(colorname,"white"); if (Intensity(color) > 32767) (void) strcpy(colorname,"black"); (void) sscanf(image_info->filename,"%*[^-]-%s",colorname); (void) XQueryColorDatabase(colorname,&color); TransformHSL(XDownScale(color.red),XDownScale(color.green), XDownScale(color.blue),&hue_step,&saturation_step,&brightness_step); hue_step=(hue_step-hue)/(double) image->packets; saturation_step=(saturation_step-saturation)/(double) image->packets; brightness_step=(brightness_step-brightness)/(double) image->packets; /* Initialize image pixels. */ q=image->pixels; for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { HSLTransform(hue,saturation,brightness,&q->red,&q->green,&q->blue); q->index=0; q->length=0; q++; hue+=hue_step; saturation+=saturation_step; brightness+=brightness_step; } ProgressMonitor(LoadImageText,y,image->rows); } CompressImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d G R A Y I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadGRAYImage reads an image of raw grayscale bytes and returns it. % It allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadGRAYImage routine is: % % image=ReadGRAYImage(image_info) % % A description of each parameter follows: % % o image: Function ReadGRAYImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadGRAYImage(const ImageInfo *image_info) { Image *image; int count, x, x_offset, y, y_offset; register int i; register RunlengthPacket *q; register unsigned char *p; unsigned char *scanline; unsigned int height, packet_size, packets, width; unsigned short index, value; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Determine width and height, e.g. 640x512. */ width=512; height=512; x_offset=0; y_offset=0; if (image_info->size != (char *) NULL) { x=0; (void) XParseGeometry(image_info->size,&x,&y,&width,&height); for (i=0; i < x; i++) (void) fgetc(image->file); } /* Allocate memory for a scanline. */ packet_size=image->depth >> 3; scanline=(unsigned char *) malloc(packet_size*width*sizeof(unsigned char)); if (scanline == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); if (image_info->subrange != 0) while (image->scene < image_info->subimage) { /* Skip to next image. */ image->scene++; for (y=0; y < height; y++) (void) ReadData((char *) scanline,packet_size,width,image->file); } do { /* Initialize image structure. */ image->columns=width; image->rows=height; if (image_info->subrange == 0) if (image_info->tile != (char *) NULL) (void) XParseGeometry(image_info->tile,&x_offset,&y_offset, &image->columns,&image->rows); image->packets=0; packets=Max((image->columns*image->rows+2) >> 2,1); image->pixels=(RunlengthPacket *) malloc(packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Unable to allocate memory",image); /* Create linear colormap. */ image->class=PseudoClass; image->colors=1 << image->depth; image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); if (image->colormap == (ColorPacket *) NULL) PrematureExit("Unable to allocate memory",image); for (i=0; i < image->colors; i++) { image->colormap[i].red=(Quantum) i; image->colormap[i].green=(Quantum) i; image->colormap[i].blue=(Quantum) i; } /* Convert raster image to runlength-encoded packets. */ for (y=0; y < y_offset; y++) (void) ReadData((char *) scanline,packet_size,width,image->file); q=image->pixels; q->length=MaxRunlength; for (y=0; y < image->rows; y++) { if ((y > 0) || (image->previous == (Image *) NULL)) (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; for (x=0; x < image->columns; x++) { ReadQuantum(index,p); if ((index == q->index) && ((int) q->length < MaxRunlength)) q->length++; else { if (image->packets != 0) q++; image->packets++; if (image->packets == packets) { packets<<=1; image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) { free((char *) scanline); PrematureExit("Unable to allocate memory",image); } q=image->pixels+image->packets-1; } q->index=index; q->length=0; } } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,y,image->rows); } image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket)); SyncImage(image); CompressColormap(image); if (image_info->subrange != 0) if (image->scene >= (image_info->subimage+image_info->subrange-1)) break; /* Proceed to next image. */ count=ReadData((char *) scanline,packet_size,width,image->file); if (count > 0) { /* Allocate next image structure. */ AllocateNextImage(image_info,image); if (image->next == (Image *) NULL) { DestroyImages(image); return((Image *) NULL); } image=image->next; ProgressMonitor(LoadImageText,(unsigned int) ftell(image->file), (unsigned int) image->filesize); } } while (count > 0); while (image->previous != (Image *) NULL) image=image->previous; free((char *) scanline); CloseImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d H D F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadHDFImage reads a Hierarchical Data Format image file and % returns it. It allocates the memory necessary for the new Image structure % and returns a pointer to the new image. % % The format of the ReadHDFImage routine is: % % image=ReadHDFImage(image_info) % % A description of each parameter follows: % % o image: Function ReadHDFImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ #ifdef HasHDF static Image *ReadHDFImage(ImageInfo *image_info) { #include "hdf.h" #undef BSD #undef LOCAL ClassType class; Image *image; int interlace, is_palette, status, y; int32 height, length, width; register int i, x; register unsigned char *p; register RunlengthPacket *q; uint16 reference; unsigned char *hdf_pixels; unsigned int packet_size; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); CloseImage(image); /* Read HDF image. */ class=DirectClass; status=DF24getdims(image->filename,&width,&height,&interlace); if (status == -1) { class=PseudoClass; status=DFR8getdims(image->filename,&width,&height,&is_palette); } if (status == -1) PrematureExit("Image file or does not contain any image data",image); do { /* Initialize image structure. */ image->class=class; image->columns=width; image->rows=height; image->packets=image->columns*image->rows; packet_size=1; if (image->class == DirectClass) packet_size=3; hdf_pixels=(unsigned char *) malloc(packet_size*image->packets*sizeof(unsigned char)); image->pixels=(RunlengthPacket *) malloc(image->packets*sizeof(RunlengthPacket)); if ((hdf_pixels == (unsigned char *) NULL) || (image->pixels == (RunlengthPacket *) NULL)) PrematureExit("Unable to allocate memory",image); q=image->pixels; if (image->class == PseudoClass) { unsigned char *hdf_palette; /* Create colormap. */ hdf_palette=(unsigned char *) malloc(768*sizeof(unsigned char)); image->colors=256; image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); if ((hdf_palette == (unsigned char *) NULL) || (image->colormap == (ColorPacket *) NULL)) PrematureExit("Unable to allocate memory",image); (void) DFR8getimage(image->filename,hdf_pixels,(int) image->columns, (int) image->rows,hdf_palette); reference=DFR8lastref(); /* Convert HDF raster image to PseudoClass runlength-encoded packets. */ p=hdf_palette; if (is_palette) for (i=0; i < 256; i++) { image->colormap[i].red=UpScale(*p++); image->colormap[i].green=UpScale(*p++); image->colormap[i].blue=UpScale(*p++); } else for (i=0; i < image->colors; i++) { image->colormap[i].red=(Quantum) UpScale(i); image->colormap[i].green=(Quantum) UpScale(i); image->colormap[i].blue=(Quantum) UpScale(i); } free((char *) hdf_palette); p=hdf_pixels; for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { q->index=(*p++); q->length=0; q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,y,image->rows); } SyncImage(image); } else { int y; /* Convert HDF raster image to DirectClass runlength-encoded packets. */ (void) DF24getimage(image->filename,(void *) hdf_pixels,image->columns, image->rows); reference=DF24lastref(); p=hdf_pixels; image->interlace=interlace ? PlaneInterlace : NoneInterlace; q=image->pixels; for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { q->red=UpScale(*p++); q->green=UpScale(*p++); q->blue=UpScale(*p++); q->index=0; q->length=0; q++; } if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,y,image->rows); } } length=DFANgetlablen(image->filename,DFTAG_RIG,reference); if (length > 0) { /* Read the image label. */ length+=MaxTextExtent; image->label=(char *) malloc(length*sizeof(char)); if (image->label != (char *) NULL) DFANgetlabel(image->filename,DFTAG_RIG,reference,image->label,length); } length=DFANgetdesclen(image->filename,DFTAG_RIG,reference); if (length > 0) { /* Read the image comments. */ length+=MaxTextExtent; image->comments=(char *) malloc(length*sizeof(char)); if (image->comments != (char *) NULL) DFANgetdesc(image->filename,DFTAG_RIG,reference,image->comments, length); } free((char *) hdf_pixels); CompressImage(image); class=DirectClass; status=DF24getdims(image->filename,&width,&height,&interlace); if (status == -1) { class=PseudoClass; status=DFR8getdims(image->filename,&width,&height,&is_palette); } if (status != -1) { /* Allocate next image structure. */ AllocateNextImage(image_info,image); if (image->next == (Image *) NULL) { DestroyImages(image); return((Image *) NULL); } image=image->next; ProgressMonitor(LoadImageText,(unsigned int) ftell(image->file), (unsigned int) image->filesize); } } while (status != -1); while (image->previous != (Image *) NULL) image=image->previous; return(image); } #else static Image *ReadHDFImage(const ImageInfo *image_info) { Warning("HDF library is not available",image_info->filename); return(ReadMIFFImage(image_info)); } #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d H I S T O G R A M I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadHISTOGRAMImage reads a HISTOGRAM image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadHISTOGRAMImage routine is: % % image=ReadHISTOGRAMImage(image_info) % % A description of each parameter follows: % % o image: Function ReadHISTOGRAMImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadHISTOGRAMImage(const ImageInfo *image_info) { Image *image; image=ReadMIFFImage(image_info); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d H T M L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadHTMLImage reads a HTML image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadHTMLImage routine is: % % image=ReadHTMLImage(image_info) % % A description of each parameter follows: % % o image: Function ReadHTMLImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadHTMLImage(const ImageInfo *image_info) { Image *image; Warning("Cannot read HTML images",image_info->filename); image=ReadMIFFImage(image_info); return(image); } #ifdef HasJBIG /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d J B I G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadJBIGImage reads a JBIG image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadJBIGImage routine is: % % image=ReadJBIGImage(image_info) % % A description of each parameter follows: % % o image: Function ReadJBIGImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadJBIGImage(const ImageInfo *image_info) { #define MaxBufferSize 8192 Image *image; int status, x, y; long length; register RunlengthPacket *q; register unsigned char *p; register unsigned short index; size_t count; struct jbg_dec_state jbig_info; unsigned char bit, buffer[MaxBufferSize]; unsigned int byte, height, packets, width; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Determine maximum width and height, e.g. 640x512. */ width=65535L; height=65535L; if (image_info->size != (char *) NULL) (void) XParseGeometry(image_info->size,&x,&y,&width,&height); /* Read JBIG file. */ jbg_dec_init(&jbig_info); jbg_dec_maxsize(&jbig_info,(unsigned long) width,(unsigned long) height); status=JBG_EAGAIN; do { length=(long) fread(buffer,1,MaxBufferSize,image->file); if (length == 0) break; p=buffer; count=0; while ((length > 0) && ((status == JBG_EAGAIN) || (status == JBG_EOK))) { status=jbg_dec_in(&jbig_info,p,length,&count); p+=count; length-=count; } } while ((status == JBG_EAGAIN) || (status == JBG_EOK)); /* Initialize image structure. */ image->columns=(unsigned int) jbg_dec_getwidth(&jbig_info); image->rows=(unsigned int) jbg_dec_getheight(&jbig_info); image->packets=0; packets=Max((image->columns*image->rows+8) >> 4,1); image->pixels=(RunlengthPacket *) malloc(packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) PrematureExit("Unable to allocate memory",image); /* Create colormap. */ image->class=PseudoClass; image->colors=2; image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); if (image->colormap == (ColorPacket *) NULL) PrematureExit("Unable to allocate memory",image); image->colormap[0].red=0; image->colormap[0].green=0; image->colormap[0].blue=0; image->colormap[1].red=MaxRGB; image->colormap[1].green=MaxRGB; image->colormap[1].blue=MaxRGB; image->x_resolution=300; image->y_resolution=300; /* Convert X bitmap image to runlength-encoded packets. */ byte=0; p=jbg_dec_getimage(&jbig_info,0); q=image->pixels; q->length=MaxRunlength; for (y=0; y < image->rows; y++) { bit=0; for (x=0; x < image->columns; x++) { if (bit == 0) byte=(*p++); index=(byte & 0x80) ? 0 : 1; if ((index == q->index) && ((int) q->length < MaxRunlength)) q->length++; else { if (image->packets != 0) q++; image->packets++; if (image->packets == packets) { packets<<=1; image->pixels=(RunlengthPacket *) realloc((char *) image->pixels, packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) { jbg_dec_free(&jbig_info); PrematureExit("Unable to allocate memory",image); } q=image->pixels+image->packets-1; } q->index=index; q->length=0; } bit++; byte<<=1; if (bit == 8) bit=0; } ProgressMonitor(LoadImageText,y,image->rows); } jbg_dec_free(&jbig_info); SyncImage(image); image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket)); CloseImage(image); return(image); } #else static Image *ReadJBIGImage(const ImageInfo *image_info) { Warning("JBIG library is not available",image_info->filename); return(ReadMIFFImage(image_info)); } #endif #ifdef HasJPEG static Image *image; static jmp_buf error_recovery; /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d J P E G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadJPEGImage reads a JPEG image file and returns it. It allocates % the memory necessary for the new Image structure and returns a pointer to % the new image. % % The format of the ReadJPEGImage routine is: % % image=ReadJPEGImage(image_info) % % A description of each parameter follows: % % o image: Function ReadJPEGImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o filename: Specifies the name of the jpeg image to read. % % */ static unsigned int GetCharacter(j_decompress_ptr jpeg_info) { struct jpeg_source_mgr *data; data=jpeg_info->src; if (data->bytes_in_buffer == 0) (*data->fill_input_buffer) (jpeg_info); data->bytes_in_buffer--; return(GETJOCTET(*data->next_input_byte++)); } static boolean CommentHandler(j_decompress_ptr jpeg_info) { long int length; register char *p; /* Determine length of comment. */ length=GetCharacter(jpeg_info) << 8; length+=GetCharacter(jpeg_info); length-=2; if (image->comments != (char *) NULL) image->comments=(char *) realloc((char *) image->comments, (unsigned int) (Extent(image->comments)+length+1)*sizeof(char)); else { image->comments=(char *) malloc((unsigned int) (length+1)*sizeof(char)); if (image->comments != (char *) NULL) *image->comments='\0'; } if (image->comments == (char *) NULL) { Warning("Memory allocation error",(char *) NULL); return(False); } /* Read comment. */ p=image->comments+Extent(image->comments); while (--length >= 0) *p++=GetCharacter(jpeg_info); *p='\0'; return(True); } static void EmitMessage(j_common_ptr jpeg_info,int level) { char message[JMSG_LENGTH_MAX]; struct jpeg_error_mgr *jpeg_error; jpeg_error=jpeg_info->err; (jpeg_error->format_message) (jpeg_info,message); if (level < 0) { if ((jpeg_error->num_warnings == 0) || (jpeg_error->trace_level >= 3)) Warning((char *) message,image->filename); jpeg_error->num_warnings++; } else if (jpeg_error->trace_level >= level) Warning((char *) message,image->filename); } static void ErrorExit(j_common_ptr jpeg_info) { EmitMessage(jpeg_info,0); longjmp(error_recovery,1); } static Image *ReadJPEGImage(const ImageInfo *image_info) { int x, y; JSAMPLE *jpeg_pixels; JSAMPROW scanline[1]; Quantum blue, green, red; register int i; register JSAMPLE *p; register RunlengthPacket *q; struct jpeg_decompress_struct jpeg_info; struct jpeg_error_mgr jpeg_error; unsigned int packets; unsigned short index; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Initialize image structure. */ jpeg_info.err=jpeg_std_error(&jpeg_error); jpeg_info.err->emit_message=EmitMessage; jpeg_info.err->error_exit=ErrorExit; image->pixels=(RunlengthPacket *) NULL; jpeg_pixels=(JSAMPLE *) NULL; if (setjmp(error_recovery)) { /* JPEG image is corrupt. */ if (jpeg_pixels != (JSAMPLE *) NULL) { free((char *) jpeg_pixels); jpeg_destroy_decompress(&jpeg_info); } DestroyImage(image); return((Image *) NULL); } jpeg_create_decompress(&jpeg_info); jpeg_set_marker_processor(&jpeg_info,JPEG_COM,CommentHandler); jpeg_stdio_src(&jpeg_info,image->file); (void) jpeg_read_header(&jpeg_info,True); if (jpeg_info.saw_JFIF_marker) { /* Set image resolution. */ image->x_resolution=jpeg_info.X_density; image->y_resolution=jpeg_info.Y_density; if (jpeg_info.density_unit == 1) image->units=PixelsPerInchResolution; if (jpeg_info.density_unit == 2) image->units=PixelsPerCentimeterResolution; } if (image_info->size != (char *) NULL) { unsigned int height, width; unsigned long scale_factor; /* Let the JPEG library subsample for us. */ jpeg_calc_output_dimensions(&jpeg_info); image->magick_columns=jpeg_info.output_width; image->magick_rows=jpeg_info.output_height; width=jpeg_info.output_width; height=jpeg_info.output_height; (void) ParseImageGeometry(image_info->size,&x,&y,&width,&height); if (width == 0) width=1; scale_factor=UpShift(jpeg_info.output_width)/width; if (height == 0) height=1; if (scale_factor > (UpShift(jpeg_info.output_height)/height)) scale_factor=UpShift(jpeg_info.output_height)/height; jpeg_info.scale_denom=DownShift(scale_factor); jpeg_calc_output_dimensions(&jpeg_info); } #if (JPEG_LIB_VERSION >= 61) jpeg_info.dct_method=JDCT_FLOAT; image->interlace=jpeg_info.progressive_mode ? PlaneInterlace : NoneInterlace; #endif jpeg_start_decompress(&jpeg_info); image->columns=jpeg_info.output_width; image->rows=jpeg_info.output_height; image->packets=0; packets=Max((image->columns*image->rows+2) >> 2,1); image->pixels=(RunlengthPacket *) malloc(packets*sizeof(RunlengthPacket)); jpeg_pixels=(JSAMPLE *) malloc(jpeg_info.output_components*image->columns*sizeof(JSAMPLE)); if ((image->pixels == (RunlengthPacket *) NULL) || (jpeg_pixels == (JSAMPLE *) NULL)) PrematureExit("Unable to allocate memory",image); if (jpeg_info.out_color_space == JCS_GRAYSCALE) { /* Initialize grayscale colormap. */ image->class=PseudoClass; image->colors=256; image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); if (image->colormap == (ColorPacket *) NULL) PrematureExit("Unable to allocate memory",image); for (i=0; i < image->colors; i++) { image->colormap[i].red=UpScale(i); image->colormap[i].green=UpScale(i); image->colormap[i].blue=UpScale(i); } } /* Convert JPEG pixels to runlength-encoded packets. */ red=0; green=0; blue=0; index=0; scanline[0]=(JSAMPROW) jpeg_pixels; q=image->pixels; q->length=MaxRunlength; for (y=0; y < image->rows; y++) { (void) jpeg_read_scanlines(&jpeg_info,scanline,1); p=jpeg_pixels; for (x=0; x < image->columns; x++) { if (jpeg_info.data_precision > QuantumDepth) { if (jpeg_info.out_color_space == JCS_GRAYSCALE) index=GETJSAMPLE(*p++) >> 4; else { red=(Quantum) (GETJSAMPLE(*p++) >> 4); green=(Quantum) (GETJSAMPLE(*p++) >> 4); blue=(Quantum) (GETJSAMPLE(*p++) >> 4); if (jpeg_info.out_color_space == JCS_CMYK) index=(Quantum) (GETJSAMPLE(*p++) >> 4); } } else if (jpeg_info.out_color_space == JCS_GRAYSCALE) index=GETJSAMPLE(*p++); else { red=(Quantum) UpScale(GETJSAMPLE(*p++)); green=(Quantum) UpScale(GETJSAMPLE(*p++)); blue=(Quantum) UpScale(GETJSAMPLE(*p++)); if (jpeg_info.out_color_space == JCS_CMYK) index=(Quantum) UpScale(GETJSAMPLE(*p++)); } if (jpeg_info.out_color_space == JCS_CMYK) { index=MAXJSAMPLE-index; if ((int) (red-index) < 0) red=0; else red-=index; if ((int) (green-index) < 0) green=0; else green-=index; if ((int) (blue-index) < 0) blue=0; else blue-=index; index=0; } if ((red == q->red) && (green == q->green) && (blue == q->blue) && (index == q->index) && ((int) q->length < MaxRunlength)) q->length++; else { if (image->packets != 0) q++; image->packets++; if (image->packets == packets) { packets<<=1; image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) { free((char *) jpeg_pixels); jpeg_destroy_decompress(&jpeg_info); PrematureExit("Unable to allocate memory",image); } q=image->pixels+image->packets-1; } q->red=red; q->green=green; q->blue=blue; q->index=index; q->length=0; } } ProgressMonitor(LoadImageText,y,image->rows); } image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket)); if (image->class == PseudoClass) { SyncImage(image); CompressColormap(image); } /* Free memory. */ free((char *) jpeg_pixels); (void) jpeg_finish_decompress(&jpeg_info); jpeg_destroy_decompress(&jpeg_info); CloseImage(image); return(image); } #else static Image *ReadJPEGImage(const ImageInfo *image_info) { Warning("JPEG library is not available",image_info->filename); return(ReadMIFFImage(image_info)); } #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d L O G O I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadLOGOImage reads a LOGO image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadLOGOImage routine is: % % image=ReadLOGOImage(image_info) % % A description of each parameter follows: % % o image: Function ReadLOGOImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadLOGOImage(ImageInfo *image_info) { #include "logo.h" char *filename, logo_filename[MaxTextExtent]; FILE *file; Image *image; register int i; register unsigned char *p; unsigned int extent; /* Open temporary output file. */ TemporaryFilename(logo_filename); file=fopen(logo_filename,WriteBinaryType); if (file == (FILE *) NULL) { Warning("Unable to write file",logo_filename); return(ReadXCImage(image_info)); } p=LogoImage; extent=LogoImageExtent; if (strcmp(image_info->magick,"GRANITE") == 0) { p=GraniteImage; extent=GraniteImageExtent; } if (strcmp(image_info->magick,"NETSCAPE") == 0) { p=NetscapeImage; extent=NetscapeImageExtent; } for (i=0; i < extent; i++) { (void) fputc((char) *p,file); p++; } if (ferror(file)) { Warning("An error has occurred writing to file",logo_filename); (void) fclose(file); (void) remove(logo_filename); return(ReadXCImage(image_info)); } (void) fclose(file); filename=image_info->filename; image_info->filename=logo_filename; image=ReadGIFImage(image_info); image_info->filename=filename; if (image != (Image *) NULL) (void) strcpy(image->filename,image_info->filename); (void) remove(logo_filename); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d M A P I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadMAPImage reads an image of raw RGB colormap and colormap index % bytes and returns it. It allocates the memory necessary for the new Image % structure and returns a pointer to the new image. % % The format of the ReadMAPImage routine is: % % image=ReadMAPImage(image_info) % % A description of each parameter follows: % % o image: Function ReadMAPImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadMAPImage(const ImageInfo *image_info) { Image *image; int colors; register int i; register unsigned char *p; unsigned char *colormap; unsigned int height, packet_size, status, width; unsigned short value; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Determine width, height, and number of colors, e.g. 640x512+256. */ width=512; height=512; colors=256; if (image_info->size != (char *) NULL) (void) XParseGeometry(image_info->size,&colors,&colors,&width,&height); /* Initialize image structure. */ image->class=PseudoClass; image->compression=NoCompression; image->columns=width; image->rows=height; image->colors=colors; image->packets=image->columns*image->rows; packet_size=3*(image->depth >> 3); colormap=(unsigned char *) malloc(packet_size*image->colors*sizeof(unsigned char)); image->colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket)); image->packed_pixels=(unsigned char *) malloc(image->packets*packet_size*(image->depth >> 3)); if ((colormap == (unsigned char *) NULL) || (image->colormap == (ColorPacket *) NULL)) PrematureExit("Unable to allocate memory",image); /* Read image colormap. */ (void) ReadData((char *) colormap,1,image->colors*packet_size,image->file); p=colormap; for (i=0; i < image->colors; i++) { ReadQuantum(image->colormap[i].red,p); ReadQuantum(image->colormap[i].green,p); ReadQuantum(image->colormap[i].blue,p); } free((char *) colormap); /* Convert raster image to runlength-encoded packets. */ packet_size=1; if (image->colors > 256) packet_size++; if (image->packed_pixels != (unsigned char *) NULL) free((char *) image->packed_pixels); image->packed_pixels=(unsigned char *) malloc(image->packets*packet_size); if (image->packed_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); (void) ReadData((char *) image->packed_pixels,packet_size,image->packets, image->file); status=RunlengthDecodeImage(image); if (status == False) { DestroyImages(image); return((Image *) NULL); } CompressImage(image); CloseImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d M A T T E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadMATTEImage reads an image of raw matte bytes and returns it. % It allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadMATTEImage routine is: % % image=ReadMATTEImage(image_info) % % A description of each parameter follows: % % o image: Function ReadMATTEImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadMATTEImage(const ImageInfo *image_info) { Image *image; int x, x_offset, y, y_offset; register int i; register RunlengthPacket *q; register unsigned char *p; unsigned char *scanline; unsigned int height, packet_size, packets, width; unsigned short index, value; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Determine width and height, e.g. 640x512. */ width=512; height=512; x_offset=0; y_offset=0; if (image_info->size != (char *) NULL) { x=0; (void) XParseGeometry(image_info->size,&x,&y,&width,&height); for (i=0; i < x; i++) (void) fgetc(image->file); } /* Initialize image structure. */ image->matte=True; image->columns=width; image->rows=height; packet_size=image->depth >> 3; scanline=(unsigned char *) malloc(packet_size*image->columns*sizeof(unsigned char)); if (image_info->tile != (char *) NULL) (void) XParseGeometry(image_info->tile,&x_offset,&y_offset,&image->columns, &image->rows); image->packets=0; packets=Max((image->columns*image->rows+2) >> 2,1); image->pixels=(RunlengthPacket *) malloc(packets*sizeof(RunlengthPacket)); if ((scanline == (unsigned char *) NULL) || (image->pixels == (RunlengthPacket *) NULL)) PrematureExit("Unable to allocate memory",image); /* Convert raster image to runlength-encoded packets. */ for (y=0; y < y_offset; y++) (void) ReadData((char *) scanline,packet_size,width,image->file); q=image->pixels; q->length=MaxRunlength; for (y=0; y < image->rows; y++) { (void) ReadData((char *) scanline,packet_size,width,image->file); p=scanline+packet_size*x_offset; for (x=0; x < image->columns; x++) { ReadQuantum(index,p); if ((index == q->index) && ((int) q->length < MaxRunlength)) q->length++; else { if (image->packets != 0) q++; image->packets++; if (image->packets == packets) { packets<<=1; image->pixels=(RunlengthPacket *) realloc((char *) image->pixels, packets*sizeof(RunlengthPacket)); if (image->pixels == (RunlengthPacket *) NULL) { free((char *) scanline); PrematureExit("Unable to allocate memory",image); } q=image->pixels+image->packets-1; } q->red=0; q->green=0; q->blue=0; q->index=index; q->length=0; } } ProgressMonitor(LoadImageText,y,image->rows); } image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket)); free((char *) scanline); CloseImage(image); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d M I F F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadMIFFImage reads a MIFF image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadMIFFImage routine is: % % image=ReadMIFFImage(filename) % % A description of each parameter follows: % % o image: Function ReadMIFFImage returns a pointer to the image after % reading. A null image is returned if there is a a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ static Image *ReadMIFFImage(const ImageInfo *image_info) { char keyword[MaxTextExtent], value[MaxTextExtent]; Image *image; register int c, i; register unsigned char *p; unsigned int length, packet_size, status; unsigned long count, packets; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); image->depth=8; /* Decode image header; header terminates one character beyond a ':'. */ c=fgetc(image->file); if (c == EOF) { DestroyImage(image); return((Image *) NULL); } do { /* Decode image header; header terminates one character beyond a ':'. */ image->compression=NoCompression; while (isgraph(c) && (c != ':')) { register char *p; if (c == '{') { /* Read comment-- any text between { }. */ if (image->comments != (char *) NULL) { length=Extent(image->comments); p=image->comments+length; } else { length=MaxTextExtent; image->comments=(char *) malloc(length*sizeof(char)); p=image->comments; } for ( ; image->comments != (char *) NULL; p++) { c=fgetc(image->file); if ((c == EOF) || (c == '}')) break; if ((p-image->comments+1) >= length) { *p='\0'; length<<=1; image->comments=(char *) realloc((char *) image->comments,length*sizeof(char)); if (image->comments == (char *) NULL) break; p=image->comments+Extent(image->comments); } *p=(unsigned char) c; } if (image->comments == (char *) NULL) PrematureExit("Unable to allocate memory",image); *p='\0'; c=fgetc(image->file); } else if (isalnum(c)) { /* Determine a keyword and its value. */ p=keyword; do { if ((p-keyword) < (MaxTextExtent-1)) *p++=(char) c; c=fgetc(image->file); } while (isalnum(c)); *p='\0'; while (isspace(c) || (c == '=')) c=fgetc(image->file); p=value; if (c != '"') while (!isspace(c) && (c != EOF)) { if ((p-value) < (MaxTextExtent-1)) *p++=(char) c; c=fgetc(image->file); } else { c=fgetc(image->file); while ((c != '"') && (c != EOF)) { if ((p-value) < (MaxTextExtent-1)) *p++=(char) c; c=fgetc(image->file); } } *p='\0'; /* Assign a value to the specified keyword. */ if (strcmp(keyword,"class") == 0) if (strcmp(value,"PseudoClass") == 0) image->class=PseudoClass; else if (strcmp(value,"DirectClass") == 0) image->class=DirectClass; else image->class=UndefinedClass; if (strcmp(keyword,"colors") == 0) image->colors=(unsigned int) atoi(value); if (strcmp(keyword,"compression") == 0) if ((strcmp(value,"Zip") == 0) || (strcmp(value,"Zlib") == 0)) image->compression=ZipCompression; else if (strcmp(value,"RunlengthEncoded") == 0) image->compression=RunlengthEncodedCompression; else image->compression=UndefinedCompression; if (strcmp(keyword,"columns") == 0) image->columns=(unsigned int) atoi(value); if (strcmp(keyword,"delay") == 0) image->delay=atoi(value); if (strcmp(keyword,"depth") == 0) image->depth=atoi(value) <= 8 ? 8 : 16; if (strcmp(keyword,"gamma") == 0) image->gamma=atof(value); if (strcmp(keyword,"id") == 0) if (strcmp(value,"ImageMagick") == 0) image->id=ImageMagickId; else image->id=UndefinedId; if (strcmp(keyword,"label") == 0) { image->label=(char *) malloc(Extent(value)+1*sizeof(char)); if (image->label == (char *) NULL) PrematureExit("Unable to allocate memory",image); (void) strcpy(image->label,value); } if ((strcmp(keyword,"matte") == 0) || (strcmp(keyword,"alpha") == 0)) if ((strcmp(value,"True") == 0) || (strcmp(value,"true") == 0)) image->matte=True; else image->matte=False; if (strcmp(keyword,"montage") == 0) { image->montage=(char *) malloc(Extent(value)+1*sizeof(char)); if (image->montage == (char *) NULL) PrematureExit("Unable to allocate memory",image); (void) strcpy(image->montage,value); } if (strcmp(keyword,"packets") == 0) image->packets=(unsigned int) atoi(value); if (strcmp(keyword,"rows") == 0) image->rows=(unsigned int) atoi(value); if (strcmp(keyword,"scene") == 0) image->scene=(unsigned int) atoi(value); if (strcmp(keyword,"signature") == 0) { image->signature=(char *) malloc((Extent(value)+1)*sizeof(char)); if (image->signature == (char *) NULL) PrematureExit("Unable to allocate memory",image); (void) strcpy(image->signature,value); } } else c=fgetc(image->file); while (isspace(c)) c=fgetc(image->file); } (void) fgetc(image->file); /* Verify that required image information is defined. */ if ((image->id == UndefinedId) || (image->class == UndefinedClass) || (image->compression == UndefinedCompression) || (image->columns == 0) || (image->rows == 0)) PrematureExit("Incorrect image header in file",image); if (image->montage != (char *) NULL) { register char *p; /* Image directory. */ image->directory=(char *) malloc(MaxTextExtent*sizeof(char)); if (image->directory == (char *) NULL) PrematureExit("Unable to read image data",image); p=image->directory; do { *p='\0'; if (((Extent(image->directory)+1) % MaxTextExtent) == 0) { /* Allocate more memory for the image directory. */ image->directory=(char *) realloc((char *) image->directory, (Extent(image->directory)+MaxTextExtent+1)*sizeof(char)); if (image->directory == (char *) NULL) PrematureExit("Unable to read image data",image); p=image->directory+Extent(image->directory); } c=fgetc(image->file); *p++=(unsigned char) c; } while (c != '\0'); } if (image->class == PseudoClass) { unsigned int colors; unsigned short value; /* PseudoClass image cannot have matte data. */ if (image->matte) PrematureExit("Matte images must be DirectClass",image); /* Create image colormap. */ colors=image->colors; if (colors == 0) colors=256; image->colormap=(ColorPacket *) malloc(colors*sizeof(ColorPacket)); if (image->colormap == (ColorPacket *) NULL) PrematureExit("Unable to allocate memory",image); if (image->colors == 0) for (i=0; i < colors; i++) { image->colormap[i].red=(Quantum) UpScale(i); image->colormap[i].green=(Quantum) UpScale(i); image->colormap[i].blue=(Quantum) UpScale(i); image->colors++; } else { unsigned char *colormap; /* Read image colormap from file. */ packet_size=3*(image->depth >> 3); colormap=(unsigned char *) malloc(packet_size*image->colors*sizeof(unsigned char)); if (colormap == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); (void) ReadData((char *) colormap,1,packet_size*image->colors, image->file); p=colormap; for (i=0; i < image->colors; i++) { ReadQuantum(image->colormap[i].red,p); ReadQuantum(image->colormap[i].green,p); ReadQuantum(image->colormap[i].blue,p); } free((char *) colormap); } } /* Determine packed packet size. */ if (image->class == PseudoClass) { image->packet_size=1; if (image->colors > 256) image->packet_size++; } else { image->packet_size=3*(image->depth >> 3); if (image->matte) image->packet_size++; } if (image->compression == RunlengthEncodedCompression) image->packet_size++; packet_size=image->packet_size; if (image->compression == ZipCompression) packet_size=1; /* Allocate image pixels. */ if (image->compression == NoCompression) image->packets=image->columns*image->rows; packets=image->packets; if (image->packets == 0) packets=image->columns*image->rows; image->packed_pixels=(unsigned char *) malloc((unsigned int) packets*packet_size*sizeof(unsigned char)); if (image->packed_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); /* Read image pixels from file. */ if ((image->compression != RunlengthEncodedCompression) || (image->packets != 0)) (void) ReadData((char *) image->packed_pixels,1,(unsigned int) packets*packet_size,image->file); else { /* Number of runlength packets is unspecified. */ count=0; p=image->packed_pixels; do { (void) ReadData((char *) p,1,packet_size,image->file); image->packets++; p+=(packet_size-1); count+=(*p+1); p++; } while (count < (image->columns*image->rows)); } if (image->compression == ZipCompression) { int status; unsigned char *compressed_pixels; /* Uncompress image pixels with Zip encoding. */ compressed_pixels=image->packed_pixels; packets=image->columns*image->rows*image->packet_size; image->packed_pixels=(unsigned char *) malloc((packets+8)*sizeof(unsigned char)); if (image->packed_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); status=True; #ifdef HasPNG status=uncompress(image->packed_pixels,&packets,compressed_pixels, image->packets); #endif image->packets=(unsigned int) (packets/image->packet_size); free((char *) compressed_pixels); if (status) PrematureExit("Unable to Zip uncompress image",image); } /*