/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % EEEEE N N CCCC OOO DDDD EEEEE % % E NN N C O O D D E % % EEE N N N C O O D D EEE % % E N NN C O O D D E % % EEEEE N N CCCC OOO DDDD EEEEE % % % % % % Utility Routines to Write 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 "version.h" #include "Colorlist.h" #include "XWDFile.h" #include "plug-ins.h" /* Define declarations. */ #define SaveImageText " Saving image... " #define PrematureExit(message,image) \ { \ Warning(message,image->filename); \ return(False); \ } /* Function prototypes. */ static unsigned int WriteMIFFImage(const ImageInfo *,Image *), WritePNMImage(const ImageInfo *,Image *), WriteYUVImage(const ImageInfo *,Image *); /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e A V S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteAVSImage writes an image to a file in AVS X image format. % % The format of the WriteAVSImage routine is: % % status=WriteAVSImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteAVSImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteAVSImage(const ImageInfo *image_info,Image *image) { register int i, j; register RunlengthPacket *p; unsigned int scene; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); scene=0; do { /* Initialize raster file header. */ MSBFirstWriteLong(image->columns,image->file); MSBFirstWriteLong(image->rows,image->file); p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { (void) fputc(image->matte ? DownScale(p->index) : Opaque,image->file); (void) fputc(DownScale(p->red),image->file); (void) fputc(DownScale(p->green),image->file); (void) fputc(DownScale(p->blue),image->file); } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e B M P I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteBMPImage writes an image in Microsoft Windows bitmap encoded % image format. % % The format of the WriteBMPImage routine is: % % status=WriteBMPImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteBMPImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteBMPImage(const ImageInfo *image_info,Image *image) { 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; register int i, j, x, y; register RunlengthPacket *p; register unsigned char *q; unsigned char *bmp_data, *bmp_pixels; unsigned int bytes_per_line, scene; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); scene=0; do { /* Initialize BMP raster file header. */ bmp_header.file_size=14+40; bmp_header.offset_bits=14+40; if (!IsPseudoClass(image) && !IsGrayImage(image)) { /* Full color BMP raster. */ bmp_header.number_colors=0; bmp_header.bit_count=24; bytes_per_line=((image->columns*bmp_header.bit_count+31)/32)*4; } else { /* Colormapped BMP raster. */ bmp_header.bit_count=8; bytes_per_line=((image->columns*bmp_header.bit_count+31)/32)*4; image->compression=image_info->compression; if (image->compression == RunlengthEncodedCompression) bytes_per_line=image->columns; if (IsMonochromeImage(image)) { bmp_header.bit_count=1; bytes_per_line=((image->columns*bmp_header.bit_count+31)/32)*4; } bmp_header.file_size+=4*(1 << bmp_header.bit_count); bmp_header.offset_bits+=4*(1 << bmp_header.bit_count); bmp_header.number_colors=1 << bmp_header.bit_count; } bmp_header.reserved[0]=0; bmp_header.reserved[1]=0; bmp_header.size=40; bmp_header.width=image->columns; bmp_header.height=image->rows; bmp_header.planes=1; bmp_header.compression=0; bmp_header.image_size=bytes_per_line*image->rows; bmp_header.file_size+=bmp_header.image_size; bmp_header.x_pixels=75*39; bmp_header.y_pixels=75*39; if (image->units == PixelsPerInchResolution) { bmp_header.x_pixels=(unsigned long) (100.0*image->x_resolution/2.54); bmp_header.y_pixels=(unsigned long) (100.0*image->y_resolution/2.54); } if (image->units == PixelsPerCentimeterResolution) { bmp_header.x_pixels=(unsigned long) (100.0*image->x_resolution); bmp_header.y_pixels=(unsigned long) (100.0*image->y_resolution); } bmp_header.colors_important=bmp_header.number_colors; /* Convert MIFF to BMP raster pixels. */ bmp_pixels=(unsigned char *) malloc(bmp_header.image_size*sizeof(unsigned char)); if (bmp_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); x=0; y=image->rows-1; switch (bmp_header.bit_count) { case 1: { register unsigned char bit, byte, polarity; /* Convert PseudoClass image to a BMP monochrome image. */ p=image->pixels; polarity=0; if (image->colors == 2) polarity= Intensity(image->colormap[1]) > Intensity(image->colormap[0]); bit=0; byte=0; q=bmp_pixels+y*bytes_per_line; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { byte<<=1; if (p->index == polarity) byte|=0x01; bit++; if (bit == 8) { *q++=byte; bit=0; byte=0; } x++; if (x == image->columns) { /* Advance to the next scanline. */ if (bit != 0) *q++=byte << (8-bit); bit=0; byte=0; x=0; y--; q=bmp_pixels+y*bytes_per_line; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case 8: { /* Convert PseudoClass packet to BMP pixel. */ p=image->pixels; q=bmp_pixels+y*bytes_per_line; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q++=p->index; x++; if (x == image->columns) { x=0; y--; q=bmp_pixels+y*bytes_per_line; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case 24: { /* Convert DirectClass packet to BMP RGB pixel. */ p=image->pixels; q=bmp_pixels+y*bytes_per_line-1; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q++=DownScale(p->blue); *q++=DownScale(p->green); *q++=DownScale(p->red); x++; if (x == image->columns) { x=0; y--; q=bmp_pixels+y*bytes_per_line; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } } if (bmp_header.bit_count == 8) if (image->compression == RunlengthEncodedCompression) { unsigned int packets; /* Convert run-length encoded raster pixels. */ packets=(unsigned int) ((bytes_per_line*(bmp_header.height+2)+1) << 1); bmp_data=(unsigned char *) malloc(packets*sizeof(unsigned char)); if (bmp_pixels == (unsigned char *) NULL) { Warning("Memory allocation error",(char *) NULL); free((char *) bmp_pixels); return(False); } bmp_header.image_size= BMPEncodeImage(bmp_pixels,bmp_data,image->columns,image->rows); free((char *) bmp_pixels); bmp_pixels=bmp_data; bmp_header.compression=1; } /* Write BMP header. */ (void) fwrite("BM",1,2,image->file); LSBFirstWriteLong(bmp_header.file_size,image->file); LSBFirstWriteShort(bmp_header.reserved[0],image->file); LSBFirstWriteShort(bmp_header.reserved[1],image->file); LSBFirstWriteLong(bmp_header.offset_bits,image->file); LSBFirstWriteLong(bmp_header.size,image->file); LSBFirstWriteLong(bmp_header.width,image->file); LSBFirstWriteLong(bmp_header.height,image->file); LSBFirstWriteShort(bmp_header.planes,image->file); LSBFirstWriteShort(bmp_header.bit_count,image->file); LSBFirstWriteLong(bmp_header.compression,image->file); LSBFirstWriteLong(bmp_header.image_size,image->file); LSBFirstWriteLong(bmp_header.x_pixels,image->file); LSBFirstWriteLong(bmp_header.y_pixels,image->file); LSBFirstWriteLong(bmp_header.number_colors,image->file); LSBFirstWriteLong(bmp_header.colors_important,image->file); if (image->class == PseudoClass) { unsigned char *bmp_colormap; /* Dump colormap to file. */ bmp_colormap=(unsigned char *) malloc(4*(1 << bmp_header.bit_count)*sizeof(unsigned char)); if (bmp_colormap == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); q=bmp_colormap; for (i=0; i < image->colors; i++) { *q++=DownScale(image->colormap[i].blue); *q++=DownScale(image->colormap[i].green); *q++=DownScale(image->colormap[i].red); q++; } for ( ; i < (int) (1 << bmp_header.bit_count); i++) { *q++=0; *q++=0; *q++=0; q++; } (void) fwrite((char *) bmp_colormap,4,1 << bmp_header.bit_count, image->file); free((char *) bmp_colormap); } (void) fwrite((char *) bmp_pixels,1,(int) bmp_header.image_size, image->file); free((char *) bmp_pixels); if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e C G M I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteCGMImage writes an image in the CGM encoded image format. % % The format of the WriteCGMImage routine is: % % status=WriteCGMImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteCGMImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteCGMImage(const ImageInfo *image_info, Image *image) { unsigned int status; Warning("Cannot write CGM images",image->filename); status=WriteMIFFImage(image_info,image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e C M Y K I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteCMYKImage writes an image to a file in cyan, magenta, % yellow, and black rasterfile format. % % The format of the WriteCMYKImage routine is: % % status=WriteCMYKImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteCMYKImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteCMYKImage(const ImageInfo *image_info,Image *image) { float black_generation, undercolor; int black, cyan, magenta, yellow; register int i, j; register RunlengthPacket *p; unsigned int scene; image->depth=QuantumDepth; if (image_info->interlace != PartitionInterlace) { /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } /* Convert MIFF to CMYK raster pixels. */ undercolor=1.0; black_generation=1.0; if (image_info->undercolor != (char *) NULL) { (void) sscanf(image_info->undercolor,"%fx%f",&undercolor, &black_generation); if (black_generation == 1.0) black_generation=undercolor; } scene=0; do { switch (image_info->interlace) { case NoneInterlace: default: { /* No interlacing: CMYKCMYKCMYKCMYKCMYKCMYK... */ p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (cyan-undercolor*black)); WriteQuantumFile((unsigned int) (magenta-undercolor*black)); WriteQuantumFile((unsigned int) (yellow-undercolor*black)); WriteQuantumFile((unsigned int) (black_generation*black)); } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case LineInterlace: { register int x, y; /* Line interlacing: CCC...MMM...YYY...CCC...MMM...YYY... */ if (!UncompressImage(image)) return(False); for (y=0; y < image->rows; y++) { p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (cyan-undercolor*black)); p++; } p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (magenta-undercolor*black)); p++; } p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (yellow-undercolor*black)); p++; } p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (black_generation*black)); p++; } ProgressMonitor(SaveImageText,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,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (cyan-undercolor*black)); } p++; } if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("M",image->filename); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } ProgressMonitor(SaveImageText,100,400); p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (magenta-undercolor*black)); } p++; } if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("Y",image->filename); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } ProgressMonitor(SaveImageText,200,400); p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (yellow-undercolor*black)); } p++; } if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("K",image->filename); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } ProgressMonitor(SaveImageText,300,400); p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { cyan=MaxRGB-p->red; magenta=MaxRGB-p->green; yellow=MaxRGB-p->blue; black=cyan; if (magenta < black) black=magenta; if (yellow < black) black=yellow; WriteQuantumFile((unsigned int) (black_generation*black)); } p++; } if (image_info->interlace == PartitionInterlace) (void) strcpy(image->filename,image_info->filename); ProgressMonitor(SaveImageText,400,400); break; } } if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e F A X I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure WriteFAXImage writes an image to a file in 1 dimensional Huffman % encoded format. % % The format of the WriteFAXImage routine is: % % status=WriteFAXImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteFAXImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteFAXImage(const ImageInfo *image_info,Image *image) { unsigned int scene, status; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); scene=0; do { /* Convert MIFF to monochrome. */ if (!IsMonochromeImage(image)) { QuantizeInfo quantize_info; GetQuantizeInfo(&quantize_info); quantize_info.number_colors=2; quantize_info.dither=image_info->dither; quantize_info.colorspace=GRAYColorspace; QuantizeImage(&quantize_info,image); SyncImage(image); } status=HuffmanEncodeImage(image_info,image); if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); CloseImage(image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e F I T S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteFITSImage writes a Flexible Image Transport System image to a % file as gray scale intensities [0..255]. % % The format of the WriteFITSImage routine is: % % status=WriteFITSImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteFITSImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteFITSImage(const ImageInfo *image_info,Image *image) { char buffer[81], *fits_header; register int i, j; register RunlengthPacket *p; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Allocate image header. */ fits_header=(char *) malloc(2880*sizeof(unsigned char)); if (fits_header == (char *) NULL) PrematureExit("Unable to allocate memory",image); /* Initialize image header. */ for (i=0; i < 2880; i++) fits_header[i]=' '; (void) strcpy(buffer,"SIMPLE = T"); (void) strncpy(fits_header+0,buffer,Extent(buffer)); (void) strcpy(buffer,"BITPIX = 8"); (void) strncpy(fits_header+80,buffer,Extent(buffer)); (void) strcpy(buffer,"NAXIS = 2"); (void) strncpy(fits_header+160,buffer,Extent(buffer)); (void) sprintf(buffer,"NAXIS1 = %10u",image->columns); (void) strncpy(fits_header+240,buffer,Extent(buffer)); (void) sprintf(buffer,"NAXIS2 = %10u",image->rows); (void) strncpy(fits_header+320,buffer,Extent(buffer)); (void) strcpy(buffer,"HISTORY Created by ImageMagick."); (void) strncpy(fits_header+400,buffer,Extent(buffer)); (void) strcpy(buffer,"END"); (void) strncpy(fits_header+480,buffer,Extent(buffer)); (void) fwrite((char *) fits_header,1,2880,image->file); free((char *) fits_header); /* Convert image to fits scale PseudoColor class. */ p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) (void) fputc(DownScale(Intensity(*p)),image->file); p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e G I F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteGIFImage writes an image to a file in the Compuserve Graphics % image format. % % The format of the WriteGIFImage routine is: % % status=WriteGIFImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteGIFImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteGIFImage(const ImageInfo *image_info,Image *image) { ColorPacket transparent_pixel; Image *next_image; RectangleInfo page_info; register int i, x; register RunlengthPacket *p; register unsigned char *q; unsigned char bits_per_pixel, c, *colormap; unsigned int colors, global_colormap, height, interlace, scene, status, width; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Allocate colormap. */ colormap=(unsigned char *) malloc(3*256*sizeof(unsigned char)); if (colormap == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); /* Write GIF header. */ if ((image->comments == (char *) NULL) && !image_info->adjoin && !image->matte) (void) fwrite("GIF87a",1,6,image->file); else if (strcmp(image_info->magick,"GIF87") == 0) (void) fwrite("GIF87a",1,6,image->file); else (void) fwrite("GIF89a",1,6,image->file); /* Determine image bounding box and global colormap status. */ page_info.x=0; page_info.y=0; page_info.width=image->columns; page_info.height=image->rows; global_colormap=image->class == PseudoClass; next_image=image; for ( ; next_image != (Image *) NULL; next_image=next_image->next) { width=next_image->columns; height=next_image->rows; if (next_image->page != (char *) NULL) (void) XParseGeometry(next_image->page,&page_info.x,&page_info.y,&width, &height); if ((width+page_info.x) > page_info.width); page_info.width=width+page_info.y; if ((height+page_info.y) > page_info.height); page_info.height=height+page_info.y; if (!global_colormap) continue; if ((next_image->class == DirectClass) || (next_image->colors != image->colors)) { global_colormap=False; continue; } for (i=0; i < image->colors; i++) if (!ColorMatch(next_image->colormap[i],image->colormap[i],0)) { global_colormap=False; break; } } if (image_info->page != (char *) NULL) (void) XParseGeometry(image_info->page,&page_info.x,&page_info.y, &page_info.width,&page_info.height); LSBFirstWriteShort(page_info.width,image->file); LSBFirstWriteShort(page_info.height,image->file); /* Write images to file. */ interlace=image_info->interlace; if (image_info->adjoin && (image->next != (Image *) NULL)) interlace=NoneInterlace; scene=0; do { transparent_pixel.flags=False; if (IsPseudoClass(image)) colors=image->colors; else { QuantizeInfo quantize_info; unsigned char *matte_image; matte_image=(unsigned char *) NULL; if (image->matte) { /* Track all the transparent pixels. */ if (!UncompressImage(image)) return(False); matte_image=(unsigned char *) malloc(image->packets*sizeof(unsigned char)); if (matte_image == (unsigned char *) NULL) { Warning("Memory allocation error",image->filename); return(False); } p=image->pixels; for (i=0; i < image->packets; i++) { matte_image[i]=p->index == Transparent; if (p->index == Transparent) { transparent_pixel.red=p->red; transparent_pixel.green=p->green; transparent_pixel.blue=p->blue; transparent_pixel.flags=True; } p++; } } colors=transparent_pixel.flags ? 255 : 256; GetQuantizeInfo(&quantize_info); quantize_info.number_colors=colors; quantize_info.dither=image_info->dither; QuantizeImage(&quantize_info,image); SyncImage(image); CompressColormap(image); colors=image->colors; if (transparent_pixel.flags) { /* Set the transparent pixel index. */ image->class=DirectClass; if (!UncompressImage(image)) return(False); p=image->pixels; for (i=0; i < image->packets; i++) { if (matte_image[i]) p->index=image->colors; p++; } colors++; } if (matte_image != (unsigned char *) NULL) free((char *) matte_image); } for (bits_per_pixel=1; bits_per_pixel < 8; bits_per_pixel++) if ((1 << bits_per_pixel) >= colors) break; q=colormap; for (i=0; i < image->colors; i++) { *q++=DownScale(image->colormap[i].red); *q++=DownScale(image->colormap[i].green); *q++=DownScale(image->colormap[i].blue); } if (transparent_pixel.flags) { *q++=DownScale(transparent_pixel.red); *q++=DownScale(transparent_pixel.green); *q++=DownScale(transparent_pixel.blue); i++; } for ( ; i < (int) (1 << bits_per_pixel); i++) { *q++=0x0; *q++=0x0; *q++=0x0; } if (!image_info->adjoin || (image->previous == (Image *) NULL)) { register int j; /* Write global colormap. */ c=0x80; c|=(8-1) << 4; /* color resolution */ c|=(bits_per_pixel-1); /* size of global colormap */ (void) fputc((char) c,image->file); for (j=0; j < image->colors; j++) if (ColorMatch(image->background_color,image->colormap[j],0)) break; (void) fputc(j,image->file); /* background color */ (void) fputc(0x0,image->file); /* reserved */ (void) fwrite(colormap,1,3*(1 << bits_per_pixel),image->file); } if (strcmp(image_info->magick,"GIF87") != 0) { /* Write Graphics Control extension. */ (void) fputc(0x21,image->file); (void) fputc(0xf9,image->file); (void) fputc(0x04,image->file); c=image->dispose << 2; if (transparent_pixel.flags) c|=0x01; (void) fputc(c,image->file); LSBFirstWriteShort(image->delay,image->file); (void) fputc((char) image->colors,image->file); (void) fputc(0x00,image->file); if (image->comments != (char *) NULL) { register char *p; register unsigned int count; /* Write Comment extension. */ (void) fputc(0x21,image->file); (void) fputc(0xfe,image->file); p=image->comments; while (Extent(p) > 0) { count=Min(Extent(p),255); (void) fputc(count,image->file); for (i=0; i < count; i++) (void) fputc(*p++,image->file); } (void) fputc(0x0,image->file); } if ((image->previous == (Image *) NULL) && (image->next != (Image *) NULL) && (image->iterations != 1)) { /* Write Netscape Loop extension. */ (void) fputc(0x21,image->file); (void) fputc(0xff,image->file); (void) fputc(0x0b,image->file); (void) fwrite("NETSCAPE2.0",1,11,image->file); (void) fputc(0x03,image->file); (void) fputc(0x01,image->file); LSBFirstWriteShort(image->iterations,image->file); (void) fputc(0x00,image->file); } } (void) fputc(',',image->file); /* image separator */ /* Write the image header. */ if (image->page != (char *) NULL) (void) XParseGeometry(image->page,&page_info.x,&page_info.y, &page_info.width,&page_info.height); LSBFirstWriteShort(page_info.x,image->file); LSBFirstWriteShort(page_info.y,image->file); LSBFirstWriteShort(image->columns,image->file); LSBFirstWriteShort(image->rows,image->file); c=0x00; if (interlace != NoneInterlace) c|=0x40; /* pixel data is interlaced */ if (global_colormap) (void) fputc((char) c,image->file); else { c|=0x80; c|=(bits_per_pixel-1); /* size of local colormap */ (void) fputc((char) c,image->file); (void) fwrite(colormap,1,3*(1 << bits_per_pixel),image->file); } /* Write the image data. */ c=Max(bits_per_pixel,2); (void) fputc((char) c,image->file); if (interlace == NoneInterlace) status=GIFEncodeImage(image,Max(bits_per_pixel,2)+1); else { Image *interlaced_image; int pass, y; register RunlengthPacket *q; static int interlace_rate[4] = { 8, 8, 4, 2 }, interlace_start[4] = { 0, 4, 2, 1 }; /* Interlace image. */ if (!UncompressImage(image)) return(False); image->orphan=True; interlaced_image=CloneImage(image,image->columns,image->rows,False); image->orphan=False; if (interlaced_image == (Image *) NULL) PrematureExit("Unable to allocate memory",image); p=image->pixels; q=interlaced_image->pixels; for (pass=0; pass < 4; pass++) { y=interlace_start[pass]; while (y < image->rows) { p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { *q=(*p); p++; q++; } y+=interlace_rate[pass]; } } interlaced_image->file=image->file; status=GIFEncodeImage(interlaced_image,Max(bits_per_pixel,2)+1); interlaced_image->file=(FILE *) NULL; DestroyImage(interlaced_image); } if (status == False) PrematureExit("Unable to allocate memory",image); (void) fputc(0x0,image->file); if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); (void) fputc(';',image->file); /* terminator */ free((char *) colormap); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e G R A D A T I O N I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteGRADATIONImage writes an image in the gradation image format. % % The format of the WriteGRADATIONImage routine is: % % status=WriteGRADATIONImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteGRADATIONImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteGRADATIONImage(const ImageInfo *image_info, Image *image) { unsigned int status; Warning("Cannot write GRADATION images",image->filename); status=WriteMIFFImage(image_info,image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e G R A Y I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteGRAYImage writes an image to a file as gray scale intensity % values. % % The format of the WriteGRAYImage routine is: % % status=WriteGRAYImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteGRAYImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteGRAYImage(const ImageInfo *image_info,Image *image) { register int i, j; register RunlengthPacket *p; unsigned int scene; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Convert image to gray scale PseudoColor class. */ image->depth=QuantumDepth; scene=0; do { p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) WriteQuantumFile(Intensity(*p)); p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e H D F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteHDFImage writes an image in the Hierarchial Data Format image % format. % % The format of the WriteHDFImage routine is: % % status=WriteHDFImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteHDFImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ #ifdef HasHDF static unsigned int WriteHDFImage(const ImageInfo *image_info,Image *image) { #include "hdf.h" #undef BSD #undef LOCAL int status; register int i, j; register RunlengthPacket *p; register unsigned char *q; uint16 reference; unsigned char *hdf_pixels; unsigned int compression, packet_size, scene; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); CloseImage(image); scene=0; do { /* Initialize raster file header. */ packet_size=1; if (image->class == DirectClass) packet_size=3; hdf_pixels=(unsigned char *) malloc(packet_size*image->columns*image->rows*sizeof(unsigned char)); if (hdf_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); p=image->pixels; if (!IsPseudoClass(image) && !IsGrayImage(image)) { /* Convert DirectClass packet to HDF pixels. */ q=hdf_pixels; switch (image_info->interlace) { case NoneInterlace: default: { /* No interlacing: RGBRGBRGBRGBRGBRGB... */ DF24setil(DFIL_PIXEL); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q++=DownScale(p->red); *q++=DownScale(p->green); *q++=DownScale(p->blue); } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case LineInterlace: { register int x, y; /* Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB... */ if (!UncompressImage(image)) return(False); DF24setil(DFIL_LINE); for (y=0; y < image->rows; y++) { p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { *q++=DownScale(p->red); p++; } p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { *q++=DownScale(p->green); p++; } p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { *q++=DownScale(p->blue); p++; } ProgressMonitor(SaveImageText,y,image->rows); } break; } case PlaneInterlace: case PartitionInterlace: { /* Plane interlacing: RRRRRR...GGGGGG...BBBBBB... */ DF24setil(DFIL_PLANE); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=DownScale(p->red); p++; } ProgressMonitor(SaveImageText,100,400); p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=DownScale(p->green); p++; } ProgressMonitor(SaveImageText,250,400); p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=DownScale(p->blue); p++; } ProgressMonitor(SaveImageText,400,400); break; } } if (scene == 0) status=DF24putimage(image->filename,(void *) hdf_pixels, image->columns,image->rows); else status=DF24addimage(image->filename,(void *) hdf_pixels, image->columns,image->rows); reference=DF24lastref(); } else { /* Convert PseudoClass packet to HDF pixels. */ q=hdf_pixels; if (IsGrayImage(image)) for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=DownScale(p->red); p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } else { unsigned char *hdf_palette; hdf_palette=(unsigned char *) malloc(768*sizeof(unsigned char)); if (hdf_palette == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); q=hdf_palette; for (i=0; i < image->colors; i++) { *q++=DownScale(image->colormap[i].red); *q++=DownScale(image->colormap[i].green); *q++=DownScale(image->colormap[i].blue); } (void) DFR8setpalette(hdf_palette); free(hdf_palette); q=hdf_pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=p->index; p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } compression=image_info->compression == NoCompression ? 0 : DFTAG_RLE; if (scene == 0) status=DFR8putimage(image->filename,(void *) hdf_pixels, image->columns,image->rows,compression); else status=DFR8addimage(image->filename,(void *) hdf_pixels, image->columns,image->rows,compression); reference=DFR8lastref(); } if (image->label != (char *) NULL) (void) DFANputlabel(image->filename,DFTAG_RIG,reference,image->label); if (image->comments != (char *) NULL) (void) DFANputdesc(image->filename,DFTAG_RIG,reference,image->comments, Extent(image->comments)+1); free(hdf_pixels); if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); return(status != -1); } #else static unsigned int WriteHDFImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("HDF library is not available",image->filename); status=WriteMIFFImage(image_info,image); return(status); } #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e H I S T O G R A M I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteHISTOGRAMImage writes an image to a file in HISTOGRAM format. % The image shows a histogram of the color (or gray) values in the image. The % image consists of three overlaid histograms: a red one for the red channel, % a green one for the green channel, and a blue one for the blue channel. The % image comment contains a list of unique pixel values and the number of times % each occurs in the image. % % This routine is strongly based on a similiar one written by % muquit@warm.semcor.com which in turn is based on ppmhistmap of netpbm. % % The format of the WriteHISTOGRAMImage routine is: % % status=WriteHISTOGRAMImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteHISTOGRAMImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteHISTOGRAMImage(const ImageInfo *image_info, Image *image) { #define HistogramDensity "256x200" char filename[MaxTextExtent]; double scale; FILE *file; Image *histogram_image; int *blue, *green, maximum, *red, sans_offset; register RunlengthPacket *p, *q; register int i, j; unsigned int height, status, width; /* Allocate histogram image. */ (void) XParseGeometry(HistogramDensity,&sans_offset,&sans_offset, &width,&height); if (image_info->density != (char *) NULL) (void) XParseGeometry(image_info->density,&sans_offset,&sans_offset, &width,&height); image->orphan=True; histogram_image=CloneImage(image,width,height,False); image->orphan=False; if (histogram_image == (Image *) NULL) PrematureExit("Unable to allocate memory",image); histogram_image->class=DirectClass; /* Allocate histogram count arrays. */ red=(int *) malloc (histogram_image->columns*sizeof(int)); green=(int *) malloc (histogram_image->columns*sizeof(int)); blue=(int *) malloc (histogram_image->columns*sizeof(int)); if ((red == (int *) NULL) || (green == (int *) NULL) || (blue == (int *) NULL)) { DestroyImage(histogram_image); PrematureExit("Unable to allocate memory",image); } /* Initialize histogram count arrays. */ for (i=0; i < histogram_image->columns; i++) { red[i]=0; green[i]=0; blue[i]=0; } p=image->pixels; for (i=0; i < image->packets; i++) { red[DownScale(p->red)]+=(p->length+1); green[DownScale(p->green)]+=(p->length+1); blue[DownScale(p->blue)]+=(p->length+1); p++; } maximum=0; for (i=0; i < histogram_image->columns; i++) { if (maximum < red[i]) maximum=red[i]; if (maximum < green[i]) maximum=green[i]; if (maximum < blue[i]) maximum=blue[i]; } for (i=0; i < histogram_image->columns; i++) { if (red[i] > maximum) red[i]=maximum; if (green[i] > maximum) green[i]=maximum; if (blue[i] > maximum) blue[i]=maximum; } /* Initialize histogram image. */ q=histogram_image->pixels; for (i=0; i < histogram_image->packets; i++) { q->red=0; q->green=0; q->blue=0; q->index=0; q->length=0; q++; } scale=(double) histogram_image->rows/maximum; q=histogram_image->pixels; for (i=0; i < histogram_image->columns; i++) { j=histogram_image->rows-(int) (scale*red[i]); while (j < histogram_image->rows) { q=histogram_image->pixels+(j*histogram_image->columns+i); q->red=MaxRGB; j++; } j=histogram_image->rows-(int) (scale*green[i]); while (j < histogram_image->rows) { q=histogram_image->pixels+(j*histogram_image->columns+i); q->green=MaxRGB; j++; } j=histogram_image->rows-(int) (scale*blue[i]); while (j < histogram_image->rows) { q=histogram_image->pixels+(j*histogram_image->columns+i); q->blue=MaxRGB; j++; } ProgressMonitor(SaveImageText,i,histogram_image->columns); } free ((char *) blue); free ((char *) green); free ((char *) red); TemporaryFilename(filename); file=fopen(filename,WriteBinaryType); if (file != (FILE *) NULL) { char command[MaxTextExtent]; /* Add a histogram as an image comment. */ (void) fprintf(file,"%s\n",image->comments); NumberColors(image,file); (void) fclose(file); (void) sprintf(command,"@%s",filename); CommentImage(histogram_image,command); (void) remove(filename); } /* Write HISTOGRAM image as MIFF. */ status=WriteMIFFImage(image_info,histogram_image); DestroyImage(histogram_image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e H T M L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteHTMLImage writes an image in the HTML encoded image format. % % The format of the WriteHTMLImage routine is: % % status=WriteHTMLImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteHTMLImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteHTMLImage(const ImageInfo *image_info,Image *image) { char filename[MaxTextExtent], mapname[MaxTextExtent], url[MaxTextExtent]; int x, y; register char *p; unsigned int height, status, width; *url='\0'; if ((strcmp(image_info->magick,"FTP") == 0) || (strcmp(image_info->magick,"HTTP") == 0)) { /* Extract URL base from filename. */ p=strrchr(image->filename,'/'); if (p) { p++; (void) strcpy(url,image_info->magick); (void) strcat(url,":"); url[Extent(url)+p-image->filename]='\0'; (void) strncat(url,image->filename,p-image->filename); (void) strcpy(image->filename,p); } } /* Refer to image map file. */ (void) strcpy(filename,image->filename); AppendImageFormat("map",filename); p=filename+Extent(filename)-1; while ((p > filename) && (*(p-1) != *BasenameSeparator)) p--; (void) strcpy(mapname,p); for (p=mapname+Extent(mapname)-1; p > mapname; p--) if (*p == '.') { *p='\0'; break; } (void) strcpy(filename,image->filename); status=True; if (strcmp(image_info->magick,"SHTML") != 0) { /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Write the HTML image file. */ if (*image->magick_filename != '\0') (void) strcpy(image->filename,image->magick_filename); (void) fprintf(image->file,"\n"); (void) fprintf(image->file,"\n"); (void) fprintf(image->file,"%s\n",image->filename); (void) fprintf(image->file,"\n"); (void) fprintf(image->file,"\n"); (void) fprintf(image->file,"
\n"); (void) fprintf(image->file,"

%s

\n",image->filename); (void) fprintf(image->file,"

\n"); (void) strcpy(filename,image->filename); AppendImageFormat("gif",filename); (void) fprintf(image->file,"\n", mapname,filename); /* Determine the size and location of each image tile. */ x=0; y=0; width=image->columns; height=image->rows; if (image->montage != (char *) NULL) (void) XParseGeometry(image->montage,&x,&y,&width,&height); /* Write an image map. */ (void) fprintf(image->file,"\n",mapname); (void) fprintf(image->file," directory == (char *) NULL) (void) fprintf(image->file,"%s shape=rect coords=0,0,%u,%u>\n", image->filename,width-1,height-1); else for (p=image->directory; *p != '\0'; p++) if (*p != '\n') (void) fputc(*p,image->file); else { (void) fprintf(image->file," shape=rect coords=%d,%d,%d,%d>\n", x,y,x+(int) width-1,y+(int) height-1); if (*(p+1) != '\0') (void) fprintf(image->file," = image->columns) { x=0; y+=height; } } (void) fprintf(image->file,"\n"); if (image->montage != (char *) NULL) { char color[MaxTextExtent]; /* Back montage background transparent. */ (void) sprintf(color,"#%02x%02x%02x", (unsigned int) image->pixels[0].red, (unsigned int) image->pixels[0].green, (unsigned int) image->pixels[0].blue); TransparentImage(image,color); } (void) strcpy(filename,image->filename); (void) fprintf(image->file,"
\n"); (void) fprintf(image->file,"\n"); status=fprintf(image->file,"\n"); CloseImage(image); if (strcmp(image_info->magick,"GIF") != 0) { /* Write the image as transparent GIF. */ (void) strcpy(image->filename,filename); AppendImageFormat("gif",image->filename); status|=WriteGIFImage(image_info,image); } /* Determine image map filename. */ (void) strcpy(image->filename,filename); for (p=filename+Extent(filename)-1; p > filename; p--) if (*p == '.') { (void) strncpy(image->filename,filename,p-filename); image->filename[p-filename]='\0'; break; } (void) strcat(image->filename,"_map.shtml"); } /* Open image map. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Determine the size and location of each image tile. */ x=0; y=0; width=image->columns; height=image->rows; if (image->montage != (char *) NULL) (void) XParseGeometry(image->montage,&x,&y,&width,&height); /* Write an image map. */ (void) fprintf(image->file,"\n",mapname); (void) fprintf(image->file," directory == (char *) NULL) (void) fprintf(image->file,"%s shape=rect coords=0,0,%u,%u>\n", image->filename,width-1,height-1); else for (p=image->directory; *p != '\0'; p++) if (*p != '\n') (void) fputc(*p,image->file); else { (void) fprintf(image->file," shape=rect coords=%d,%d,%d,%d>\n",x,y, x+(int) width-1,y+(int) height-1); if (*(p+1) != '\0') (void) fprintf(image->file," = image->columns) { x=0; y+=height; } } (void) fprintf(image->file,"\n"); CloseImage(image); (void) strcpy(image->filename,filename); return(status); } #ifdef HasJBIG /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e J B I G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteJBIGImage writes an image in the JBIG encoded image format. % % The format of the WriteJBIGImage routine is: % % status=WriteJBIGImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteJBIGImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static void JBIGEncode(unsigned char *start,size_t length,void *file) { (void) fwrite(start,length,1,(FILE *) file); return; } static unsigned int WriteJBIGImage(const ImageInfo *image_info,Image *image) { int sans_offset; register int i, j; register RunlengthPacket *p; register unsigned char bit, *q; struct jbg_enc_state jbig_info; unsigned char *pixels, polarity; unsigned int byte, number_packets, scene, x, x_resolution, y_resolution; /* Open image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); scene=0; do { /* Allocate pixel data. */ number_packets=((image->columns+7) >> 3)*image->rows; pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char)); if (pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); /* Convert Runlength encoded pixels to a bitmap. */ if (!IsMonochromeImage(image)) { QuantizeInfo quantize_info; GetQuantizeInfo(&quantize_info); quantize_info.number_colors=2; quantize_info.dither=image_info->dither; quantize_info.colorspace=GRAYColorspace; QuantizeImage(&quantize_info,image); SyncImage(image); } polarity=0; if (image->colors == 2) polarity=Intensity(image->colormap[0]) > Intensity(image->colormap[1]); bit=0; byte=0; x=0; p=image->pixels; q=pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { byte<<=1; if (p->index == polarity) byte|=0x01; bit++; if (bit == 8) { *q++=byte; bit=0; byte=0; } x++; if (x == image->columns) { /* Advance to the next scanline. */ if (bit != 0) *q++=byte << (8-bit); bit=0; byte=0; x=0; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } /* Initialize JBIG info structure. */ jbg_enc_init(&jbig_info,image->columns,image->rows,1,&pixels, (void (*)(unsigned char *,size_t,void *)) JBIGEncode,image->file); x_resolution=640; y_resolution=480; (void) XParseGeometry(image_info->density,&sans_offset,&sans_offset, &x_resolution,&y_resolution); if (image_info->subimage != 0) jbg_enc_layers(&jbig_info,image_info->subimage); else jbg_enc_lrlmax(&jbig_info,x_resolution,y_resolution); jbg_enc_lrange(&jbig_info,-1,-1); jbg_enc_options(&jbig_info,JBG_ILEAVE | JBG_SMID,JBG_TPDON | JBG_TPBON | JBG_DPON,-1,-1,-1); /* Write JBIG image. */ jbg_enc_out(&jbig_info); jbg_enc_free(&jbig_info); free((char *) pixels); if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); CloseImage(image); return(True); } #else static unsigned int WriteJBIGImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("JBIG library is not available",image->filename); status=WriteMIFFImage(image_info,image); return(status); } #endif #ifdef HasJPEG static Image *image; /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e J P E G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteJPEGImage writes 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 WriteJPEGImage routine is: % % status=WriteJPEGImage(image_info,image) % % A description of each parameter follows: % % o status: Function WriteJPEGImage return True if the image is written. % False is returned is there is of a memory shortage or if the image % file cannot be opened for writing. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o jpeg_image: A pointer to a Image structure. % % */ 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 unsigned int WriteJPEGImage(const ImageInfo *image_info,Image *image) { JSAMPLE *jpeg_pixels; JSAMPROW scanline[1]; register int i, j, x; register JSAMPLE *q; register RunlengthPacket *p; struct jpeg_compress_struct jpeg_info; struct jpeg_error_mgr jpeg_error; unsigned int packets; /* Open image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Initialize JPEG parameters. */ jpeg_info.err=jpeg_std_error(&jpeg_error); jpeg_info.err->emit_message=EmitMessage; jpeg_create_compress(&jpeg_info); jpeg_stdio_dest(&jpeg_info,image->file); jpeg_info.image_width=image->columns; jpeg_info.image_height=image->rows; jpeg_info.input_components=3; jpeg_info.in_color_space=JCS_RGB; if (IsGrayImage(image)) { jpeg_info.input_components=1; jpeg_info.in_color_space=JCS_GRAYSCALE; } jpeg_set_defaults(&jpeg_info); jpeg_info.density_unit=0; jpeg_info.X_density=(short) image->x_resolution; jpeg_info.Y_density=(short) image->y_resolution; if (image->units == PixelsPerInchResolution) jpeg_info.density_unit=1; if (image->units == PixelsPerCentimeterResolution) jpeg_info.density_unit=2; for (i=0; i < MAX_COMPONENTS; i++) { jpeg_info.comp_info[i].h_samp_factor=1; jpeg_info.comp_info[i].v_samp_factor=1; } jpeg_set_quality(&jpeg_info,image_info->quality,True); jpeg_info.optimize_coding=True; #if (JPEG_LIB_VERSION >= 61) jpeg_info.dct_method=JDCT_FLOAT; if (image_info->interlace != NoneInterlace) jpeg_simple_progression(&jpeg_info); #endif jpeg_start_compress(&jpeg_info,True); if (image->comments != (char *) NULL) for (i=0; i < Extent(image->comments); i+=65533) jpeg_write_marker(&jpeg_info,JPEG_COM,(unsigned char *) image->comments+i, (unsigned int) Min(Extent(image->comments+i),65533)); /* Convert MIFF to JPEG raster pixels. */ packets=jpeg_info.input_components*image->columns; jpeg_pixels=(JSAMPLE *) malloc(packets*sizeof(JSAMPLE)); if (jpeg_pixels == (JSAMPLE *) NULL) PrematureExit("Unable to allocate memory",image); p=image->pixels; q=jpeg_pixels; x=0; scanline[0]=(JSAMPROW) jpeg_pixels; if ((jpeg_info.data_precision > 8) && (QuantumDepth > 8)) { if (jpeg_info.in_color_space == JCS_GRAYSCALE) for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q++=(JSAMPLE) (Intensity(*p) >> 4); x++; if (x == image->columns) { (void) jpeg_write_scanlines(&jpeg_info,scanline,1); q=jpeg_pixels; x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } else for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q++=(JSAMPLE) (p->red >> 4); *q++=(JSAMPLE) (p->green >> 4); *q++=(JSAMPLE) (p->blue >> 4); x++; if (x == image->columns) { (void) jpeg_write_scanlines(&jpeg_info,scanline,1); q=jpeg_pixels; x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } } else if (jpeg_info.in_color_space == JCS_GRAYSCALE) for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q++=(JSAMPLE) DownScale(Intensity(*p)); x++; if (x == image->columns) { (void) jpeg_write_scanlines(&jpeg_info,scanline,1); q=jpeg_pixels; x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } else for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q++=(JSAMPLE) DownScale(p->red); *q++=(JSAMPLE) DownScale(p->green); *q++=(JSAMPLE) DownScale(p->blue); x++; if (x == image->columns) { (void) jpeg_write_scanlines(&jpeg_info,scanline,1); q=jpeg_pixels; x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } jpeg_finish_compress(&jpeg_info); /* Free memory. */ jpeg_destroy_compress(&jpeg_info); free((char *) jpeg_pixels); CloseImage(image); return(True); } #else static unsigned int WriteJPEGImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("JPEG library is not available",image->filename); status=WriteMIFFImage(image_info,image); return(status); } #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e L O G O I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteLOGOImage writes an image in the LOGO encoded image format. % We use GIF because it is the only format that is compressed without % requiring addition optional plug-ins (TIFF, ZIP, etc). % % The format of the WriteLOGOImage routine is: % % status=WriteLOGOImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteLOGOImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteLOGOImage(const ImageInfo *image_info,Image *image) { char filename[MaxTextExtent]; FILE *file; int c; register int i; unsigned int status; unsigned long filesize; /* Write logo as PseudoColor MIFF image to a temporary file. */ (void) strcpy(filename,image->filename); TemporaryFilename(image->filename); status=WriteGIFImage(image_info,image); if (status == False) return(status); OpenImage(image_info,image,ReadBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); (void) remove(image->filename); filesize=image->filesize; file=image->file; /* Write logo image. */ (void) strcpy(image->filename,filename); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); (void) fprintf(image->file,"/*\n"); (void) fprintf(image->file," Logo image declaration.\n"); (void) fprintf(image->file,"*/\n"); (void) fprintf(image->file,"#define LogoImageExtent %lu\n\n",filesize); (void) fprintf(image->file,"static unsigned char\n"); (void) fprintf(image->file," LogoImage[]=\n"); (void) fprintf(image->file," {\n"); (void) fprintf(image->file," "); for (i=0; ; i++) { c=fgetc(file); if (c < 0) break; (void) fprintf(image->file,"0x%02x, ",c); if (((i+1) % 12) == 0) (void) fprintf(image->file,"\n "); } (void) fprintf(image->file,"\n };\n"); (void) fclose(file); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e M A P I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteMAPImage writes an image to a file as red, green, and blue % colormap bytes followed by the colormap indexes. % % The format of the WriteMAPImage routine is: % % status=WriteMAPImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteMAPImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteMAPImage(const ImageInfo *image_info,Image *image) { register int i; register unsigned char *q; unsigned char *colormap; unsigned int packets, packet_size; unsigned short value; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Allocate colormap. */ if (image->class == DirectClass) { QuantizeInfo quantize_info; /* Demote DirectClass to PseudoClass. */ GetQuantizeInfo(&quantize_info); quantize_info.number_colors=MaxColormapSize; quantize_info.dither=image_info->dither; QuantizeImage(&quantize_info,image); SyncImage(image); } 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); /* Write colormap to file. */ q=colormap; for (i=0; i < image->colors; i++) { WriteQuantum(image->colormap[i].red,q); WriteQuantum(image->colormap[i].green,q); WriteQuantum(image->colormap[i].blue,q); } (void) fwrite((char *) colormap,1,(int) image->colors*packet_size, image->file); free((char *) colormap); /* Write image pixels to file. */ image->compression=NoCompression; packets=RunlengthEncodeImage(image); (void) fwrite((char *) image->packed_pixels,(int) image->packet_size, (int) packets,image->file); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e M A T T E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteMATTEImage writes an image of matte bytes to a file. It % consists of data from the matte component of the image [0..255]. % % The format of the WriteMATTEImage routine is: % % status=WriteMATTEImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteMATTEImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteMATTEImage(const ImageInfo *image_info,Image *image) { Image *matte_image; register int i; unsigned int status; if (!image->matte) PrematureExit("Image does not have a matte channel",image); image->orphan=True; matte_image=CloneImage(image,image->columns,image->rows,True); image->orphan=False; if (matte_image == (Image *) NULL) PrematureExit("Unable to allocate memory",image); matte_image->class=PseudoClass; matte_image->colors=(Opaque-Transparent)+1; matte_image->colormap=(ColorPacket *) malloc(matte_image->colors*sizeof(ColorPacket)); if (matte_image->colormap == (ColorPacket *) NULL) PrematureExit("Unable to allocate memory",image); for (i=Transparent; i <= Opaque; i++) { matte_image->colormap[i].red=i; matte_image->colormap[i].green=i; matte_image->colormap[i].blue=i; } SyncImage(matte_image); status=WriteMIFFImage(image_info,matte_image); DestroyImage(matte_image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e M I F F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteMIFFImage writes an image to a file. % % The format of the WriteMIFFImage routine is: % % status=WriteMIFFImage(image_info,image) % % A description of each parameter follows: % % o status: Function WriteMIFFImage return True if the image is written. % False is returned if there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteMIFFImage(const ImageInfo *image_info,Image *image) { register int i; unsigned int scene; unsigned long packets; if ((image->class != DirectClass) && (image->class != PseudoClass)) PrematureExit("Unknown image class",image); /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); (void) strcpy((char *) image_info->magick,"MIFF"); scene=0; do { /* Pack image pixels. */ image->compression=image_info->compression; packets=RunlengthEncodeImage(image); if (image_info->compression == ZipCompression) { int status; unsigned char *compressed_pixels; unsigned long compressed_packets; /* Compress image pixels with Zip encoding. */ compressed_packets=((packets*image->packet_size*110)/100)+8; compressed_pixels=(unsigned char *) malloc(compressed_packets*sizeof(unsigned char)); if (compressed_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); status=True; #ifdef HasPNG status=compress(compressed_pixels,&compressed_packets, image->packed_pixels,packets*image->packet_size); #endif if (status) { Warning("Unable to Zip compress image",image->filename); free((char *) compressed_pixels); } else { free((char *) image->packed_pixels); image->packed_pixels=compressed_pixels; image->packet_size=1; packets=compressed_packets; } } /* Write header to file. */ (void) fprintf(image->file,"id=ImageMagick\n"); if (image->class == PseudoClass) (void) fprintf(image->file,"class=PseudoClass colors=%u\n", image->colors); else if (image->matte) (void) fprintf(image->file,"class=DirectClass matte=True\n"); else (void) fprintf(image->file,"class=DirectClass\n"); if (image->compression == RunlengthEncodedCompression) (void) fprintf(image->file,"compression=RunlengthEncoded packets=%lu\n", packets); else if (image->compression == ZipCompression) (void) fprintf(image->file,"compression=Zip packets=%lu\n",packets); (void) fprintf(image->file,"columns=%u rows=%u depth=%u\n",image->columns, image->rows,image->depth); SignatureImage(image); if (image->signature != (char *) NULL) (void) fprintf(image->file,"signature=%s\n",image->signature); if (image->scene != 0) (void) fprintf(image->file,"scene=%u\n",image->scene); if (image->gamma != 0.0) (void) fprintf(image->file,"gamma=%f\n",image->gamma); if (image->delay != 0) (void) fprintf(image->file,"delay=%u\n",image->delay); if (image->montage != (char *) NULL) (void) fprintf(image->file,"montage=%s\n",image->montage); if (image->label != (char *) NULL) (void) fprintf(image->file,"label=\"%s\"\n",image->label); if (image->comments != (char *) NULL) (void) fprintf(image->file,"{\n%s\n}\n",image->comments); (void) fprintf(image->file,"\f\n:\n"); if (image->montage != (char *) NULL) { /* Write montage tile directory. */ if (image->directory != (char *) NULL) (void) fprintf(image->file,"%s",image->directory); (void) fputc('\0',image->file); } if (image->class == PseudoClass) { register unsigned char *q; unsigned char *colormap; unsigned int packet_size; unsigned short value; /* Allocate colormap. */ 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); q=colormap; for (i=0; i < image->colors; i++) { WriteQuantum(image->colormap[i].red,q); WriteQuantum(image->colormap[i].green,q); WriteQuantum(image->colormap[i].blue,q); } /* Write colormap to file. */ (void) fwrite((char *) colormap,1,(int) image->colors*packet_size, image->file); free((char *) colormap); } /* Write image pixels to file. */ (void) fwrite((char *) image->packed_pixels,(int) image->packet_size, (int) packets,image->file); if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e M O N O I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteMONOImage writes an image of raw bits in LSB order to a file. % % The format of the WriteMONOImage routine is: % % status=WriteMONOImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteMATTEImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteMONOImage(const ImageInfo *image_info,Image *image) { int x; register unsigned char bit, byte, polarity; register int i, j; register RunlengthPacket *p; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Convert image to a bi-level image. */ if (!IsMonochromeImage(image)) { QuantizeInfo quantize_info; GetQuantizeInfo(&quantize_info); quantize_info.number_colors=2; quantize_info.dither=image_info->dither; quantize_info.colorspace=GRAYColorspace; QuantizeImage(&quantize_info,image); SyncImage(image); } polarity=0; if (image->colors == 2) polarity=Intensity(image->colormap[0]) > Intensity(image->colormap[1]); bit=0; byte=0; x=0; p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { byte>>=1; if (p->index == polarity) byte|=0x80; bit++; if (bit == 8) { (void) fputc(byte,image->file); bit=0; byte=0; } x++; if (x == image->columns) { /* Advance to the next scanline. */ if (bit != 0) (void) fputc(byte >> (8-bit),image->file); bit=0; byte=0; x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e M P E G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteMPEGImage writes an image in the MPEG encoded image format. % % The format of the WriteMPEGImage routine is: % % status=WriteMPEGImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteMPEGImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteMPEGImage(const ImageInfo *image_info,Image *image) { char basename[MaxTextExtent], command[MaxTextExtent], filename[MaxTextExtent]; Image component_image; ImageInfo local_info; MonitorHandler handler; register int i; unsigned int scene, status; if (image->next == (Image *) NULL) PrematureExit("MPEG requires multi-frame image",image); /* Write component images. */ scene=image->scene; TemporaryFilename(basename); (void) strcpy(filename,basename); (void) strcat(filename,"%d"); local_info=(*image_info); local_info.interlace=PartitionInterlace; for (i=0; i < image->number_scenes; i++) { handler=SetMonitorHandler((MonitorHandler) NULL); component_image=(*image); component_image.previous=(Image *) NULL; component_image.next=(Image *) NULL; (void) sprintf(component_image.filename,filename,i); (void) WriteYUVImage(&local_info,&component_image); if (image->next != (Image *) NULL) image=image->next; (void) SetMonitorHandler(handler); ProgressMonitor(SaveImageText,i,image->number_scenes); } /* Write MPEG image. */ (void) sprintf(command,"mpeg -a %u -b %u -h %u -v %u -PF %s -s %s",scene, image->scene,image->columns,image->rows,basename,image->filename); status=SystemCommand(command); /* Remove component files. */ for (i=0; i < image->number_scenes; i++) { (void) sprintf(component_image.filename,filename,i); (void) strcat(component_image.filename,".Y"); (void) remove(component_image.filename); (void) sprintf(component_image.filename,filename,i); (void) strcat(component_image.filename,".U"); (void) remove(component_image.filename); (void) sprintf(component_image.filename,filename,i); (void) strcat(component_image.filename,".V"); (void) remove(component_image.filename); } return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e M T V I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteMTVImage writes an image to a file in red, green, and blue % MTV rasterfile format. % % The format of the WriteMTVImage routine is: % % status=WriteMTVImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteMTVImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WriteMTVImage(const ImageInfo *image_info,Image *image) { register int i, j; register RunlengthPacket *p; unsigned int scene; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); scene=0; do { /* Convert MIFF to MTV raster pixels. */ (void) fprintf(image->file,"%u %u\n",image->columns,image->rows); p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { (void) fputc(DownScale(p->red),image->file); (void) fputc(DownScale(p->green),image->file); (void) fputc(DownScale(p->blue),image->file); } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P C D I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePCDImage writes an image in the Photo CD encoded image % format. % % The format of the WritePCDImage routine is: % % status=WritePCDImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePCDImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WritePCDTile(Image *image,char *geometry, char *tile_geometry) { Image *downsampled_image, *tile_image; int x, y; register int i; register RunlengthPacket *p, *q; unsigned int height, width; /* Scale image to tile size. */ width=image->columns; height=image->rows; (void) ParseImageGeometry(geometry,&x,&y,&width,&height); if ((width % 2) != 0) width--; if ((height % 2) != 0) height--; image->orphan=True; tile_image=ZoomImage(image,width,height,MitchellFilter); image->orphan=False; if (tile_image == (Image *) NULL) PrematureExit("Unable to scale image",image); (void) sscanf(geometry,"%ux%u",&width,&height); if ((tile_image->columns != width) || (tile_image->rows != height)) { Image *bordered_image; RectangleInfo border_info; /* Put a border around the image. */ border_info.width=(width-tile_image->columns+1) >> 1; border_info.height=(height-tile_image->rows+1) >> 1; bordered_image=BorderImage(tile_image,&border_info); if (bordered_image == (Image *) NULL) PrematureExit("Unable to border image",image); DestroyImage(tile_image); tile_image=bordered_image; } TransformImage(&tile_image,(char *) NULL,tile_geometry); RGBTransformImage(tile_image,YCCColorspace); downsampled_image=MinifyImage(tile_image); if (downsampled_image == (Image *) NULL) PrematureExit("Unable to scale image",image); if (!UncompressImage(tile_image)) return(False); if (!UncompressImage(downsampled_image)) return(False); /* Write tile to PCD file. */ p=tile_image->pixels; for (y=0; y < tile_image->rows; y+=2) { for (x=0; x < (tile_image->columns << 1); x++) { (void) fputc(DownScale(p->red),image->file); p++; } q=downsampled_image->pixels+(y >> 1)*downsampled_image->columns; for (x=0; x < downsampled_image->columns; x++) { (void) fputc(DownScale(q->green),image->file); q++; } q=downsampled_image->pixels+(y >> 1)*downsampled_image->columns; for (x=0; x < downsampled_image->columns; x++) { (void) fputc(DownScale(q->blue),image->file); q++; } ProgressMonitor(SaveImageText,y,tile_image->rows); } for (i=0; i < 0x800; i++) (void) fputc('\0',image->file); DestroyImage(downsampled_image); DestroyImage(tile_image); return(True); } static unsigned int WritePCDImage(const ImageInfo *image_info,Image *image) { Image *pcd_image; register int i; unsigned int status; pcd_image=image; if (image->columns < image->rows) { Image *rotated_image; /* Rotate portrait to landscape. */ image->orphan=True; rotated_image=RotateImage(image,90.0,False,True); image->orphan=False; if (rotated_image == (Image *) NULL) PrematureExit("Unable to rotate image",image); pcd_image=rotated_image; } /* Open output image file. */ OpenImage(image_info,pcd_image,WriteBinaryType); if (pcd_image->file == (FILE *) NULL) PrematureExit("Unable to open file",pcd_image); /* Write PCD image header. */ for (i=0; i < 0x800; i++) (void) fputc('\0',pcd_image->file); (void) fwrite("PCD_IPI",1,7,pcd_image->file); for (i=0; i < 1531; i++) (void) fputc('\0',pcd_image->file); if (image->columns < image->rows) (void) fputc('\1',pcd_image->file); else (void) fputc('\0',pcd_image->file); for (i=0; i < 3*0x800-1539; i++) (void) fputc('\0',pcd_image->file); /* Write PCD tiles. */ status=WritePCDTile(pcd_image,"768x512>","192x128"); status|=WritePCDTile(pcd_image,"768x512>","384x256"); status|=WritePCDTile(pcd_image,"768x512>","768x512"); CloseImage(pcd_image); if (image->columns < image->rows) DestroyImage(pcd_image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P C L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePCLImage writes an image in the Page Control Language encoded % image format. % % The format of the WritePCLImage routine is: % % status=WritePCLImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePCLImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % % */ static unsigned int WritePCLImage(const ImageInfo *image_info,Image *image) { int delta_x, delta_y, flags, sans_offset, x, y; register int i, j; register RunlengthPacket *p; unsigned int density, height, page_height, page_size, page_width, text_size, width; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Initialize the printer. */ (void) fprintf(image->file,"\033E"); /* reset */ (void) fprintf(image->file,"\033&l0O"); /* portrait orientation */ (void) fprintf(image->file,"\033&l0E"); /* top margin 0 */ /* Center image on PCL page. */ text_size=0; if (image->label != (char *) NULL) text_size=MultilineCensus(image->label)*image_info->pointsize+12; x=0; y=0; width=image->columns; height=image->rows; (void) XParseGeometry(PCLPageGeometry,&x,&y,&page_width,&page_height); flags=NoValue; if (image_info->page != (char *) NULL) flags=XParseGeometry(image_info->page,&x,&y,&page_width,&page_height); if (image->page != (char *) NULL) flags=XParseGeometry(image->page,&x,&y,&page_width,&page_height); if (((page_width-(x << 1)) < width) || ((page_height-(y << 1)-text_size) < height)) { unsigned long scale_factor; /* Scale image relative to PCL page. */ scale_factor=UpShift(page_width-(x << 1))/width; if (scale_factor > (UpShift(page_height-(y << 1)-text_size)/height)) scale_factor=UpShift(page_height-(y << 1)-text_size)/height; width=DownShift(width*scale_factor); height=DownShift(height*scale_factor); } if ((flags & XValue) == 0) { /* Center image in the X direction. */ delta_x=page_width-(width+(x << 1)); if (delta_x >= 0) x=(delta_x >> 1)+x; } if ((flags & YValue) == 0) { /* Center image in the X direction. */ delta_y=page_height-(height+(y << 1))-text_size; if (delta_y >= 0) y=(delta_y >> 1)+y; } page_size=2; if ((page_width == 540) && (page_height == 720)) page_size=1; /* executive */ if ((page_width == 612) && (page_height == 792)) page_size=2; /* letter */ if ((page_width == 612) && (page_height == 1008)) page_size=3; /* legal */ if ((page_width == 1224) && (page_height == 792)) page_size=6; /* ledger */ if ((page_width == 595) && (page_height == 842)) page_size=26; /* A4 */ if ((page_width == 842) && (page_height == 1191)) page_size=27; /* A3 */ if ((page_width == 729) && (page_height == 1032)) page_size=45; /* B5 */ if ((page_width == 516) && (page_height == 729)) page_size=46; /* B4 */ (void) fprintf(image->file,"\033&l%uA",page_size); /* papersize */ (void) XParseGeometry(PCLDensityGeometry,&sans_offset,&sans_offset, &density,&density); if (image_info->density != (char *) NULL) (void) XParseGeometry(image_info->density,&sans_offset,&sans_offset, &density,&density); (void) fprintf(image->file,"\033*p%dx%dY",x,y); if (image->label != (char *) NULL) { /* Print label. */ (void) fprintf(image->file,"\033&k2G"); (void) fprintf(image->file,"\033(s1p%uv5t3b",image_info->pointsize); (void) fprintf(image->file,"\n%s\n",image->label); (void) fprintf(image->file,"\033(s0B"); } (void) fprintf(image->file,"\033*t%uR",density); /* graphic resolution */ width=(density*width)/75; height=(density*height)/75; if (!IsGrayImage(image)) { /* Write PCL color image. */ (void) fprintf(image->file,"\033*r%us%uT",image->columns,image->rows); (void) fprintf(image->file,"\033*t%uh%uV",width,height); (void) fprintf(image->file,"\033*v6W"); (void) fputc('\000',image->file); /* color model */ (void) fputc('\003',image->file); /* direct pixel encoding */ (void) fputc('\000',image->file); /* bits per index */ (void) fputc('\010',image->file); /* bits red*/ (void) fputc('\010',image->file); /* bits green*/ (void) fputc('\010',image->file); /* bits blue */ (void) fprintf(image->file,"\033*r2A"); /* start graphics */ (void) fprintf(image->file,"\033*b0M"); /* no compression */ (void) fprintf(image->file,"\033*b%uW",3*image->columns); x=0; p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) (void) fprintf(image->file,"%c%c%c",(int) DownScale(p->red), (int) DownScale(p->green),(int) DownScale(p->blue)); x++; if (x == image->columns) { (void) fprintf(image->file,"\033*b%uW",3*image->columns); x=0; } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } (void) fprintf(image->file,"\033*rC"); /* end graphics */ } else { char geometry[MaxTextExtent]; register unsigned char bit, byte, polarity; /* Write PCL monochrome image. */ if ((width != image->columns) || (height != image->rows)) { FILE *file; /* Scale image. */ file=image->file; image->file=(FILE *) NULL; /* prevents closing */ (void) sprintf(geometry,"%ux%u",width,height); TransformImage(&image,(char *) NULL,geometry); image->file=file; } if (image->colors > 2) { QuantizeInfo quantize_info; GetQuantizeInfo(&quantize_info); quantize_info.number_colors=2; quantize_info.dither=image_info->dither; quantize_info.colorspace=GRAYColorspace; QuantizeImage(&quantize_info,image); SyncImage(image); } p=image->pixels; polarity=0; if (image->colors == 2) polarity= Intensity(image->colormap[0]) > Intensity(image->colormap[1]); bit=0; byte=0; x=0; y=0; (void) fprintf(image->file,"\033*r%us%uT",image->columns,image->rows); (void) fprintf(image->file,"\033*r1A"); /* start graphics */ (void) fprintf(image->file,"\033*b0M"); /* no compression */ (void) fprintf(image->file,"\033*b%uW",(image->columns+7)/8); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { byte<<=1; if (p->index == polarity) byte|=0x01; bit++; if (bit == 8) { (void) fputc(byte,image->file); bit=0; byte=0; } x++; if (x == image->columns) { /* Advance to the next scanline. */ if (bit != 0) (void) fputc(byte << (8-bit),image->file); bit=0; byte=0; x=0; y++; if (y < image->rows) (void) fprintf(image->file,"\033*b%uW",(image->columns+7)/8); } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } (void) fprintf(image->file,"\033*rB"); /* end graphics */ } (void) fprintf(image->file,"\033&l0H"); (void) fprintf(image->file,"\033E"); /* reset */ CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P C X I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePCXImage writes an image in the ZSoft IBM PC Paintbrush file % format. % % The format of the WritePCXImage routine is: % % status=WritePCXImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePCXImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WritePCXImage(const ImageInfo *image_info,Image *image) { typedef struct _PCXHeader { unsigned char identifier, version, encoding, bits_per_pixel; short int left, top, right, bottom, horizontal_resolution, vertical_resolution; unsigned char reserved, planes; short int bytes_per_line, palette_info; unsigned char colormap_signature; } PCXHeader; PCXHeader pcx_header; register int i, j, x, y; register RunlengthPacket *p; register unsigned char *q; unsigned char count, packet, *pcx_colormap, *pcx_pixels, previous; unsigned int packets, scene; unsigned long *page_table; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); page_table=(unsigned long *) NULL; if (image_info->adjoin) { /* Write the DCX page table. */ LSBFirstWriteLong(0x3ADE68B1L,image->file); page_table=(unsigned long *) malloc(1024*sizeof(unsigned long)); if (page_table == (unsigned long *) NULL) PrematureExit("Unable to allocate memory",image); for (scene=0; scene < 1024; scene++) LSBFirstWriteLong(0x00000000L,image->file); } scene=0; do { if (page_table != (unsigned long *) NULL) page_table[scene]=ftell(image->file); /* Initialize PCX raster file header. */ pcx_header.identifier=0x0a; pcx_header.version=5; pcx_header.encoding=1; pcx_header.bits_per_pixel=8; if (IsMonochromeImage(image)) pcx_header.bits_per_pixel=1; pcx_header.left=0; pcx_header.top=0; pcx_header.right=image->columns-1; pcx_header.bottom=image->rows-1; pcx_header.horizontal_resolution=(short) image->columns; pcx_header.vertical_resolution=(short) image->rows; if (image->units == PixelsPerInchResolution) { pcx_header.horizontal_resolution=(short) image->x_resolution; pcx_header.vertical_resolution=(short) image->y_resolution; } if (image->units == PixelsPerCentimeterResolution) { pcx_header.horizontal_resolution=(short) (2.54*image->x_resolution); pcx_header.vertical_resolution=(short) (2.54*image->y_resolution); } pcx_header.reserved=0; pcx_header.planes=1; if (!IsPseudoClass(image)) { pcx_header.planes=3; if (image->matte) pcx_header.planes++; } pcx_header.bytes_per_line=(image->columns*pcx_header.bits_per_pixel+7)/8; pcx_header.palette_info=1; pcx_header.colormap_signature=0x0c; /* Write PCX header. */ (void) fwrite(&pcx_header.identifier,1,1,image->file); (void) fwrite(&pcx_header.version,1,1,image->file); (void) fwrite(&pcx_header.encoding,1,1,image->file); (void) fwrite(&pcx_header.bits_per_pixel,1,1,image->file); LSBFirstWriteShort((unsigned int) pcx_header.left,image->file); LSBFirstWriteShort((unsigned int) pcx_header.top,image->file); LSBFirstWriteShort((unsigned int) pcx_header.right,image->file); LSBFirstWriteShort((unsigned int) pcx_header.bottom,image->file); LSBFirstWriteShort((unsigned int) pcx_header.horizontal_resolution, image->file); LSBFirstWriteShort((unsigned int) pcx_header.vertical_resolution, image->file); /* Dump colormap to file. */ pcx_colormap=(unsigned char *) malloc(3*256*sizeof(unsigned char)); if (pcx_colormap == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); for (i=0; i < (3*256); i++) pcx_colormap[i]=0; q=pcx_colormap; if (image->class == PseudoClass) for (i=0; i < image->colors; i++) { *q++=DownScale(image->colormap[i].red); *q++=DownScale(image->colormap[i].green); *q++=DownScale(image->colormap[i].blue); } (void) fwrite((char *) pcx_colormap,3,16,image->file); (void) fwrite(&pcx_header.reserved,1,1,image->file); (void) fwrite(&pcx_header.planes,1,1,image->file); LSBFirstWriteShort((unsigned int) pcx_header.bytes_per_line,image->file); LSBFirstWriteShort((unsigned int) pcx_header.palette_info,image->file); for (i=0; i < 58; i++) (void) fwrite("\0",1,1,image->file); packets=image->rows*pcx_header.bytes_per_line*pcx_header.planes; pcx_pixels=(unsigned char *) malloc(packets*sizeof(unsigned char)); if (pcx_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); x=0; y=0; p=image->pixels; q=pcx_pixels; if (image->class == DirectClass) { /* Convert DirectClass image to PCX raster pixels. */ if (!UncompressImage(image)) return(False); for (y=0; y < image->rows; y++) { q=pcx_pixels+(y*pcx_header.bytes_per_line*pcx_header.planes); for (i=0; i < (int) pcx_header.planes; i++) { p=image->pixels+y*image->columns; for (x=0; x < pcx_header.bytes_per_line; x++) { switch (i) { case 0: { *q++=DownScale(p->red); break; } case 1: { *q++=DownScale(p->green); break; } case 2: { *q++=DownScale(p->blue); break; } case 3: default: { *q++=DownScale(p->index); break; } } p++; } } ProgressMonitor(SaveImageText,y,image->rows); } } else if (pcx_header.bits_per_pixel > 1) for (i=0; i < image->packets; i++) { /* Convert PseudoClass image to PCX raster pixels. */ for (j=0; j <= ((int) p->length); j++) { *q++=p->index; x++; if (x == image->columns) { x=0; y++; q=pcx_pixels+y*pcx_header.bytes_per_line; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } else { register unsigned char bit, byte, polarity; /* Convert PseudoClass image to a PCX monochrome image. */ polarity=0; if (image->colors == 2) polarity=Intensity(image->colormap[0]) < Intensity(image->colormap[1]); bit=0; byte=0; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { byte<<=1; if (p->index == polarity) byte|=0x01; bit++; if (bit == 8) { *q++=byte; bit=0; byte=0; } x++; if (x == image->columns) { /* Advance to the next scanline. */ if (bit != 0) *q++=byte << (8-bit); bit=0; byte=0; x=0; y++; q=pcx_pixels+y*pcx_header.bytes_per_line; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } /* Runlength-encoded PCX pixels. */ for (y=0; y < image->rows; y++) { q=pcx_pixels+(y*pcx_header.bytes_per_line*pcx_header.planes); for (i=0; i < (int) pcx_header.planes; i++) { previous=(*q++); count=1; for (x=0; x < (pcx_header.bytes_per_line-1); x++) { packet=(*q++); if ((packet == previous) && (count < 63)) { count++; continue; } if ((count > 1) || ((previous & 0xc0) == 0xc0)) { count|=0xc0; (void) fwrite(&count,1,1,image->file); } (void) fwrite(&previous,1,1,image->file); previous=packet; count=1; } if ((count > 1) || ((previous & 0xc0) == 0xc0)) { count|=0xc0; (void) fwrite(&count,1,1,image->file); } (void) fwrite(&previous,1,1,image->file); ProgressMonitor(SaveImageText,y,image->rows); } } if (image->colors > 16) { (void) fwrite(&pcx_header.colormap_signature,1,1,image->file); (void) fwrite((char *) pcx_colormap,3,256,image->file); } free((char *) pcx_pixels); free((char *) pcx_colormap); if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); if (scene >= 1023) break; } while (image_info->adjoin); if (page_table != (unsigned long *) NULL) { /* Write the DCX page table. */ page_table[scene+1]=0; (void) fseek(image->file,0L,SEEK_SET); LSBFirstWriteLong(0x3ADE68B1L,image->file); for (i=0; i <= (int) scene; i++) LSBFirstWriteLong(page_table[i],image->file); free((char *) page_table); } CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P D F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePDFImage writes an image in the Portable Document image % format. % % The format of the WritePDFImage routine is: % % status=WritePDFImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePDFImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ static unsigned int WritePDFImage(const ImageInfo *image_info,Image *image) { #define DefaultThumbnailGeometry "106x106" #define ObjectsPerImage 12 char date[MaxTextExtent], density[MaxTextExtent], **labels; f