/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % 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; float dx_resolution, dy_resolution, x_resolution, y_resolution; int count, delta_x, delta_y, flags, x, y; Image encode_image, *tile_image; register RunlengthPacket *p; register unsigned char *q; register int i, j; time_t timer; unsigned char *pixels; unsigned int height, info_id, number_packets, object, pages_id, page_height, page_width, root_id, scene, text_size, width; unsigned long length, *xref; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); if ((image->file == stdout) || image->pipe) { /* Write standard output or pipe to temporary file. */ encode_image=(*image); TemporaryFilename(image->filename); image->temporary=True; OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } /* Allocate X ref memory. */ xref=(unsigned long *) malloc(2048*sizeof(unsigned long)); if (xref == (unsigned long *) NULL) { Warning("Memory allocation error",image->filename); return(False); } /* Write Info object. */ object=0; (void) fprintf(image->file,"%%PDF-1.1 \n"); xref[object++]=ftell(image->file); info_id=object; (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); timer=time((time_t *) NULL); (void) localtime(&timer); (void) strcpy(date,ctime(&timer)); date[Extent(date)-1]='\0'; (void) fprintf(image->file,"/CreationDate (%s)\n",date); (void) fprintf(image->file,"/Producer ImageMagick\n"); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"endobj\n"); /* Write Catalog object. */ xref[object++]=ftell(image->file); root_id=object; (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); (void) fprintf(image->file,"/Type /Catalog\n"); (void) fprintf(image->file,"/Pages %u 0 R\n",object+1); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"endobj\n"); /* Write Pages object. */ xref[object++]=ftell(image->file); pages_id=object; (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); (void) fprintf(image->file,"/Type /Pages\n"); (void) fprintf(image->file,"/Kids [ %u 0 R ",object+1); count=pages_id+ObjectsPerImage+1; if (image_info->adjoin) { Image *kid_image; /* Predict page object id's. */ kid_image=image; for ( ; kid_image->next != (Image *) NULL; count+=ObjectsPerImage) { (void) fprintf(image->file,"%d 0 R ",count); kid_image=kid_image->next; } xref=(unsigned long *) realloc((char *) xref,(count+2048)*sizeof(unsigned long)); if (xref == (unsigned long *) NULL) { Warning("Memory allocation error",image->filename); return(False); } } (void) fprintf(image->file,"]\n"); (void) fprintf(image->file,"/Count %u\n",(count-pages_id)/ObjectsPerImage); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"endobj\n"); scene=0; do { /* Scale image to size of Portable Document 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; /* Center image on Portable Document page. */ (void) XParseGeometry(PSPageGeometry,&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 Portable Document 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; } /* Scale relative to dots-per-inch. */ dx_resolution=72.0; dy_resolution=72.0; x_resolution=72.0; (void) strcpy(density,PSDensityGeometry); count=sscanf(density,"%fx%f",&x_resolution,&y_resolution); if (image_info->density != (char *) NULL) count=sscanf(image_info->density,"%fx%f",&x_resolution,&y_resolution); if (count != 2) y_resolution=x_resolution; width=(unsigned int) (((width*dx_resolution)/x_resolution)+0.5); height=(unsigned int) (((height*dy_resolution)/y_resolution)+0.5); /* Write Page object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); (void) fprintf(image->file,"/Type /Page\n"); (void) fprintf(image->file,"/Parent %u 0 R\n",pages_id); (void) fprintf(image->file,"/Resources <<\n"); (void) fprintf(image->file,"/Font << /F%u %u 0 R >>\n",image->scene, object+4); (void) fprintf(image->file,"/XObject << /Im%u %u 0 R >>\n",image->scene, object+5); (void) fprintf(image->file,"/ProcSet %u 0 R >>\n",object+3); (void) fprintf(image->file,"/MediaBox [ 0 0 %u %u ]\n", page_width,page_height); (void) fprintf(image->file,"/Contents %u 0 R\n",object+1); if (!IsMonochromeImage(image)) (void) fprintf(image->file,"/Thumb %u 0 R\n",object+8); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"endobj\n"); /* Write Contents object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); (void) fprintf(image->file,"/Length %u 0 R\n",object+1); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"stream\n"); length=ftell(image->file); (void) fprintf(image->file,"q\n"); labels=StringToList(image->label); if (labels != (char **) NULL) { for (i=0; labels[i] != (char *) NULL; i++) { (void) fprintf(image->file,"BT\n"); (void) fprintf(image->file,"/F%u %u Tf\n",image->scene, image_info->pointsize); (void) fprintf(image->file,"%d %u Td\n",x,y+height+ i*image_info->pointsize+12); (void) fprintf(image->file,"(%s) Tj\n",labels[i]); (void) fprintf(image->file,"ET\n"); free(labels[i]); } free((char *) labels); } (void) fprintf(image->file,"%u 0 0 %u %d %d cm\n",width,height,x,y); (void) fprintf(image->file,"/Im%u Do\n",image->scene); (void) fprintf(image->file,"Q\n"); length=ftell(image->file)-length; (void) fprintf(image->file,"endstream\n"); (void) fprintf(image->file,"endobj\n"); /* Write Length object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"%lu\n",length); (void) fprintf(image->file,"endobj\n"); /* Write Procset object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); if (!IsPseudoClass(image) && !IsGrayImage(image)) (void) fprintf(image->file,"[ /PDF /Text /ImageC"); else if (IsMonochromeImage(image)) (void) fprintf(image->file,"[ /PDF /Text /ImageB"); else (void) fprintf(image->file,"[ /PDF /Text /ImageI"); (void) fprintf(image->file," ]\n"); (void) fprintf(image->file,"endobj\n"); /* Write Font object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); (void) fprintf(image->file,"/Type /Font\n"); (void) fprintf(image->file,"/Subtype /Type1\n"); (void) fprintf(image->file,"/Name /F%u\n",image->scene); (void) fprintf(image->file,"/BaseFont /Helvetica\n"); (void) fprintf(image->file,"/Encoding /MacRomanEncoding\n"); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"endobj\n"); /* Write XObject object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); (void) fprintf(image->file,"/Type /XObject\n"); (void) fprintf(image->file,"/Subtype /Image\n"); (void) fprintf(image->file,"/Name /Im%u\n",image->scene); image->compression=image_info->compression; if (image->compression == NoCompression) (void) fprintf(image->file,"/Filter /ASCII85Decode\n"); else if (!IsMonochromeImage(image)) (void) fprintf(image->file, "/Filter [ /ASCII85Decode /LZWDecode ]\n"); else { (void) fprintf(image->file, "/Filter [ /ASCII85Decode /CCITTFaxDecode ]\n"); (void) fprintf(image->file, "/DecodeParms [ << >> << /Columns %d /Rows %d >> ]\n", image->columns,image->rows); } (void) fprintf(image->file,"/Width %u\n",image->columns); (void) fprintf(image->file,"/Height %u\n",image->rows); (void) fprintf(image->file,"/ColorSpace %u 0 R\n",object+2); (void) fprintf(image->file,"/BitsPerComponent %d\n", IsMonochromeImage(image) ? 1 : 8); (void) fprintf(image->file,"/Length %u 0 R\n",object+1); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"stream\n"); length=ftell(image->file); p=image->pixels; if (!IsPseudoClass(image) && !IsGrayImage(image)) switch (image->compression) { case RunlengthEncodedCompression: default: { /* Allocate pixel array. */ number_packets=3*image->columns*image->rows; pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char)); if (pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); /* Dump runlength encoded pixels. */ q=pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (image->matte && (p->index == Transparent)) { *q++=DownScale(MaxRGB); *q++=DownScale(MaxRGB); *q++=DownScale(MaxRGB); } else { *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); } (void) LZWEncodeImage(image->file,pixels,number_packets); free((char *) pixels); break; } case NoCompression: { /* Dump uncompressed DirectColor packets. */ Ascii85Initialize(); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (image->matte && (p->index == Transparent)) { Ascii85Encode(DownScale(MaxRGB),image->file); Ascii85Encode(DownScale(MaxRGB),image->file); Ascii85Encode(DownScale(MaxRGB),image->file); } else { Ascii85Encode(DownScale(p->red),image->file); Ascii85Encode(DownScale(p->green),image->file); Ascii85Encode(DownScale(p->blue),image->file); } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } Ascii85Flush(image->file); break; } } else if (IsMonochromeImage(image)) { register unsigned char bit, byte, polarity; polarity= Intensity(image->colormap[0]) < Intensity(image->colormap[1]); bit=0; byte=0; x=0; switch (image->compression) { case RunlengthEncodedCompression: default: { (void) HuffmanEncodeImage(image_info,image); break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(); 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) { Ascii85Encode(byte,image->file); bit=0; byte=0; } x++; if (x == image->columns) { /* Advance to the next scanline. */ if (bit != 0) Ascii85Encode(byte << (8-bit),image->file); bit=0; byte=0; x=0; y++; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } Ascii85Flush(image->file); break; } } } else { /* Dump number of colors and colormap. */ switch (image->compression) { case RunlengthEncodedCompression: default: { /* Allocate pixel array. */ number_packets=image->columns*image->rows; pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char)); if (pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); /* Dump Runlength encoded pixels. */ q=pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=(unsigned char) p->index; p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } (void) LZWEncodeImage(image->file,pixels,number_packets); free((char *) pixels); break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) Ascii85Encode((unsigned char) p->index,image->file); p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } Ascii85Flush(image->file); break; } } } length=ftell(image->file)-length; (void) fprintf(image->file,"\nendstream\n"); (void) fprintf(image->file,"endobj\n"); /* Write Length object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"%lu\n",length); (void) fprintf(image->file,"endobj\n"); /* Write Colorspace object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); if (!IsPseudoClass(image) && !IsGrayImage(image)) (void) fprintf(image->file,"/DeviceRGB\n"); else if (IsMonochromeImage(image)) (void) fprintf(image->file,"/DeviceGray\n"); else (void) fprintf(image->file,"[ /Indexed /DeviceRGB %u %u 0 R ]\n", image->colors-1,object+3); (void) fprintf(image->file,"endobj\n"); if (IsMonochromeImage(image)) { xref[object++]=0; xref[object++]=0; } else { /* Write Thumb object. */ image->orphan=True; (void) ParseImageGeometry(DefaultThumbnailGeometry,&x,&y,&width, &height); if (image->class == PseudoClass) tile_image=SampleImage(image,width,height); else tile_image=ZoomImage(image,width,height,MitchellFilter); image->orphan=False; if (tile_image == (Image *) NULL) PrematureExit("Unable to allocate memory",image); xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); if (image->compression == NoCompression) (void) fprintf(image->file,"/Filter /ASCII85Decode\n"); else if (!IsMonochromeImage(image)) (void) fprintf(image->file, "/Filter [ /ASCII85Decode /LZWDecode ]\n"); else { (void) fprintf(image->file, "/Filter [ /ASCII85Decode /CCITTFaxDecode ]\n"); (void) fprintf(image->file, "/DecodeParms [ << >> << /Columns %d /Rows %d >> ]\n", tile_image->columns,tile_image->rows); } (void) fprintf(image->file,"/Width %u\n",tile_image->columns); (void) fprintf(image->file,"/Height %u\n",tile_image->rows); (void) fprintf(image->file,"/ColorSpace %u 0 R\n",object-1); (void) fprintf(image->file,"/BitsPerComponent %d\n", IsMonochromeImage(image) ? 1 : 8); (void) fprintf(image->file,"/Length %u 0 R\n",object+1); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"stream\n"); length=ftell(image->file); p=tile_image->pixels; if (!IsPseudoClass(image) && !IsGrayImage(image)) switch (image->compression) { case RunlengthEncodedCompression: default: { /* Allocate pixel array. */ number_packets=3*tile_image->columns*tile_image->rows; pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char)); if (pixels == (unsigned char *) NULL) { DestroyImage(tile_image); PrematureExit("Unable to allocate memory",image); } /* Dump runlength encoded pixels. */ q=pixels; for (i=0; i < tile_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (tile_image->matte && (p->index == Transparent)) { *q++=DownScale(MaxRGB); *q++=DownScale(MaxRGB); *q++=DownScale(MaxRGB); } else { *q++=DownScale(p->red); *q++=DownScale(p->green); *q++=DownScale(p->blue); } } p++; } (void) LZWEncodeImage(image->file,pixels,number_packets); free((char *) pixels); break; } case NoCompression: { /* Dump uncompressed DirectColor packets. */ Ascii85Initialize(); for (i=0; i < tile_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (tile_image->matte && (p->index == Transparent)) { Ascii85Encode(DownScale(MaxRGB),image->file); Ascii85Encode(DownScale(MaxRGB),image->file); Ascii85Encode(DownScale(MaxRGB),image->file); } else { Ascii85Encode(DownScale(p->red),image->file); Ascii85Encode(DownScale(p->green),image->file); Ascii85Encode(DownScale(p->blue),image->file); } } p++; } Ascii85Flush(image->file); break; } } else if (IsMonochromeImage(image)) { register unsigned char bit, byte, polarity; polarity=Intensity(tile_image->colormap[0]) < Intensity(tile_image->colormap[1]); bit=0; byte=0; x=0; switch (image->compression) { case RunlengthEncodedCompression: default: { /* Allocate pixel array. */ number_packets= ((tile_image->columns+7) >> 3)*tile_image->rows; pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char)); if (pixels == (unsigned char *) NULL) { DestroyImage(tile_image); PrematureExit("Unable to allocate memory",image); } /* Dump Runlength encoded pixels. */ q=pixels; for (i=0; i < tile_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 == tile_image->columns) { /* Advance to the next scanline. */ if (bit != 0) *q++=byte << (8-bit); bit=0; byte=0; x=0; y++; } } p++; } (void) LZWEncodeImage(image->file,pixels,number_packets); free((char *) pixels); break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(); for (i=0; i < tile_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { byte<<=1; if (p->index == polarity) byte|=0x01; bit++; if (bit == 8) { Ascii85Encode(byte,image->file); bit=0; byte=0; } x++; if (x == tile_image->columns) { /* Advance to the next scanline. */ if (bit != 0) Ascii85Encode(byte << (8-bit),image->file); bit=0; byte=0; x=0; y++; } } p++; } Ascii85Flush(image->file); break; } } } else { /* Dump number of colors and colormap. */ switch (image->compression) { case RunlengthEncodedCompression: default: { /* Allocate pixel array. */ number_packets=tile_image->columns*tile_image->rows; pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char)); if (pixels == (unsigned char *) NULL) { DestroyImage(tile_image); PrematureExit("Unable to allocate memory",image); } /* Dump Runlength encoded pixels. */ q=pixels; for (i=0; i < tile_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=(unsigned char) p->index; p++; } (void) LZWEncodeImage(image->file,pixels,number_packets); free((char *) pixels); break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(); for (i=0; i < tile_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) Ascii85Encode((unsigned char) p->index,image->file); p++; } Ascii85Flush(image->file); break; } } } DestroyImage(tile_image); length=ftell(image->file)-length; (void) fprintf(image->file,"\nendstream\n"); (void) fprintf(image->file,"endobj\n"); /* Write Length object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"%lu\n",length); (void) fprintf(image->file,"endobj\n"); } if ((image->class == DirectClass) || IsMonochromeImage(image)) { xref[object++]=0; xref[object++]=0; } else { /* Write Colormap object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"<<\n"); (void) fprintf(image->file,"/Filter /ASCII85Decode \n"); (void) fprintf(image->file,"/Length %u 0 R\n",object+1); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"stream\n"); length=ftell(image->file); Ascii85Initialize(); for (i=0; i < image->colors; i++) { Ascii85Encode(DownScale(image->colormap[i].red),image->file); Ascii85Encode(DownScale(image->colormap[i].green),image->file); Ascii85Encode(DownScale(image->colormap[i].blue),image->file); } Ascii85Flush(image->file); length=ftell(image->file)-length; (void) fprintf(image->file,"\nendstream\n"); (void) fprintf(image->file,"endobj\n"); /* Write Length object. */ xref[object++]=ftell(image->file); (void) fprintf(image->file,"%u 0 obj\n",object); (void) fprintf(image->file,"%lu\n",length); (void) fprintf(image->file,"endobj\n"); } if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); /* Write Xref object. */ length=ftell(image->file)-xref[0]+10; (void) fprintf(image->file,"xref\n"); (void) fprintf(image->file,"0 %u\n",object+1); (void) fprintf(image->file,"0000000000 65535 f \n"); for (i=0; i < object; i++) (void) fprintf(image->file,"%010lu 00000 n \n",xref[i]); (void) fprintf(image->file,"trailer\n"); (void) fprintf(image->file,"<<\n"); (void) fprintf(image->file,"/Size %u\n",object+1); (void) fprintf(image->file,"/Info %u 0 R\n",info_id); (void) fprintf(image->file,"/Root %u 0 R\n",root_id); (void) fprintf(image->file,">>\n"); (void) fprintf(image->file,"startxref\n"); (void) fprintf(image->file,"%lu\n",length); (void) fprintf(image->file,"%%%%EOF\n"); free((char *) xref); CloseImage(image); if (image->temporary) { FILE *file; int c; /* Copy temporary file to standard output or pipe. */ file=fopen(image->filename,ReadBinaryType); if (file == (FILE *) NULL) PrematureExit("Unable to open file",image); c=fgetc(file); while (c != EOF) { (void) putc(c,encode_image.file); c=fgetc(file); } (void) fclose(file); (void) remove(image->filename); CloseImage(&encode_image); } return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P I C T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePICTImage writes an image to a file in the Apple Macintosh % QuickDraw/PICT image format. % % The format of the WritePICTImage routine is: % % status=WritePICTImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePICTImage 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 WritePICTImage(const ImageInfo *image_info,Image *image) { #define MaxCount 128 #define PictCropRegionOp 0x01 #define PictEndOfPictureOp 0xff #define PictHeaderOp 0x0C00 #define PictHeaderSize 512 #define PictPixmapOp 0x9A #define PictPICTOp 0x98 #define PictVersion 0x11 typedef struct _PICTRectangle { unsigned short top, left, bottom, right; } PICTRectangle; typedef struct _PICTPixmap { unsigned short base_address, row_bytes; PICTRectangle bounds; unsigned short version, pack_type; unsigned long pack_size, horizontal_resolution, vertical_resolution; unsigned short pixel_type, pixel_size, component_count, component_size; unsigned short plane_bytes, table, reserved; } PICTPixmap; int count; PICTPixmap pixmap; PICTRectangle crop_rectangle, destination_rectangle, frame_rectangle, size_rectangle, source_rectangle; register int i, j, x; register RunlengthPacket *p; unsigned char *buffer, *packed_scanline, *scanline; unsigned int bytes_per_line; unsigned short transfer_mode; unsigned long horizontal_resolution, vertical_resolution; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Allocate memory. */ bytes_per_line=image->columns; if (image->class == DirectClass) bytes_per_line*=3; buffer=(unsigned char *) malloc(PictHeaderSize*sizeof(unsigned char)); packed_scanline=(unsigned char *) malloc((bytes_per_line+bytes_per_line/MaxCount+1)*sizeof(unsigned char)); scanline=(unsigned char *) malloc(bytes_per_line*sizeof(unsigned char)); if ((buffer == (unsigned char *) NULL) || (packed_scanline == (unsigned char *) NULL) || (scanline == (unsigned char *) NULL)) PrematureExit("Unable to allocate memory",image); /* Initialize image info. */ size_rectangle.top=0; size_rectangle.left=0; size_rectangle.right=image->rows; size_rectangle.bottom=image->columns; frame_rectangle=size_rectangle; crop_rectangle=size_rectangle; source_rectangle=size_rectangle; destination_rectangle=size_rectangle; horizontal_resolution=0x00480000; vertical_resolution=0x00480000; pixmap.base_address=0xff; pixmap.row_bytes= ((image->class == DirectClass ? 4 : 1)*image->columns) | 0x8000; pixmap.version=0; pixmap.bounds.top=0; pixmap.bounds.left=0; pixmap.bounds.right=image->rows; pixmap.bounds.bottom=image->columns; pixmap.pack_type=(image->class == DirectClass ? 0x4 : 0x0); pixmap.pack_size=0; pixmap.horizontal_resolution=horizontal_resolution; pixmap.vertical_resolution=vertical_resolution; pixmap.pixel_type=(image->class == DirectClass ? 16 : 0); pixmap.pixel_size=(image->class == DirectClass ? 32 : 8); pixmap.component_count=(image->class == DirectClass ? 3 : 1); pixmap.component_size=8; pixmap.plane_bytes=0; pixmap.table=0; pixmap.reserved=0; transfer_mode=(image->class == DirectClass ? 0x40 : 0); /* Write header, header size, size bounding box, version, and reserved. */ for (i=0; i < PictHeaderSize; i++) buffer[i]=0; (void) fwrite((char *) buffer,1,PictHeaderSize,image->file); MSBFirstWriteShort(0,image->file); MSBFirstWriteShort(size_rectangle.top,image->file); MSBFirstWriteShort(size_rectangle.left,image->file); MSBFirstWriteShort(size_rectangle.right,image->file); MSBFirstWriteShort(size_rectangle.bottom,image->file); MSBFirstWriteShort(PictVersion,image->file); MSBFirstWriteShort(0x02ff,image->file); MSBFirstWriteShort(PictHeaderOp,image->file); /* Write full size of the file, resolution, frame bounding box, and reserved. */ MSBFirstWriteLong(0xFFFE0000L,image->file); MSBFirstWriteLong(horizontal_resolution,image->file); MSBFirstWriteLong(vertical_resolution,image->file); MSBFirstWriteShort(frame_rectangle.top,image->file); MSBFirstWriteShort(frame_rectangle.left,image->file); MSBFirstWriteShort(frame_rectangle.right,image->file); MSBFirstWriteShort(frame_rectangle.bottom,image->file); MSBFirstWriteLong(0x00000000L,image->file); /* Write crop region opcode and crop bounding box. */ MSBFirstWriteShort(PictCropRegionOp,image->file); MSBFirstWriteShort(0xa,image->file); MSBFirstWriteShort(crop_rectangle.top,image->file); MSBFirstWriteShort(crop_rectangle.left,image->file); MSBFirstWriteShort(crop_rectangle.right,image->file); MSBFirstWriteShort(crop_rectangle.bottom,image->file); /* Write picture opcode, row bytes, and picture bounding box, and version. */ if (image->class == PseudoClass) MSBFirstWriteShort(PictPICTOp,image->file); else { MSBFirstWriteShort(PictPixmapOp,image->file); MSBFirstWriteLong((unsigned long) pixmap.base_address,image->file); } MSBFirstWriteShort(pixmap.row_bytes | 0x8000,image->file); MSBFirstWriteShort(pixmap.bounds.top,image->file); MSBFirstWriteShort(pixmap.bounds.left,image->file); MSBFirstWriteShort(pixmap.bounds.right,image->file); MSBFirstWriteShort(pixmap.bounds.bottom,image->file); MSBFirstWriteShort(pixmap.version,image->file); /* Write pack type, pack size, resolution, pixel type, and pixel size. */ MSBFirstWriteShort(pixmap.pack_type,image->file); MSBFirstWriteLong(pixmap.pack_size,image->file); MSBFirstWriteLong(pixmap.horizontal_resolution,image->file); MSBFirstWriteLong(pixmap.vertical_resolution,image->file); MSBFirstWriteShort(pixmap.pixel_type,image->file); MSBFirstWriteShort(pixmap.pixel_size,image->file); /* Write component count, size, plane bytes, table size, and reserved. */ MSBFirstWriteShort(pixmap.component_count,image->file); MSBFirstWriteShort(pixmap.component_size,image->file); MSBFirstWriteLong((unsigned long) pixmap.plane_bytes,image->file); MSBFirstWriteLong((unsigned long) pixmap.table,image->file); MSBFirstWriteLong((unsigned long) pixmap.reserved,image->file); if (image->class == PseudoClass) { unsigned short red, green, blue; /* Write image colormap. */ MSBFirstWriteLong(0x00000000L,image->file); /* color seed */ MSBFirstWriteShort(0L,image->file); /* color flags */ MSBFirstWriteShort((unsigned short) (image->colors-1),image->file); for (i=0; i < image->colors; i++) { red=(unsigned int) (image->colormap[i].red*65535L)/MaxRGB; green=(unsigned int) (image->colormap[i].green*65535L)/MaxRGB; blue=(unsigned int) (image->colormap[i].blue*65535L)/MaxRGB; MSBFirstWriteShort((unsigned int) i,image->file); MSBFirstWriteShort(red,image->file); MSBFirstWriteShort(green,image->file); MSBFirstWriteShort(blue,image->file); } } /* Write source and destination rectangle. */ MSBFirstWriteShort(source_rectangle.top,image->file); MSBFirstWriteShort(source_rectangle.left,image->file); MSBFirstWriteShort(source_rectangle.right,image->file); MSBFirstWriteShort(source_rectangle.bottom,image->file); MSBFirstWriteShort(destination_rectangle.top,image->file); MSBFirstWriteShort(destination_rectangle.left,image->file); MSBFirstWriteShort(destination_rectangle.right,image->file); MSBFirstWriteShort(destination_rectangle.bottom,image->file); MSBFirstWriteShort(transfer_mode,image->file); /* Write picture data. */ count=0; x=0; p=image->pixels; if (image->class == PseudoClass) { register unsigned char *index; index=scanline; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *index++=(unsigned char) p->index; x++; if (x == image->columns) { count+=PICTEncodeImage(image,scanline,packed_scanline); index=scanline; x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } } else { register unsigned char *blue, *red, *green; red=scanline; green=scanline+image->columns; blue=scanline+(image->columns << 1); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *red++=DownScale(p->red); *green++=DownScale(p->green); *blue++=DownScale(p->blue); x++; if (x == image->columns) { red=scanline; green=scanline+image->columns; blue=scanline+(image->columns << 1); count+=PICTEncodeImage(image,red,packed_scanline); x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } } if (count & 0x1) (void) fputc('\0',image->file); MSBFirstWriteShort(PictEndOfPictureOp,image->file); free((char *) scanline); free((char *) packed_scanline); free((char *) buffer); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P L A S M A I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePLASMAImage writes an image in the plasma image format. % % The format of the WritePLASMAImage routine is: % % status=WritePLASMAImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePLASMAImage 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 WritePLASMAImage(const ImageInfo *image_info, Image *image) { unsigned int status; Warning("Cannot write PLASMA images",image->filename); status=WriteMIFFImage(image_info,image); return(status); } #ifdef HasPNG /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P N G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePNGImage writes an image in the Portable Network Graphics % encoded image format. % % The format of the WritePNGImage routine is: % % status=WritePNGImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePNGImage 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 PNGError(png_struct *ping,png_const_charp message) { Warning(message,(char *) NULL); longjmp(ping->jmpbuf,1); } static void PNGWarning(png_struct *ping,png_const_charp message) { Warning(message,(char *) NULL); } static unsigned int WritePNGImage(const ImageInfo *image_info,Image *image) { #define PNGTextChunk(i,keyword,value) \ { \ ping_info->text[i].key=(char *) malloc(strlen(keyword)+1); \ if (ping_info->text[i].key == (char *) NULL) \ PrematureExit("Unable to allocate memory",image); \ (void) strcpy(ping_info->text[i].key,keyword); \ ping_info->text[i].text=value; \ ping_info->text[i].text_length=Extent(value); \ ping_info->text[i].compression=Extent(value) > 1024 ? 0 : -1; \ i++; \ } register int i, j; register RunlengthPacket *p; register unsigned char *q; png_info *ping_info; png_struct *ping; unsigned char *png_pixels, **scanlines; unsigned int matte, scene, x, y; unsigned short value; /* Open image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); if (image_info->adjoin) { /* Write the MNG signature and MHDR chunk. */ (void) fwrite("\212MNG\r\n\032\n",1,8,image->file); MSBFirstWriteLong(0x0000000CL,image->file); (void) fwrite("MHDR",1,4,image->file); MSBFirstWriteLong(image->columns,image->file); MSBFirstWriteLong(image->rows,image->file); MSBFirstWriteLong(1,image->file); MSBFirstWriteLong(0xFFFFFFFFL,image->file); } scene=0; do { /* Allocate the PNG structures */ ping=png_create_write_struct(PNG_LIBPNG_VER_STRING,(void *) NULL,PNGError, PNGWarning); if (ping == (png_struct *) NULL) PrematureExit("Unable to allocate memory",image); ping_info=png_create_info_struct(ping); if (ping_info == (png_info *) NULL) { png_destroy_write_struct(&ping,(png_info **) NULL); PrematureExit("Unable to allocate memory",image); } png_init_io(ping,image->file); png_set_compression_level(ping,Z_BEST_COMPRESSION); png_pixels=(unsigned char *) NULL; scanlines=(unsigned char **) NULL; if (setjmp(ping->jmpbuf)) { /* PNG write failed. */ png_destroy_write_struct(&ping,&ping_info); if (scanlines != (unsigned char **) NULL) free((char *) scanlines); if (png_pixels != (unsigned char *) NULL) free((char *) png_pixels); CloseImage(image); return(False); } /* Prepare PNG for writing. */ ping_info->width=image->columns; ping_info->height=image->rows; ping_info->bit_depth=image->depth; ping_info->color_type=PNG_COLOR_TYPE_RGB; ping_info->valid|=PNG_INFO_pHYs; ping_info->phys_unit_type=PNG_RESOLUTION_UNKNOWN; ping_info->x_pixels_per_unit= (png_uint_32) image->x_resolution; ping_info->y_pixels_per_unit=(png_uint_32) image->y_resolution; if (image->units == PixelsPerInchResolution) { ping_info->phys_unit_type=PNG_RESOLUTION_METER; ping_info->x_pixels_per_unit=(png_uint_32) (100.0*image->x_resolution/2.54); ping_info->y_pixels_per_unit=(png_uint_32) (100.0*image->y_resolution/2.54); } if (image->units == PixelsPerCentimeterResolution) { ping_info->phys_unit_type=PNG_RESOLUTION_METER; ping_info->x_pixels_per_unit=(png_uint_32) (100.0*image->x_resolution); ping_info->y_pixels_per_unit=(png_uint_32) (100.0*image->y_resolution); } ping_info->valid|=PNG_INFO_bKGD; ping_info->background.red=DownScale(image->background_color.red); ping_info->background.green=DownScale(image->background_color.green); ping_info->background.blue=DownScale(image->background_color.blue); ping_info->background.gray=DownScale(Intensity(image->background_color)); ping_info->background.index=ping_info->background.gray; matte=image->matte; if (matte) { /* Determine if there is one and only one transparent color. */ ping_info->color_type=PNG_COLOR_TYPE_GRAY_ALPHA; p=image->pixels; for (i=0; (p->index == Opaque) && (i < (image->packets-1)); i++) { if (!IsGray(*p)) ping_info->color_type=PNG_COLOR_TYPE_RGB_ALPHA; p++; } if (p->index != Opaque) ping_info->valid|=PNG_INFO_tRNS; ping_info->trans_values.red=p->red; ping_info->trans_values.green=p->green; ping_info->trans_values.blue=p->blue; ping_info->trans_values.gray=Intensity(*p); ping_info->trans_values.index=DownScale(p->index); for ( ; i < image->packets; i++) { if (!IsGray(*p)) ping_info->color_type=PNG_COLOR_TYPE_RGB_ALPHA; if (p->index != ping_info->trans_values.index) if (ColorMatch(ping_info->trans_values,*p,0)) ping_info->valid&=(~PNG_INFO_tRNS); p++; } if (ping_info->valid & PNG_INFO_tRNS) { matte=False; ping_info->color_type=PNG_COLOR_TYPE_RGB; } } if (IsGrayImage(image)) ping_info->color_type=PNG_COLOR_TYPE_GRAY; else if (IsPseudoClass(image)) { /* Set image palette. */ ping_info->color_type=PNG_COLOR_TYPE_PALETTE; ping_info->num_palette=image->colors; ping_info->valid|=PNG_INFO_PLTE; ping_info->palette=(png_color *) malloc(image->colors*sizeof(png_color)); if (ping_info->palette == (png_color *) NULL) PrematureExit("Unable to allocate memory",image); for (i=0; i < image->colors; i++) { ping_info->palette[i].red=DownScale(image->colormap[i].red); ping_info->palette[i].green=DownScale(image->colormap[i].green); ping_info->palette[i].blue=DownScale(image->colormap[i].blue); } ping_info->bit_depth=1; while ((1 << ping_info->bit_depth) < image->colors) ping_info->bit_depth<<=1; if (ping_info->valid & PNG_INFO_tRNS) { /* Identify which colormap entry is transparent. */ ping_info->trans=(unsigned char *) malloc(image->colors*sizeof(unsigned char)); if (ping_info->trans == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); for (i=0; i < image->colors; i++) { ping_info->trans[i]=DownScale(Opaque); if (ColorMatch(ping_info->trans_values,image->colormap[i],0)) { ping_info->trans[i]=ping_info->trans_values.index; break; } } ping_info->num_trans=i+1; } /* Identify which colormap entry is the background color. */ for (i=0; i < (image->colors-1); i++) if (ColorMatch(ping_info->background,image->colormap[i],0)) break; ping_info->background.index=i; } if (image->gamma != 0.0) { /* Note image gamma. */ ping_info->valid|=PNG_INFO_gAMA; ping_info->gamma=image->gamma; } ping_info->interlace_type=image_info->interlace != NoneInterlace; if (image_info->adjoin) { /* Write the DEFI chunk. */ png_set_sig_bytes(ping,8); MSBFirstWriteLong(0x00000003L,image->file); (void) fwrite("DEFI",1,4,image->file); MSBFirstWriteShort(scene,image->file); (void) fputc(0x01,image->file); MSBFirstWriteLong(0xFFFFFFFFL,image->file); } png_write_info(ping,ping_info); png_set_packing(ping); /* Allocate memory. */ ping_info->rowbytes=image->columns; if (!IsPseudoClass(image)) ping_info->rowbytes*=(matte ? 4 : 3)*(image->depth >> 3); png_pixels=(unsigned char *) malloc(ping_info->rowbytes*image->rows*sizeof(Quantum)); scanlines=(unsigned char **) malloc(image->rows*sizeof(unsigned char *)); if ((png_pixels == (unsigned char *) NULL) || (scanlines == (unsigned char **) NULL)) PrematureExit("Unable to allocate memory",image); /* Initialize image scanlines. */ for (i=0; i < image->rows; i++) scanlines[i]=png_pixels+(ping_info->rowbytes*i); x=0; y=0; p=image->pixels; q=scanlines[y]; if (IsGrayImage(image)) for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { WriteQuantum(Intensity(*p),q); x++; if (x == image->columns) { x=0; y++; q=scanlines[y]; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } else if (!IsPseudoClass(image)) for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { WriteQuantum(p->red,q); if (ping_info->color_type != PNG_COLOR_TYPE_GRAY_ALPHA) { WriteQuantum(p->green,q); WriteQuantum(p->blue,q); } if (matte) WriteQuantum(p->index,q); x++; if (x == image->columns) { x=0; y++; if (y < image->rows) q=scanlines[y]; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } else 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++; if (y < image->rows) q=scanlines[y]; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } png_write_image(ping,scanlines); /* Generate text chunks. */ ping_info->num_text=0; ping_info->text=(png_text *) malloc(256*sizeof(png_text)); if (ping_info->text == (png_text *) NULL) PrematureExit("Unable to allocate memory",image); PNGTextChunk(ping_info->num_text,"Software",Version); SignatureImage(image); if (image->signature != (char *) NULL) PNGTextChunk(ping_info->num_text,"Signature",image->signature); if (image->scene != 0) { char scene[MaxTextExtent]; (void) sprintf(scene,"%u",image->scene); PNGTextChunk(ping_info->num_text,"Scene",scene); } if (image->delay != 0) { char delay[MaxTextExtent]; (void) sprintf(delay,"%u",image->delay); PNGTextChunk(ping_info->num_text,"Delay",delay); } if (image->label != (char *) NULL) PNGTextChunk(ping_info->num_text,"Label",image->label); if (image->montage != (char *) NULL) PNGTextChunk(ping_info->num_text,"Montage",image->montage); if (image->directory != (char *) NULL) PNGTextChunk(ping_info->num_text,"Directory",image->directory); if (image->comments != (char *) NULL) PNGTextChunk(ping_info->num_text,"Comment",image->comments); png_write_end(ping,ping_info); png_destroy_write_struct(&ping,&ping_info); if (image->next == (Image *) NULL) break; image->next->file=image->file; image=image->next; ProgressMonitor(SaveImageText,scene++,image->number_scenes); } while (image_info->adjoin); if (image_info->adjoin) { /* Write the MEND chunk. */ MSBFirstWriteLong(0x00000000L,image->file); (void) fwrite("MEND",1,4,image->file); MSBFirstWriteLong(0xFFFFFFFFL,image->file); } /* Free memory. */ CloseImage(image); return(True); } #else static unsigned int WritePNGImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("PNG library is not available",image->filename); status=WriteMIFFImage(image_info,image); return(status); } #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P N M I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure WritePNMImage writes an image to a file in the PNM rasterfile % format. % % The format of the WritePNMImage routine is: % % status=WritePNMImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePNMImage 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 WritePNMImage(const ImageInfo *image_info,Image *image) { #define MaxRawValue 255 register int i, j; register RunlengthPacket *p; unsigned char format; unsigned int scene, x; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); scene=0; do { /* Promote/Demote image based on image type. */ if (strcmp(image_info->magick,"PPM") == 0) image->class=DirectClass; else if (strcmp(image_info->magick,"PGM") == 0) RGBTransformImage(image,GRAYColorspace); else if (strcmp(image_info->magick,"PBM") == 0) 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); } /* Write PNM file header. */ image->compression=image_info->compression; if (!IsPseudoClass(image) && !IsGrayImage(image)) { /* Full color PNM image. */ format='6'; if ((image->compression == NoCompression) || (MaxRGB > MaxRawValue)) format='3'; } else { /* Colormapped PNM image. */ format='6'; if ((image->compression == NoCompression) || (MaxRGB > MaxRawValue)) format='3'; if ((strcmp(image_info->magick,"PPM") != 0) && IsGrayImage(image)) { /* Grayscale PNM image. */ format='5'; if ((image->compression == NoCompression) || (MaxRGB > MaxRawValue)) format='2'; if (strcmp(image_info->magick,"PGM") != 0) if (image->colors == 2) { format='4'; if (image->compression == NoCompression) format='1'; } } } if (strcmp(image_info->magick,"P7") == 0) { format='7'; (void) fprintf(image->file,"P7 332\n"); } else (void) fprintf(image->file,"P%c\n",format); if (image->comments != (char *) NULL) { register char *p; /* Write comments to file. */ (void) fprintf(image->file,"#"); for (p=image->comments; *p != '\0'; p++) { (void) fputc(*p,image->file); if (*p == '\n') (void) fprintf(image->file,"#"); } (void) fputc('\n',image->file); } if (format != '7') (void) fprintf(image->file,"%u %u\n",image->columns,image->rows); /* Convert runlength encoded to PNM raster pixels. */ x=0; p=image->pixels; switch (format) { case '1': { register unsigned char polarity; /* Convert image to a PBM image. */ polarity=0; if (image->colors == 2) polarity= Intensity(image->colormap[0]) > Intensity(image->colormap[1]); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { (void) fprintf(image->file,"%d ",(int) (p->index == polarity)); x++; if (x == 36) { (void) fprintf(image->file,"\n"); x=0; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case '2': { /* Convert image to a PGM image. */ (void) fprintf(image->file,"%d\n",MaxRGB); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { (void) fprintf(image->file,"%d ",p->red); x++; if (x == 12) { (void) fprintf(image->file,"\n"); x=0; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case '3': { /* Convert image to a PNM image. */ (void) fprintf(image->file,"%d\n",MaxRGB); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { (void) fprintf(image->file,"%d %d %d ",p->red,p->green,p->blue); x++; if (x == 4) { (void) fprintf(image->file,"\n"); x=0; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case '4': { register unsigned char bit, byte, polarity; /* Convert image to a PBM image. */ polarity=0; if (image->colors == 2) polarity= Intensity(image->colormap[0]) > Intensity(image->colormap[1]); bit=0; byte=0; x=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) { (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) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case '5': { /* Convert image to a PGM image. */ (void) fprintf(image->file,"%u\n",DownScale(MaxRGB)); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) (void) fputc(DownScale(p->red),image->file); p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case '6': { /* Convert image to a PNM image. */ (void) fprintf(image->file,"%u\n",DownScale(MaxRGB)); 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); } break; } case '7': { static short int dither_red[2][16]= { {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8}, { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9} }, dither_green[2][16]= { { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1}, {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0} }, dither_blue[2][16]= { { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4}, { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5} }; int value, y; Quantum pixel; unsigned short *blue_map[2][16], *green_map[2][16], *red_map[2][16]; if (!UncompressImage(image)) break; /* Allocate and initialize dither maps. */ for (i=0; i < 2; i++) for (j=0; j < 16; j++) { red_map[i][j]=(unsigned short *) malloc(256*sizeof(unsigned short)); green_map[i][j]=(unsigned short *) malloc(256*sizeof(unsigned short)); blue_map[i][j]=(unsigned short *) malloc(256*sizeof(unsigned short)); if ((red_map[i][j] == (unsigned short *) NULL) || (green_map[i][j] == (unsigned short *) NULL) || (blue_map[i][j] == (unsigned short *) NULL)) { Warning("Unable to dither image","Memory allocation failed"); break; } } /* Initialize dither tables. */ for (i=0; i < 2; i++) for (j=0; j < 16; j++) for (x=0; x < 256; x++) { value=x-16; if (x < 48) value=x/2+8; value+=dither_red[i][j]; red_map[i][j][x]=(unsigned short) ((value < 0) ? 0 : (value > MaxRGB) ? MaxRGB : value); value=x-16; if (x < 48) value=x/2+8; value+=dither_green[i][j]; green_map[i][j][x]=(unsigned short) ((value < 0) ? 0 : (value > MaxRGB) ? MaxRGB : value); value=x-32; if (x < 112) value=x/2+24; value+=(dither_blue[i][j] << 1); blue_map[i][j][x]=(unsigned short) ((value < 0) ? 0 : (value > MaxRGB) ? MaxRGB : value); } /* Convert image to a P7 image. */ (void) fprintf(image->file,"#END_OF_COMMENTS\n"); (void) fprintf(image->file,"%u %u %d\n",image->columns,image->rows, MaxRGB); i=0; j=0; p=image->pixels; for (y=0; y < image->rows; y++) { for (x=0; x < image->columns; x++) { pixel=(Quantum) ((red_map[i][j][p->red] & 0xe0) | ((green_map[i][j][p->green] & 0xe0) >> 3) | ((blue_map[i][j][p->blue] & 0xc0) >> 6)); WriteQuantumFile(pixel); p++; j++; if (j == 16) j=0; } i++; if (i == 2) i=0; ProgressMonitor(SaveImageText,y,image->rows); } /* Free allocated memory. */ for (i=0; i < 2; i++) for (j=0; j < 16; j++) { free((char *) green_map[i][j]); free((char *) blue_map[i][j]); free((char *) red_map[i][j]); } 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 P R E V I E W I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePREVIEWImage creates several tiles each with a varying % stength of an image enhancement function (e.g. gamma). The image is written % in the MIFF format. % % The format of the WritePREVIEWImage routine is: % % status=WritePREVIEWImage(image_info,image) % % A description of each parameter follows. % % o status: Function WritePREVIEWImage 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 WritePREVIEWImage(const ImageInfo *image_info, Image *image) { #define NumberTiles 9 #define PreviewImageText " Creating image preview... " char *commands[NumberTiles+6], factor[MaxTextExtent], label[MaxTextExtent], *resource_value; Display *display; float degrees, gamma, percentage, threshold; Image *images[NumberTiles], *montage_image, *preview_image; ImageInfo local_info; int argc, x, y; MonitorHandler handler; register int i; unsigned int colors, height, status, width; XMontageInfo montage_info; XResourceInfo resource_info; XrmDatabase resource_database; /* Scale the image to tile size. */ image->orphan=True; width=image->columns; height=image->rows; (void) ParseImageGeometry(DefaultPreviewGeometry,&x,&y,&width,&height); if (image->class == PseudoClass) preview_image=SampleImage(image,width,height); else preview_image=ZoomImage(image,width,height,MitchellFilter); image->orphan=False; if (preview_image == (Image *) NULL) PrematureExit("Unable to allocate memory",image); LabelImage(preview_image,DefaultTileLabel); /* Apply enhancement at varying strengths. */ local_info=(*image_info); degrees=0; gamma=(-0.1); colors=2; x=0; y=0; percentage=0.0; threshold=0.0; commands[0]=client_name; for (i=0; i < NumberTiles; i++) { images[i]= CloneImage(preview_image,preview_image->columns,preview_image->rows,True); if (images[i] == (Image *) NULL) { for (x=0; x < i; x++) DestroyImage(images[x]); PrematureExit("Unable to allocate memory",image); } argc=1; if (i == (NumberTiles >> 1)) { commands[argc++]="-mattecolor"; commands[argc++]=DefaultPreviewMatte; MogrifyImage(&local_info,argc,commands,&images[i]); continue; } handler=SetMonitorHandler((MonitorHandler) NULL); switch (image_info->preview_type) { case RotatePreview: { (void) sprintf(factor,"%.1f",degrees+=45.0); (void) sprintf(label,"rotate %s",factor); commands[argc++]="-rotate"; commands[argc++]=factor; commands[argc++]="-crop"; commands[argc++]="0x0"; break; } case ShearPreview: { degrees+=10.0; (void) sprintf(factor,"%.1fx%.1f",degrees,2.0*degrees); (void) sprintf(label,"shear %s",factor); commands[argc++]="-shear"; commands[argc++]=factor; commands[argc++]="-crop"; commands[argc++]="0x0"; break; } case RollPreview: { x+=preview_image->columns/NumberTiles; y+=preview_image->rows/NumberTiles; (void) sprintf(factor,"%+d%+d",x,y); (void) sprintf(label,"roll %s",factor); commands[argc++]="-roll"; commands[argc++]=factor; break; } case HuePreview: { (void) sprintf(factor,"0,0,%.1f",percentage+=12.5); (void) sprintf(label,"modulate %s",factor); commands[argc++]="-modulate"; commands[argc++]=factor; break; } case SaturationPreview: { (void) sprintf(factor,"0,%.1f",percentage+=12.5); (void) sprintf(label,"modulate %s",factor); commands[argc++]="-modulate"; commands[argc++]=factor; break; } case BrightnessPreview: { (void) sprintf(factor,"%.1f",percentage+=12.5); (void) sprintf(label,"modulate %s",factor); commands[argc++]="-modulate"; commands[argc++]=factor; break; } case GammaPreview: default: { (void) sprintf(factor,"%.1f",gamma+=0.4); (void) sprintf(label,"gamma %s",factor); commands[argc++]="-gamma"; commands[argc++]=factor; break; } case SpiffPreview: { for (x=0; x < i; x++) commands[argc++]="-contrast"; (void) sprintf(label,"-contast %d",i+1); break; } case DullPreview: { for (x=0; x < i; x++) commands[argc++]="+contrast"; (void) sprintf(label,"+contast %d",i+1); break; } case GrayscalePreview: { (void) sprintf(factor,"%u",colors); colors<<=1; (void) sprintf(label,"colors %s",factor); commands[argc++]="-colorspace"; commands[argc++]="gray"; commands[argc++]="-colors"; commands[argc++]=factor; break; } case QuantizePreview: { (void) sprintf(factor,"%u",colors<<=1); (void) sprintf(label,"colors %s",factor); commands[argc++]="-colors"; commands[argc++]=factor; break; } case DespecklePreview: { for (x=0; x < i; x++) commands[argc++]="-despeckle"; (void) sprintf(label,"despeckle %d",i+1); break; } case ReduceNoisePreview: { for (x=0; x < i; x++) commands[argc++]="-noise"; (void) sprintf(label,"noise %d",i+1); break; } case AddNoisePreview: { switch (x) { case 0: (void) strcpy(factor,"uniform"); break; case 1: (void) strcpy(factor,"gaussian"); break; case 2: (void) strcpy(factor,"multiplicative"); break; case 3: (void) strcpy(factor,"impulse"); break; case 4: (void) strcpy(factor,"laplacian"); break; case 5: (void) strcpy(factor,"poisson"); break; default: (void) strcpy(images[i]->magick,"NULL"); break; } x++; (void) sprintf(label,"+noise %s",factor); commands[argc++]="+noise"; commands[argc++]=factor; break; } case SharpenPreview: { (void) sprintf(factor,"%.1f",percentage+=12.5); (void) sprintf(label,"sharpen %s",factor); commands[argc++]="-sharpen"; commands[argc++]=factor; break; } case BlurPreview: { (void) sprintf(factor,"%.1f",percentage+=12.5); (void) sprintf(label,"+sharpen %s",factor); commands[argc++]="+sharpen"; commands[argc++]=factor; break; } case ThresholdPreview: { (void) sprintf(factor,"%d",(int) ((percentage*(MaxRGB+1))/100)); (void) sprintf(label,"threshold %s",factor); commands[argc++]="-threshold"; commands[argc++]=factor; percentage+=12.5; break; } case EdgeDetectPreview: { (void) sprintf(factor,"%.1f",percentage+=12.5); (void) sprintf(label,"edge %s",factor); commands[argc++]="-edge"; commands[argc++]=factor; break; } case SpreadPreview: { (void) sprintf(factor,"%d",i+1); (void) sprintf(label,"spread %s",factor); commands[argc++]="-spread"; commands[argc++]=factor; break; } case SolarizePreview: { (void) sprintf(factor,"%.1f",percentage+=12.5); (void) sprintf(label,"solarize %s",factor); commands[argc++]="-solarize"; commands[argc++]=factor; break; } case ShadePreview: { if (i == 0) { (void) strcpy(label,"+shade"); commands[argc++]="+shade"; break; } degrees+=10.0; (void) sprintf(factor,"%.1fx%.1f",degrees,degrees); (void) sprintf(label,"shade %s",factor); commands[argc++]="-shade"; commands[argc++]=factor; break; } case RaisePreview: { (void) sprintf(factor,"%d",i+1); (void) sprintf(label,"raise %s",factor); commands[argc++]="-raise"; commands[argc++]=factor; break; } case SegmentPreview: { (void) sprintf(factor,"1.5x%.1f",threshold+=0.4); (void) sprintf(label,"segment %s",factor); commands[argc++]="-colors"; commands[argc++]=factor; break; } case SwirlPreview: { (void) sprintf(factor,"%.1f",degrees+=45.0); (void) sprintf(label,"swirl %s",factor); commands[argc++]="-swirl"; commands[argc++]=factor; break; } case ImplodePreview: { (void) sprintf(factor,"%.1f",percentage+=12.5); (void) sprintf(label,"implode %s",factor); commands[argc++]="-implode"; commands[argc++]=factor; break; } case WavePreview: { degrees+=5.0; (void) sprintf(factor,"%.1fx%.1f",degrees,degrees); (void) sprintf(label,"wave %s",factor); commands[argc++]="-implode"; commands[argc++]=factor; break; } case OilPaintPreview: { (void) sprintf(factor,"%i",i+1); (void) sprintf(label,"paint %s",factor); commands[argc++]="-paint"; commands[argc++]=factor; break; } case CharcoalDrawingPreview: { (void) sprintf(factor,"%.1f",percentage+=12.5); (void) sprintf(label,"charcoal %s",factor); commands[argc++]="-charcoal"; commands[argc++]=factor; break; } } commands[argc++]="-label"; commands[argc++]=label; MogrifyImage(&local_info,argc,commands,&images[i]); (void) SetMonitorHandler(handler); ProgressMonitor(PreviewImageText,i,NumberTiles); } DestroyImage(preview_image); /* Get user defaults from X resource database. */ XGetMontageInfo(&montage_info); display=XOpenDisplay(image_info->server_name); if (display != (Display *) NULL) XSetErrorHandler(XError); resource_database=XGetResourceDatabase(display,client_name); XGetResourceInfo(resource_database,client_name,&resource_info); resource_info.background_color=XGetResourceInstance(resource_database, client_name,"background",DefaultTileBackground); resource_info.foreground_color=XGetResourceInstance(resource_database, client_name,"foreground",DefaultTileForeground); montage_info.frame=XGetResourceClass(resource_database,client_name,"frame", DefaultTileFrame); resource_info.image_geometry=XGetResourceInstance(resource_database, client_name,"imageGeometry",DefaultPreviewGeometry); resource_info.matte_color=XGetResourceInstance(resource_database,client_name, "mattecolor",DefaultTileMatte); resource_value=XGetResourceClass(resource_database,client_name,"pointsize", DefaultPointSize); montage_info.pointsize=atoi(resource_value); resource_value= XGetResourceClass(resource_database,client_name,"shadow","True"); montage_info.shadow=IsTrue(resource_value); montage_info.texture=XGetResourceClass(resource_database,client_name, "texture","granite:"); montage_info.tile=XGetResourceClass(resource_database,client_name,"tile", DefaultPreviewPageGeometry); if (display != (Display *) NULL) XCloseDisplay(display); /* Create the PCD Overview image. */ for (i=1; i < NumberTiles; i++) { images[i]->previous=images[i-1]; images[i-1]->next=images[i]; } (void) strcpy(montage_info.filename,image_info->filename); montage_image=XMontageImages(&resource_info,&montage_info,*images); for (i=0; i < i; i++) DestroyImage(images[i]); if (montage_image == (Image *) NULL) PrematureExit("Unable to allocate memory",image); if (montage_image->montage != (char *) NULL) { /* Free image directory. */ free(montage_image->montage); montage_image->montage=(char *) NULL; if (image->directory != (char *) NULL) { free(montage_image->directory); montage_image->directory=(char *) NULL; } } status=WriteMIFFImage(image_info,montage_image); DestroyImage(montage_image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePSImage translates an image to encapsulated Postscript % Level I for printing. If the supplied geometry is null, the image is % centered on the Postscript page. Otherwise, the image is positioned as % specified by the geometry. % % The format of the WritePSImage routine is: % % status=WritePSImage(image_info,image) % % A description of each parameter follows: % % o status: Function WritePSImage return True if the image is printed. % False is returned if the image file cannot be opened for printing. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ static unsigned int WritePSImage(const ImageInfo *image_info,Image *image) { static char *Postscript[]= { "%%BeginProlog", "%", "% Display a color image. The image is displayed in color on", "% Postscript viewers or printers that support color, otherwise", "% it is displayed as grayscale.", "%", "/buffer 512 string def", "/byte 1 string def", "/color_packet 3 string def", "/pixels 768 string def", "", "/DirectClassPacket", "{", " %", " % Get a DirectClass packet.", " %", " % Parameters:", " % red.", " % green.", " % blue.", " % length: number of pixels minus one of this color (optional).", " %", " currentfile color_packet readhexstring pop pop", " compression 0 gt", " {", " /number_pixels 3 def", " }", " {", " currentfile byte readhexstring pop 0 get", " /number_pixels exch 1 add 3 mul def", " } ifelse", " 0 3 number_pixels 1 sub", " {", " pixels exch color_packet putinterval", " } for", " pixels 0 number_pixels getinterval", "} bind def", "", "/DirectClassImage", "{", " %", " % Display a DirectClass image.", " %", " systemdict /colorimage known", " {", " columns rows 8", " [", " columns 0 0", " rows neg 0 rows", " ]", " { DirectClassPacket } false 3 colorimage", " }", " {", " %", " % No colorimage operator; convert to grayscale.", " %", " columns rows 8", " [", " columns 0 0", " rows neg 0 rows", " ]", " { GrayDirectClassPacket } image", " } ifelse", "} bind def", "", "/GrayDirectClassPacket", "{", " %", " % Get a DirectClass packet; convert to grayscale.", " %", " % Parameters:", " % red", " % green", " % blue", " % length: number of pixels minus one of this color (optional).", " %", " currentfile color_packet readhexstring pop pop", " color_packet 0 get 0.299 mul", " color_packet 1 get 0.587 mul add", " color_packet 2 get 0.114 mul add", " cvi", " /gray_packet exch def", " compression 0 gt", " {", " /number_pixels 1 def", " }", " {", " currentfile byte readhexstring pop 0 get", " /number_pixels exch 1 add def", " } ifelse", " 0 1 number_pixels 1 sub", " {", " pixels exch gray_packet put", " } for", " pixels 0 number_pixels getinterval", "} bind def", "", "/GrayPseudoClassPacket", "{", " %", " % Get a PseudoClass packet; convert to grayscale.", " %", " % Parameters:", " % index: index into the colormap.", " % length: number of pixels minus one of this color (optional).", " %", " currentfile byte readhexstring pop 0 get", " /offset exch 3 mul def", " /color_packet colormap offset 3 getinterval def", " color_packet 0 get 0.299 mul", " color_packet 1 get 0.587 mul add", " color_packet 2 get 0.114 mul add", " cvi", " /gray_packet exch def", " compression 0 gt", " {", " /number_pixels 1 def", " }", " {", " currentfile byte readhexstring pop 0 get", " /number_pixels exch 1 add def", " } ifelse", " 0 1 number_pixels 1 sub", " {", " pixels exch gray_packet put", " } for", " pixels 0 number_pixels getinterval", "} bind def", "", "/PseudoClassPacket", "{", " %", " % Get a PseudoClass packet.", " %", " % Parameters:", " % index: index into the colormap.", " % length: number of pixels minus one of this color (optional).", " %", " currentfile byte readhexstring pop 0 get", " /offset exch 3 mul def", " /color_packet colormap offset 3 getinterval def", " compression 0 gt", " {", " /number_pixels 3 def", " }", " {", " currentfile byte readhexstring pop 0 get", " /number_pixels exch 1 add 3 mul def", " } ifelse", " 0 3 number_pixels 1 sub", " {", " pixels exch color_packet putinterval", " } for", " pixels 0 number_pixels getinterval", "} bind def", "", "/PseudoClassImage", "{", " %", " % Display a PseudoClass image.", " %", " % Parameters:", " % class: 0-PseudoClass or 1-Grayscale.", " %", " currentfile buffer readline pop", " token pop /class exch def pop", " class 0 gt", " {", " currentfile buffer readline pop", " token pop /depth exch def pop", " /grays columns 8 add depth sub depth mul 8 idiv string def", " columns rows depth", " [", " columns 0 0", " rows neg 0 rows", " ]", " { currentfile grays readhexstring pop } image", " }", " {", " %", " % Parameters:", " % colors: number of colors in the colormap.", " % colormap: red, green, blue color packets.", " %", " currentfile buffer readline pop", " token pop /colors exch def pop", " /colors colors 3 mul def", " /colormap colors string def", " currentfile colormap readhexstring pop pop", " systemdict /colorimage known", " {", " columns rows 8", " [", " columns 0 0", " rows neg 0 rows", " ]", " { PseudoClassPacket } false 3 colorimage", " }", " {", " %", " % No colorimage operator; convert to grayscale.", " %", " columns rows 8", " [", " columns 0 0", " rows neg 0 rows", " ]", " { GrayPseudoClassPacket } image", " } ifelse", " } ifelse", "} bind def", "", "/DisplayImage", "{", " %", " % Display a DirectClass or PseudoClass image.", " %", " % Parameters:", " % x & y translation.", " % x & y scale.", " % label pointsize.", " % image label.", " % image columns & rows.", " % class: 0-DirectClass or 1-PseudoClass.", " % compression: 0-RunlengthEncodedCompression or 1-NoCompression.", " % hex color packets.", " %", " gsave", " currentfile buffer readline pop", " token pop /x exch def", " token pop /y exch def pop", " x y translate", " currentfile buffer readline pop", " token pop /x exch def", " token pop /y exch def pop", " currentfile buffer readline pop", " token pop /pointsize exch def pop", " /NewCenturySchlbk-Roman findfont pointsize scalefont setfont", "^", " x y scale", " currentfile buffer readline pop", " token pop /columns exch def", " token pop /rows exch def pop", " currentfile buffer readline pop", " token pop /class exch def pop", " currentfile buffer readline pop", " token pop /compression exch def pop", " class 0 gt { PseudoClassImage } { DirectClassImage } ifelse", " grestore", (char *) NULL }; char date[MaxTextExtent], density[MaxTextExtent], **labels, **q; float dx_resolution, dy_resolution, x_resolution, y_resolution; int length, x, y; register RunlengthPacket *p; register int i, j; time_t timer; unsigned int bit, byte, count, height, page, polarity, scene, text_size, width; XSegment bounding_box; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); page=1; scene=0; do { /* Scale image to size of Postscript 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; if (strcmp(image_info->magick,"PS") == 0) { int delta_x, delta_y, flags; unsigned int page_height, page_width; /* Center image on Postscript page. */ (void) XParseGeometry(PSPageGeometry,&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 Postscript 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; } } /* Scale relative to dots-per-inch. */ dx_resolution=72.0; dy_resolution=72.0; x_resolution=72.0; (void) strcpy(density,PSDensityGeometry); count=sscanf(density,"%fx%f",&x_resolution,&y_resolution); if (image_info->density != (char *) NULL) count=sscanf(image_info->density,"%fx%f",&x_resolution,&y_resolution); if (count != 2) y_resolution=x_resolution; width=(unsigned int) (((width*dx_resolution)/x_resolution)+0.5); height=(unsigned int) (((height*dy_resolution)/y_resolution)+0.5); if (page == 1) { /* Output Postscript header. */ if (strcmp(image_info->magick,"PS") == 0) (void) fprintf(image->file,"%%!PS-Adobe-3.0\n"); else (void) fprintf(image->file,"%%!PS-Adobe-3.0 EPSF-3.0\n"); (void) fprintf(image->file,"%%%%Creator: (ImageMagick)\n"); (void) fprintf(image->file,"%%%%Title: (%s)\n",image->filename); timer=time((time_t *) NULL); (void) localtime(&timer); (void) strcpy(date,ctime(&timer)); date[Extent(date)-1]='\0'; (void) fprintf(image->file,"%%%%CreationDate: (%s)\n",date); bounding_box.x1=x; bounding_box.y1=y; bounding_box.x2=x+(int) width-1; bounding_box.y2=y+(int) (height+text_size)-1; if (image_info->adjoin && (image->next != (Image *) NULL)) (void) fprintf(image->file,"%%%%BoundingBox: (atend)\n"); else (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n", bounding_box.x1,bounding_box.y1,bounding_box.x2,bounding_box.y2); if (image->label != (char *) NULL) (void) fprintf(image->file, "%%%%DocumentNeededResources: font NewCenturySchlbk-Roman\n"); (void) fprintf(image->file,"%%%%DocumentData: Clean7Bit\n"); (void) fprintf(image->file,"%%%%LanguageLevel: 1\n"); if (strcmp(image_info->magick,"PS") != 0) (void) fprintf(image->file,"%%%%Pages: 0\n"); else { Image *next_image; unsigned int pages; /* Compute the number of pages. */ (void) fprintf(image->file,"%%%%Orientation: Portrait\n"); (void) fprintf(image->file,"%%%%PageOrder: Ascend\n"); pages=1; if (image_info->adjoin) for (next_image=image->next; next_image != (Image *) NULL; ) { next_image=next_image->next; pages++; } (void) fprintf(image->file,"%%%%Pages: %u\n",pages); } (void) fprintf(image->file,"%%%%EndComments\n"); (void) fprintf(image->file,"\n%%%%BeginDefaults\n"); (void) fprintf(image->file,"%%%%PageOrientation: Portrait\n"); (void) fprintf(image->file,"%%%%EndDefaults\n\n"); if (strcmp(image_info->magick,"EPSI") == 0) { Image *preview_image; /* Create preview image. */ image->orphan=True; preview_image=CloneImage(image,image->columns,image->rows,True); image->orphan=False; if (preview_image == (Image *) NULL) PrematureExit("Unable to allocate memory",image); /* Dump image as bitmap. */ if (!IsMonochromeImage(preview_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,preview_image); SyncImage(preview_image); } polarity=0; if (image->colors == 2) polarity= Intensity(image->colormap[0]) > Intensity(image->colormap[1]); bit=0; byte=0; count=0; x=0; p=preview_image->pixels; (void) fprintf(image->file,"%%%%BeginPreview: %u %u %u %u\n%% ", preview_image->columns,preview_image->rows,(unsigned int) 1, (((preview_image->columns+7) >> 3)*preview_image->rows+35)/36); for (i=0; i < preview_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { byte<<=1; if (p->index == polarity) byte|=0x01; bit++; if (bit == 8) { (void) fprintf(image->file,"%02x",byte & 0xff); count++; if (count == 36) { (void) fprintf(image->file,"\n%% "); count=0; }; bit=0; byte=0; } x++; if (x == preview_image->columns) { if (bit != 0) { byte<<=(8-bit); (void) fprintf(image->file,"%02x",byte & 0xff); count++; if (count == 36) { (void) fprintf(image->file,"\n%% "); count=0; }; bit=0; byte=0; }; x=0; } } p++; } (void) fprintf(image->file,"\n%%%%EndPreview\n"); DestroyImage(preview_image); } /* Output Postscript commands. */ for (q=Postscript; *q; q++) { if (*(*q) != '^') { (void) fprintf(image->file,"%s\n",*q); continue; } for (i=MultilineCensus(image->label)-1; i >= 0; i--) { (void) fprintf(image->file," /label 512 string def\n"); (void) fprintf(image->file," currentfile label readline pop\n"); (void) fprintf(image->file," 0 y %d add moveto label show pop\n", i*image_info->pointsize+12); } } if (strcmp(image_info->magick,"PS") == 0) (void) fprintf(image->file," showpage\n"); (void) fprintf(image->file,"} bind def\n"); (void) fprintf(image->file,"%%%%EndProlog\n"); } (void) fprintf(image->file,"%%%%Page: 1 %u\n",page++); (void) fprintf(image->file,"%%%%PageBoundingBox: %d %d %d %d\n",x,y, x+(int) width-1,y+(int) (height+text_size)-1); if (x < bounding_box.x1) bounding_box.x1=x; if (y < bounding_box.y1) bounding_box.y1=y; if ((x+(int) width-1) > bounding_box.x2) bounding_box.x2=x+(int) width-1; if ((y+(int) (height+text_size)-1) > bounding_box.y2) bounding_box.y2=y+(int) (height+text_size)-1; if (image->label != (char *) NULL) (void) fprintf(image->file, "%%%%PageResources: font NewCenturySchlbk-Roman\n"); if (strcmp(image_info->magick,"PS") != 0) (void) fprintf(image->file,"userdict begin\n"); (void) fprintf(image->file,"%%%%BeginData:\n"); (void) fprintf(image->file,"DisplayImage\n"); /* Output image data. */ labels=StringToList(image->label); image->compression=image_info->compression; CompressImage(image); (void) fprintf(image->file,"%d %d\n%u %u\n%u\n",x,y,width,height, image_info->pointsize); if (labels != (char **) NULL) { for (i=0; labels[i] != (char *) NULL; i++) { (void) fprintf(image->file,"%s \n",labels[i]); free(labels[i]); } free(labels); } x=0; p=image->pixels; if (!IsPseudoClass(image) && !IsGrayImage(image)) { /* Dump DirectClass image. */ (void) fprintf(image->file,"%u %u\n%d\n%d\n", image->columns,image->rows,(int) (image->class == PseudoClass), (int) (image->compression == NoCompression)); switch (image->compression) { case RunlengthEncodedCompression: default: { /* Dump runlength-encoded DirectColor packets. */ for (i=0; i < image->packets; i++) { for (length=p->length; length >= 0; length-=256) { if (image->matte && (p->index == Transparent)) (void) fprintf(image->file,"ffffff%02x",(unsigned int) Min(length,0xff)); else (void) fprintf(image->file,"%02x%02x%02x%02x", DownScale(p->red),DownScale(p->green),DownScale(p->blue), (unsigned int) Min(length,0xff)); x++; if (x == 9) { x=0; (void) fprintf(image->file,"\n"); } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case NoCompression: { /* Dump uncompressed DirectColor packets. */ for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (image->matte && (p->index == Transparent)) (void) fprintf(image->file,"ffffff"); else (void) fprintf(image->file,"%02x%02x%02x",DownScale(p->red), DownScale(p->green),DownScale(p->blue)); x++; if (x == 12) { x=0; (void) fprintf(image->file,"\n"); } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } } (void) fprintf(image->file,"\n"); } else if (IsGrayImage(image)) { (void) fprintf(image->file,"%u %u\n1\n1\n1\n%d\n", image->columns,image->rows,IsMonochromeImage(image) ? 1 : 8); if (!IsMonochromeImage(image)) { /* Dump image as grayscale. */ for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { (void) fprintf(image->file,"%02x",DownScale(p->red)); x++; if (x == 36) { x=0; (void) fprintf(image->file,"\n"); } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } else { /* Dump image as bitmap. */ polarity= Intensity(image->colormap[1]) > Intensity(image->colormap[0]); bit=0; byte=0; count=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) { (void) fprintf(image->file,"%02x",byte & 0xff); count++; if (count == 36) { (void) fprintf(image->file,"\n"); count=0; }; bit=0; byte=0; } x++; if (x == image->columns) { /* Advance to the next scanline. */ if (bit != 0) { byte<<=(8-bit); (void) fprintf(image->file,"%02x",byte & 0xff); count++; if (count == 36) { (void) fprintf(image->file,"\n"); count=0; }; }; bit=0; byte=0; x=0; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } if (count != 0) (void) fprintf(image->file,"\n"); } else { /* Dump PseudoClass image. */ (void) fprintf(image->file,"%u %u\n%d\n%d\n0\n", image->columns,image->rows,(int) (image->class == PseudoClass), (int) (image->compression == NoCompression)); /* Dump number of colors and colormap. */ (void) fprintf(image->file,"%u\n",image->colors); for (i=0; i < image->colors; i++) (void) fprintf(image->file,"%02x%02x%02x\n", DownScale(image->colormap[i].red), DownScale(image->colormap[i].green), DownScale(image->colormap[i].blue)); switch (image->compression) { case RunlengthEncodedCompression: default: { /* Dump runlength-encoded PseudoColor packets. */ for (i=0; i < image->packets; i++) { for (length=p->length; length >= 0; length-=256) { (void) fprintf(image->file,"%02x%02x",(unsigned int) p->index, (unsigned int) Min(length,0xff)); x++; if (x == 18) { x=0; (void) fprintf(image->file,"\n"); } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { (void) fprintf(image->file,"%02x",(unsigned int) p->index); x++; if (x == 36) { x=0; (void) fprintf(image->file,"\n"); } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } } (void) fprintf(image->file,"\n"); } (void) fprintf(image->file,"%%%%EndData\n"); if (strcmp(image_info->magick,"PS") != 0) (void) fprintf(image->file,"end\n"); (void) fprintf(image->file,"%%%%PageTrailer\n"); 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) fprintf(image->file,"%%%%Trailer\n"); if (page > 1) (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n", bounding_box.x1,bounding_box.y1,bounding_box.x2,bounding_box.y2); (void) fprintf(image->file,"%%%%EOF\n"); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P S 2 I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WritePS2Image translates an image to encapsulated Postscript % Level II for printing. If the supplied geometry is null, the image is % centered on the Postscript page. Otherwise, the image is positioned as % specified by the geometry. % % The format of the WritePS2Image routine is: % % status=WritePS2Image(image_info,image) % % A description of each parameter follows: % % o status: Function WritePS2Image return True if the image is printed. % False is returned if the image file cannot be opened for printing. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ static unsigned int WritePS2Image(const ImageInfo *image_info,Image *image) { static char *Postscript[]= { "%%BeginProlog", "%", "% Display a color image. The image is displayed in color on", "% Postscript viewers or printers that support color, otherwise", "% it is displayed as grayscale.", "%", "/buffer 512 string def", "/pixel_stream currentfile /ASCII85Decode filter def", "", "/DirectClassImage", "{", " %", " % Display a DirectClass image.", " %", " /DeviceRGB setcolorspace", " <<", " /ImageType 1", " /Interpolate true", " /Width columns", " /Height rows", " /BitsPerComponent 8", " /Decode [0 1 0 1 0 1]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream }", " { /DataSource pixel_stream /LZWDecode filter } ifelse", " >> image", "} bind def", "", "/PseudoClassImage", "{", " %", " % Display a PseudoClass image.", " %", " % Parameters:", " % colors: number of colors in the colormap.", " %", " currentfile buffer readline pop", " token pop /colors exch def pop", " colors 0 eq", " {", " %", " % Image is grayscale.", " %", " /DeviceGray setcolorspace", " <<", " /ImageType 1", " /Interpolate true", " /Width columns", " /Height rows", " /BitsPerComponent 1", " /Decode [0 1]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream }", " {", " /DataSource pixel_stream", " <<", " /Columns columns", " /Rows rows", " >> /CCITTFaxDecode filter", " } ifelse", " >> image", " }", " {", " %", " % Parameters:", " % colormap: red, green, blue color packets.", " %", " /colormap colors 3 mul string def", " currentfile colormap readhexstring pop pop", " [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace", " <<", " /ImageType 1", " /Interpolate true", " /Width columns", " /Height rows", " /BitsPerComponent 8", " /Decode [0 255]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream }", " { /DataSource pixel_stream /LZWDecode filter } ifelse", " >> image", " } ifelse", "} bind def", "", "/DisplayImage", "{", " %", " % Display a DirectClass or PseudoClass image.", " %", " % Parameters:", " % x & y translation.", " % x & y scale.", " % label pointsize.", " % image label.", " % image columns & rows.", " % class: 0-DirectClass or 1-PseudoClass.", " % compression: 0-RunlengthEncodedCompression or 1-NoCompression.", " % hex color packets.", " %", " gsave", " currentfile buffer readline pop", " token pop /x exch def", " token pop /y exch def pop", " x y translate", " currentfile buffer readline pop", " token pop /x exch def", " token pop /y exch def pop", " currentfile buffer readline pop", " token pop /pointsize exch def pop", " /NewCenturySchlbk-Roman findfont pointsize scalefont setfont", "^", " x y scale", " currentfile buffer readline pop", " token pop /columns exch def", " token pop /rows exch def pop", " currentfile buffer readline pop", " token pop /class exch def pop", " currentfile buffer readline pop", " token pop /compression exch def pop", " class 0 gt { PseudoClassImage } { DirectClassImage } ifelse", " pixel_stream flushfile", " grestore", (char *) NULL }; char date[MaxTextExtent], density[MaxTextExtent], **labels, **q; float dx_resolution, dy_resolution, x_resolution, y_resolution; int count, delta_x, delta_y, flags, x, y; register RunlengthPacket *p; register int i, j; time_t timer; unsigned char *pixels; unsigned int height, number_packets, page, page_height, page_width, scene, text_size, width; XSegment bounding_box; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); page=1; scene=0; do { /* Scale image to size of Postscript 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; /* Center image on Postscript page. */ (void) XParseGeometry(PSPageGeometry,&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 Postscript 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; } /* Scale relative to dots-per-inch. */ dx_resolution=72.0; dy_resolution=72.0; x_resolution=72.0; (void) strcpy(density,PSDensityGeometry); count=sscanf(density,"%fx%f",&x_resolution,&y_resolution); if (image_info->density != (char *) NULL) count=sscanf(image_info->density,"%fx%f",&x_resolution,&y_resolution); if (count != 2) y_resolution=x_resolution; width=(unsigned int) (((width*dx_resolution)/x_resolution)+0.5); height=(unsigned int) (((height*dy_resolution)/y_resolution)+0.5); if (page == 1) { /* Output Postscript header. */ if (strcmp(image_info->magick,"PS2") == 0) (void) fprintf(image->file,"%%!PS-Adobe-3.0\n"); else (void) fprintf(image->file,"%%!PS-Adobe-3.0 EPSF-3.0\n"); (void) fprintf(image->file,"%%%%Creator: (ImageMagick)\n"); (void) fprintf(image->file,"%%%%Title: (%s)\n",image->filename); timer=time((time_t *) NULL); (void) localtime(&timer); (void) strcpy(date,ctime(&timer)); date[Extent(date)-1]='\0'; (void) fprintf(image->file,"%%%%CreationDate: (%s)\n",date); bounding_box.x1=x; bounding_box.y1=y; bounding_box.x2=x+(int) width-1; bounding_box.y2=y+(int) (height+text_size)-1; if (image_info->adjoin && (image->next != (Image *) NULL)) (void) fprintf(image->file,"%%%%BoundingBox: (atend)\n"); else (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n", bounding_box.x1,bounding_box.y1,bounding_box.x2,bounding_box.y2); if (image->label != (char *) NULL) (void) fprintf(image->file, "%%%%DocumentNeededResources: font NewCenturySchlbk-Roman\n"); (void) fprintf(image->file,"%%%%LanguageLevel: 2\n"); if (strcmp(image_info->magick,"PS2") != 0) (void) fprintf(image->file,"%%%%Pages: 0\n"); else { Image *next_image; unsigned int pages; /* Compute the number of pages. */ (void) fprintf(image->file,"%%%%Orientation: Portrait\n"); (void) fprintf(image->file,"%%%%PageOrder: Ascend\n"); pages=1; if (image_info->adjoin) for (next_image=image->next; next_image != (Image *) NULL; ) { next_image=next_image->next; pages++; } (void) fprintf(image->file,"%%%%Pages: %u\n",pages); } (void) fprintf(image->file,"%%%%EndComments\n"); (void) fprintf(image->file,"\n%%%%BeginDefaults\n"); (void) fprintf(image->file,"%%%%PageOrientation: Portrait\n"); (void) fprintf(image->file,"%%%%EndDefaults\n\n"); /* Output Postscript commands. */ for (q=Postscript; *q; q++) { if (*(*q) != '^') { (void) fprintf(image->file,"%s\n",*q); continue; } for (i=MultilineCensus(image->label)-1; i >= 0; i--) { (void) fprintf(image->file," /label 512 string def\n"); (void) fprintf(image->file," currentfile label readline pop\n"); (void) fprintf(image->file," 0 y %d add moveto label show pop\n", i*image_info->pointsize+12); } } if (strcmp(image_info->magick,"PS2") == 0) (void) fprintf(image->file," showpage\n"); (void) fprintf(image->file,"} bind def\n"); (void) fprintf(image->file,"%%%%EndProlog\n"); } (void) fprintf(image->file,"%%%%Page: 1 %u\n",page++); (void) fprintf(image->file,"%%%%PageBoundingBox: %d %d %d %d\n",x,y, x+(int) width-1,y+(int) (height+text_size)-1); if (x < bounding_box.x1) bounding_box.x1=x; if (y < bounding_box.y1) bounding_box.y1=y; if ((x+(int) width-1) > bounding_box.x2) bounding_box.x2=x+(int) width-1; if ((y+(int) (height+text_size)-1) > bounding_box.y2) bounding_box.y2=y+(int) (height+text_size)-1; if (image->label != (char *) NULL) (void) fprintf(image->file, "%%%%PageResources: font NewCenturySchlbk-Roman\n"); if (strcmp(image_info->magick,"PS2") != 0) (void) fprintf(image->file,"userdict begin\n"); (void) fprintf(image->file,"%%%%BeginData:\n"); (void) fprintf(image->file,"DisplayImage\n"); /* Output image data. */ labels=StringToList(image->label); image->compression=image_info->compression; CompressImage(image); (void) fprintf(image->file,"%d %d\n%u %u\n%u\n",x,y,width,height, image_info->pointsize); if (labels != (char **) NULL) { for (i=0; labels[i] != (char *) NULL; i++) { (void) fprintf(image->file,"%s \n",labels[i]); free(labels[i]); } free(labels); } (void) fprintf(image->file,"%u %u\n%u\n%d\n",image->columns,image->rows, IsPseudoClass(image),(int) (image->compression == NoCompression)); p=image->pixels; if (!IsPseudoClass(image) && !IsGrayImage(image)) switch (image->compression) { case RunlengthEncodedCompression: default: { register unsigned char *q; /* Allocate pixel array. */ number_packets=3*image->columns*image->rows; pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char)); if (pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); /* Dump Packbit encoded pixels. */ q=pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (image->matte && (p->index == Transparent)) { *q++=DownScale(MaxRGB); *q++=DownScale(MaxRGB); *q++=DownScale(MaxRGB); } else { *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); } (void) LZWEncodeImage(image->file,pixels,number_packets); free((char *) pixels); break; } case NoCompression: { /* Dump uncompressed DirectColor packets. */ Ascii85Initialize(); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (image->matte && (p->index == Transparent)) { Ascii85Encode(DownScale(MaxRGB),image->file); Ascii85Encode(DownScale(MaxRGB),image->file); Ascii85Encode(DownScale(MaxRGB),image->file); } else { Ascii85Encode(DownScale(p->red),image->file); Ascii85Encode(DownScale(p->green),image->file); Ascii85Encode(DownScale(p->blue),image->file); } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } Ascii85Flush(image->file); break; } } else if (IsMonochromeImage(image)) { register unsigned char bit, byte, polarity; polarity= Intensity(image->colormap[0]) < Intensity(image->colormap[1]); bit=0; byte=0; x=0; (void) fprintf(image->file,"0\n"); switch (image->compression) { case RunlengthEncodedCompression: default: { (void) HuffmanEncodeImage(image_info,image); break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(); 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) { Ascii85Encode(byte,image->file); bit=0; byte=0; } x++; if (x == image->columns) { /* Advance to the next scanline. */ if (bit != 0) Ascii85Encode(byte << (8-bit),image->file); bit=0; byte=0; x=0; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } Ascii85Flush(image->file); break; } } } else { /* Dump number of colors and colormap. */ (void) fprintf(image->file,"%u\n",image->colors); for (i=0; i < image->colors; i++) (void) fprintf(image->file,"%02x%02x%02x\n", DownScale(image->colormap[i].red), DownScale(image->colormap[i].green), DownScale(image->colormap[i].blue)); switch (image->compression) { case RunlengthEncodedCompression: default: { register unsigned char *q; /* Allocate pixel array. */ number_packets=image->columns*image->rows; pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char)); if (pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); /* Dump Runlength encoded pixels. */ q=pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=(unsigned char) p->index; p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } (void) LZWEncodeImage(image->file,pixels,number_packets); free((char *) pixels); break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(); for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) Ascii85Encode((unsigned char) p->index,image->file); p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } Ascii85Flush(image->file); break; } } } (void) fprintf(image->file,"\n"); (void) fprintf(image->file,"%%%%EndData\n"); if (strcmp(image_info->magick,"PS2") != 0) (void) fprintf(image->file,"end\n"); (void) fprintf(image->file,"%%%%PageTrailer\n"); 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) fprintf(image->file,"%%%%Trailer\n"); if (page > 1) (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n", bounding_box.x1,bounding_box.y1,bounding_box.x2,bounding_box.y2); (void) fprintf(image->file,"%%%%EOF\n"); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e R A D I A N C E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteRADIANCEImage writes an image in the RADIANCE encoded image % format. % % The format of the WriteRADIANCEImage routine is: % % status=WriteRADIANCEImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteRADIANCEImage 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 WriteRADIANCEImage(const ImageInfo *image_info, Image *image) { unsigned int status; Warning("Cannot write RADIANCE images",image->filename); status=WriteMIFFImage(image_info,image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e R G B I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteRGBImage writes an image to a file in red, green, and % blue rasterfile format. % % The format of the WriteRGBImage routine is: % % status=WriteRGBImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteRGBImage 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 WriteRGBImage(const ImageInfo *image_info,Image *image) { 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); } scene=0; do { /* Convert MIFF to RGB raster pixels. */ if (strcmp(image_info->magick,"RGB") == 0) image->matte=False; switch (image_info->interlace) { case NoneInterlace: default: { /* No interlacing: RGBRGBRGBRGBRGBRGB... */ p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { WriteQuantumFile(p->red); WriteQuantumFile(p->green); WriteQuantumFile(p->blue); if (image->matte) WriteQuantumFile(p->index); } 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); for (y=0; y < image->rows; y++) { p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { WriteQuantumFile(p->red); p++; } p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { WriteQuantumFile(p->green); p++; } p=image->pixels+(y*image->columns); for (x=0; x < image->columns; x++) { WriteQuantumFile(p->blue); p++; } p=image->pixels+(y*image->columns); if (image->matte) for (x=0; x < image->columns; x++) { WriteQuantumFile(p->index); p++; } ProgressMonitor(SaveImageText,y,image->rows); } break; } case PlaneInterlace: case PartitionInterlace: { /* Plane interlacing: RRRRRR...GGGGGG...BBBBBB... */ if (image_info->interlace == PartitionInterlace) { AppendImageFormat("R",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++) WriteQuantumFile(p->red); p++; } if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("G",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++) WriteQuantumFile(p->green); p++; } if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("B",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++) WriteQuantumFile(p->blue); p++; } if (image->matte) { ProgressMonitor(SaveImageText,300,400); p=image->pixels; if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("A",image->filename); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) WriteQuantumFile(p->index); 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 R L A I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteRLAImage writes an image in the Alias/Wavefront encoded image % format. % % The format of the WriteRLAImage routine is: % % status=WriteRLAImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteRLAImage 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 WriteRLAImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("Cannot write RLA images",image->filename); status=WriteMIFFImage(image_info,image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e R L E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteRLEImage writes an image in the Utah Run length encoded image % format. % % The format of the WriteRLEImage routine is: % % status=WriteRLEImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteRLEImage 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 WriteRLEImage(const ImageInfo *image_info,Image *image) { char command[MaxTextExtent]; Image *flipped_image; ImageInfo rle_info; unsigned int packet_size, status; /* Flip image. */ image->orphan=True; flipped_image=FlipImage(image); image->orphan=False; if (flipped_image == (Image *) NULL) PrematureExit("Unable to flip image",image); rle_info=(*image_info); rle_info.interlace=NoneInterlace; TemporaryFilename(flipped_image->filename); status=WriteRGBImage(&rle_info,flipped_image); if (status) { packet_size=3; if (image->matte) packet_size=4; (void) sprintf(command,"rawtorle -w %u -h %u -n %u -o %s %s\n", image->columns,image->rows,packet_size,image_info->filename, flipped_image->filename); status=SystemCommand(command); (void) remove(flipped_image->filename); if (!IsAccessible(image_info->filename)) Warning("RLE translation failed",command); } DestroyImage(flipped_image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e S G I I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteSGIImage writes an image in SGI RGB encoded image format. % % The format of the WriteSGIImage routine is: % % status=WriteSGIImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteSGIImage 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 int SGIEncode(unsigned char *pixels,int count, unsigned char *packets) { short runlength; unsigned char *limit, *mark, *p, *q; p=pixels; limit=p+count*4; q=packets; while (p < limit) { mark=p; p+=8; while ((p < limit) && ((*(p-8) != *(p-4)) || (*(p-4) != *p))) p+=4; p-=8; count=(int) ((p-mark) >> 2); while (count) { runlength=count > 126 ? 126 : count; count-=runlength; *q++=0x80 | runlength; for ( ; runlength > 0; runlength--) { *q++=(*mark); mark+=4; } } mark=p; p+=4; while ((p < limit) && (*p == *mark)) p+=4; count=(int) ((p-mark) >> 2); while (count) { runlength=count > 126 ? 126 : count; count-=runlength; *q++=runlength; *q++=(*mark); } } *q++=0; return((int) (q-packets)); } static unsigned int WriteSGIImage(const ImageInfo *image_info,Image *image) { typedef struct _SGIHeader { unsigned short magic; unsigned char storage, bytes_per_pixel; unsigned short dimension, columns, rows, depth; unsigned long minimum_value, maximum_value; unsigned char filler[492]; } SGIHeader; SGIHeader iris_header; register int i, j, x, y, z; register RunlengthPacket *p; register unsigned char *q; unsigned char *iris_pixels, *packets, 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 SGI raster file header. */ iris_header.magic=0x01DA; image->compression=image_info->compression; if (image->compression == NoCompression) iris_header.storage=0x00; else iris_header.storage=0x01; iris_header.bytes_per_pixel=1; /* one byte per pixel */ iris_header.dimension=3; iris_header.columns=image->columns; iris_header.rows=image->rows; iris_header.depth=image->matte ? 4 : 3; if (IsGrayImage(image)) { iris_header.dimension=2; iris_header.depth=1; } iris_header.minimum_value=0; iris_header.maximum_value=MaxRGB; for (i=0; i < sizeof(iris_header.filler); i++) iris_header.filler[i]=0; /* Write SGI header. */ MSBFirstWriteShort(iris_header.magic,image->file); (void) fputc(iris_header.storage,image->file); (void) fputc(iris_header.bytes_per_pixel,image->file); MSBFirstWriteShort(iris_header.dimension,image->file); MSBFirstWriteShort(iris_header.columns,image->file); MSBFirstWriteShort(iris_header.rows,image->file); MSBFirstWriteShort(iris_header.depth,image->file); MSBFirstWriteLong(iris_header.minimum_value,image->file); MSBFirstWriteLong(iris_header.maximum_value,image->file); (void) fwrite(iris_header.filler,1,sizeof(iris_header.filler),image->file); /* Allocate SGI pixels. */ iris_pixels=(unsigned char *) malloc(4*image->columns*image->rows*sizeof(unsigned char)); if (iris_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); /* Convert runlength-encoded packets to uncompressed SGI pixels. */ x=0; y=0; p=image->pixels; q=iris_pixels+(iris_header.rows-1)*(iris_header.columns*4); 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); *q++=(unsigned char) p->index; x++; if (x == image->columns) { y++; q=iris_pixels+((iris_header.rows-1)-y)*(iris_header.columns*4); x=0; } } p++; } if (image->compression == NoCompression) { unsigned char *scanline; /* Write uncompressed SGI pixels. */ scanline=(unsigned char *) malloc(iris_header.columns*sizeof(unsigned char)); if (scanline == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); for (z=0; z < (int) iris_header.depth; z++) { q=iris_pixels+z; for (y=0; y < (int) iris_header.rows; y++) { for (x=0; x < (int) iris_header.columns; x++) { scanline[x]=(*q); q+=4; } (void) fwrite(scanline,sizeof(unsigned char),iris_header.columns, image->file); } ProgressMonitor(SaveImageText,z,iris_header.depth); } free(scanline); } else { unsigned long length, number_packets, offset, *offsets, *runlength; /* Convert SGI uncompressed pixels to runlength-encoded pixels. */ offsets=(unsigned long *) malloc(iris_header.rows*iris_header.depth*sizeof(unsigned long)); packets=(unsigned char *) malloc(4*((iris_header.columns << 1)+10)* image->rows*sizeof(unsigned char)); runlength=(unsigned long *) malloc(iris_header.rows*iris_header.depth*sizeof(unsigned long)); if ((offsets == (unsigned long *) NULL) || (packets == (unsigned char *) NULL) || (runlength == (unsigned long *) NULL)) PrematureExit("Unable to allocate memory",image); offset=512+4*((iris_header.rows*iris_header.depth) << 1); number_packets=0; q=iris_pixels; for (y=0; y < (int) iris_header.rows; y++) { for (z=0; z < (int) iris_header.depth; z++) { length= SGIEncode(q+z,(int) iris_header.columns,packets+number_packets); number_packets+=length; offsets[y+z*iris_header.rows]=offset; runlength[y+z*iris_header.rows]=length; offset+=length; } q+=(iris_header.columns*4); ProgressMonitor(SaveImageText,y,iris_header.rows); } /* Write out line start and length tables and runlength-encoded pixels. */ for (i=0; i < (int) (iris_header.rows*iris_header.depth); i++) MSBFirstWriteLong(offsets[i],image->file); for (i=0; i < (int) (iris_header.rows*iris_header.depth); i++) MSBFirstWriteLong(runlength[i],image->file); (void) fwrite(packets,sizeof(unsigned char),number_packets,image->file); /* Free memory. */ free(runlength); free(packets); free(offsets); } free(iris_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 S U N I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteSUNImage writes an image in the SUN rasterfile format. % % The format of the WriteSUNImage routine is: % % status=WriteSUNImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteSUNImage 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 WriteSUNImage(const ImageInfo *image_info,Image *image) { #define RMT_EQUAL_RGB 1 #define RMT_NONE 0 #define RMT_RAW 2 #define RT_STANDARD 1 #define RT_FORMAT_RGB 3 typedef struct _SUNHeader { unsigned long magic, width, height, depth, length, type, maptype, maplength; } SUNHeader; register int i, j, x; register RunlengthPacket *p; SUNHeader sun_header; 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 SUN raster file header. */ sun_header.magic=0x59a66a95; sun_header.width=image->columns; sun_header.height=image->rows; sun_header.type=(image->class == DirectClass ? RT_FORMAT_RGB : RT_STANDARD); sun_header.maptype=RMT_NONE; sun_header.maplength=0; if (!IsPseudoClass(image) && !IsGrayImage(image)) { /* Full color SUN raster. */ sun_header.depth=(image->matte ? 32 : 24); sun_header.length=image->columns*image->rows*(image->matte ? 4 : 3); sun_header.length+=image->columns % 2 ? image->rows : 0; } else if (IsMonochromeImage(image)) { /* Monochrome SUN raster. */ sun_header.depth=1; sun_header.length=((image->columns+7) >> 3)*image->rows; sun_header.length+=((image->columns/8)+(image->columns % 8 ? 1 : 0)) % 2 ? image->rows : 0; } else { /* Colormapped SUN raster. */ sun_header.depth=8; sun_header.length=image->columns*image->rows; sun_header.length+=image->columns % 2 ? image->rows : 0; sun_header.maptype=RMT_EQUAL_RGB; sun_header.maplength=image->colors*3; } /* Write SUN header. */ MSBFirstWriteLong(sun_header.magic,image->file); MSBFirstWriteLong(sun_header.width,image->file); MSBFirstWriteLong(sun_header.height,image->file); MSBFirstWriteLong(sun_header.depth,image->file); MSBFirstWriteLong(sun_header.length,image->file); MSBFirstWriteLong(sun_header.type,image->file); MSBFirstWriteLong(sun_header.maptype,image->file); MSBFirstWriteLong(sun_header.maplength,image->file); /* Convert MIFF to SUN raster pixels. */ p=image->pixels; x=0; if (!IsPseudoClass(image) && !IsGrayImage(image)) { /* Convert DirectClass packet to SUN RGB pixel. */ for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (image->matte) (void) fputc(DownScale(p->index),image->file); (void) fputc(DownScale(p->red),image->file); (void) fputc(DownScale(p->green),image->file); (void) fputc(DownScale(p->blue),image->file); x++; if (x == image->columns) { if ((image->columns % 2) != 0) (void) fputc(0,image->file); /* pad scanline */ x=0; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } else if (IsMonochromeImage(image)) { register unsigned char bit, byte, polarity; /* Convert PseudoClass image to a SUN monochrome image. */ 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) { (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); if ((((image->columns/8)+ (image->columns % 8 ? 1 : 0)) % 2) != 0) (void) fputc(0,image->file); /* pad scanline */ bit=0; byte=0; x=0; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } else { /* Dump colormap to file. */ for (i=0; i < image->colors; i++) (void) fputc(DownScale(image->colormap[i].red),image->file); for (i=0; i < image->colors; i++) (void) fputc(DownScale(image->colormap[i].green),image->file); for (i=0; i < image->colors; i++) (void) fputc(DownScale(image->colormap[i].blue),image->file); /* Convert PseudoClass packet to SUN colormapped pixel. */ for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { (void) fputc(p->index,image->file); x++; if (x == image->columns) { if ((image->columns % 2) != 0) (void) fputc(0,image->file); /* pad scanline */ x=0; } } 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 T A R G A I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteTARGAImage writes a image in the Truevision Targa rasterfile % format. % % The format of the WriteTARGAImage routine is: % % status=WriteTARGAImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteTARGAImage 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 WriteTARGAImage(const ImageInfo *image_info,Image *image) { #define TargaColormap 1 #define TargaRGB 2 #define TargaMonochrome 3 #define TargaRLEColormap 9 #define TargaRLERGB 10 #define TargaRLEMonochrome 11 typedef struct _TargaHeader { unsigned char id_length, colormap_type, image_type; unsigned short colormap_index, colormap_length; unsigned char colormap_size; unsigned short x_origin, y_origin, width, height; unsigned char pixel_size, attributes; } TargaHeader; Image *flopped_image; int count, runlength; register int i, j; register RunlengthPacket *p; register unsigned char *q, *r; TargaHeader targa_header; unsigned char *targa_pixels; 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 { /* Flop image. */ image->orphan=True; flopped_image=FlopImage(image); image->orphan=False; if (flopped_image == (Image *) NULL) PrematureExit("Unable to flop image",image); flopped_image->compression=image_info->compression; CompressImage(flopped_image); /* Initialize TARGA raster file header. */ targa_header.id_length=0; if (flopped_image->comments != (char *) NULL) targa_header.id_length=Min(Extent(flopped_image->comments),255); targa_header.colormap_type=0; targa_header.colormap_index=0; targa_header.colormap_length=0; targa_header.colormap_size=0; targa_header.x_origin=0; targa_header.y_origin=0; targa_header.width=flopped_image->columns; targa_header.height=flopped_image->rows; targa_header.pixel_size=8; targa_header.attributes=0; if (!IsPseudoClass(flopped_image)) { /* Full color TARGA raster. */ targa_header.image_type=TargaRGB; if (flopped_image->compression == RunlengthEncodedCompression) targa_header.image_type=TargaRLERGB; targa_header.pixel_size=flopped_image->matte ? 32 : 24; } else { /* Colormapped TARGA raster. */ targa_header.image_type=TargaColormap; if (flopped_image->compression == RunlengthEncodedCompression) targa_header.image_type=TargaRLEColormap; if (!IsMonochromeImage(flopped_image)) { targa_header.colormap_type=1; targa_header.colormap_index=0; targa_header.colormap_length=flopped_image->colors; targa_header.colormap_size=24; } else { /* Monochrome TARGA raster. */ targa_header.image_type=TargaMonochrome; if (flopped_image->compression == RunlengthEncodedCompression) targa_header.image_type=TargaRLEMonochrome; } } /* Write TARGA header. */ (void) fputc((char) targa_header.id_length,image->file); (void) fputc((char) targa_header.colormap_type,image->file); (void) fputc((char) targa_header.image_type,image->file); LSBFirstWriteShort(targa_header.colormap_index,image->file); LSBFirstWriteShort(targa_header.colormap_length,image->file); (void) fputc((char) targa_header.colormap_size,image->file); LSBFirstWriteShort(targa_header.x_origin,image->file); LSBFirstWriteShort(targa_header.y_origin,image->file); LSBFirstWriteShort(targa_header.width,image->file); LSBFirstWriteShort(targa_header.height,image->file); (void) fputc((char) targa_header.pixel_size,image->file); (void) fputc((char) targa_header.attributes,image->file); if (targa_header.id_length != 0) (void) fwrite((char *) flopped_image->comments,1,targa_header.id_length, image->file); /* Convert MIFF to TARGA raster pixels. */ count=(unsigned int) (targa_header.pixel_size*targa_header.width*targa_header.height) >> 3; if (flopped_image->compression == RunlengthEncodedCompression) count+=(count/128)+1; targa_pixels=(unsigned char *) malloc(count*sizeof(unsigned char)); if (targa_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",flopped_image); p=flopped_image->pixels+(flopped_image->packets-1); q=targa_pixels; if (!IsPseudoClass(flopped_image)) { /* Convert DirectClass packet to TARGA RGB pixel. */ if (flopped_image->compression != RunlengthEncodedCompression) for (i=0; i < flopped_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q++=DownScale(p->blue); *q++=DownScale(p->green); *q++=DownScale(p->red); if (flopped_image->matte) *q++=DownScale(p->index); } p--; if (QuantumTick(i,flopped_image)) ProgressMonitor(SaveImageText,i,flopped_image->packets); } else for (i=0; i < flopped_image->packets; i++) { for (runlength=p->length+1; runlength > 128; runlength-=128) { *q++=0xff; *q++=DownScale(p->blue); *q++=DownScale(p->green); *q++=DownScale(p->red); if (flopped_image->matte) *q++=DownScale(p->index); } r=q; *q++=0x80+(runlength-1); *q++=DownScale(p->blue); *q++=DownScale(p->green); *q++=DownScale(p->red); if (flopped_image->matte) *q++=DownScale(p->index); if (runlength != 1) p--; else { for ( ; i < flopped_image->packets; i++) { p--; if ((p->length != 0) || (runlength == 128)) break; *q++=DownScale(p->blue); *q++=DownScale(p->green); *q++=DownScale(p->red); if (flopped_image->matte) *q++=DownScale(p->index); runlength++; } *r=runlength-1; } if (QuantumTick(i,flopped_image)) ProgressMonitor(SaveImageText,i,flopped_image->packets); } } else if (!IsMonochromeImage(flopped_image)) { unsigned char *targa_colormap; /* Dump colormap to file (blue, green, red byte order). */ if (flopped_image->colors > 256) { QuantizeInfo quantize_info; GetQuantizeInfo(&quantize_info); quantize_info.number_colors=256; quantize_info.dither=image_info->dither; QuantizeImage(&quantize_info,flopped_image); } targa_colormap=(unsigned char *) malloc(3*targa_header.colormap_length*sizeof(unsigned char)); if (targa_colormap == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",flopped_image); q=targa_colormap; for (i=0; i < flopped_image->colors; i++) { *q++=DownScale(flopped_image->colormap[i].blue); *q++=DownScale(flopped_image->colormap[i].green); *q++=DownScale(flopped_image->colormap[i].red); } (void) fwrite((char *) targa_colormap,1, (int) 3*targa_header.colormap_length,image->file); free((char *) targa_colormap); /* Convert PseudoClass packet to TARGA colormapped pixel. */ q=targa_pixels; if (flopped_image->compression != RunlengthEncodedCompression) for (i=0; i < flopped_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=p->index; p--; if (QuantumTick(i,flopped_image)) ProgressMonitor(SaveImageText,i,flopped_image->packets); } else for (i=0; i < flopped_image->packets; i++) { for (runlength=p->length+1; runlength > 128; runlength-=128) { *q++=0xff; *q++=p->index; } r=q; *q++=0x80+(runlength-1); *q++=p->index; if (runlength != 1) p--; else { for ( ; i < flopped_image->packets; i++) { p--; if ((p->length != 0) || (runlength == 128)) break; *q++=p->index; runlength++; } *r=runlength-1; } if (QuantumTick(i,flopped_image)) ProgressMonitor(SaveImageText,i,flopped_image->packets); } } else { unsigned int polarity; /* Convert PseudoClass image to a TARGA monochrome image. */ polarity=0; if (flopped_image->colors == 2) polarity=Intensity(flopped_image->colormap[0]) > Intensity(flopped_image->colormap[1]); if (flopped_image->compression != RunlengthEncodedCompression) for (i=0; i < flopped_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=p->index == polarity ? 0 : DownScale(MaxRGB); p--; if (QuantumTick(i,flopped_image)) ProgressMonitor(SaveImageText,i,flopped_image->packets); } else for (i=0; i < flopped_image->packets; i++) { for (runlength=p->length+1; runlength > 128; runlength-=128) { *q++=0xff; *q++=p->index == polarity ? 0 : DownScale(MaxRGB); } r=q; *q++=0x80+(runlength-1); *q++=p->index == polarity ? 0 : DownScale(MaxRGB); if (runlength != 1) p--; else { for ( ; i < flopped_image->packets; i++) { p--; if ((p->length != 0) || (runlength == 128)) break; *q++=p->index == polarity ? 0 : DownScale(MaxRGB); runlength++; } *r=runlength-1; } if (QuantumTick(i,flopped_image)) ProgressMonitor(SaveImageText,i,flopped_image->packets); } } (void) fwrite((char *) targa_pixels,1,(int) (q-targa_pixels),image->file); DestroyImage(flopped_image); free((char *) targa_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 T E X T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteTEXTImage writes an image in the TEXT image forma. % % The format of the WriteTEXTImage routine is: % % status=WriteTEXTImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteTEXTImage 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 WriteTEXTImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("Cannot write TEXT images",image->filename); status=WriteMIFFImage(image_info,image); return(status); } #ifdef HasTIFF /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e T I F F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteTIFFImage writes an image in the Tagged image file format. % % The format of the WriteTIFFImage routine is: % % status=WriteTIFFImage(image_info,image) % % A description of each parameter follows: % % o status: Function WriteTIFFImage 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 image: A pointer to a Image structure. % % */ static unsigned int WriteTIFFImage(const ImageInfo *image_info,Image *image) { #ifndef TIFFDefaultStripSize #define TIFFDefaultStripSize(tiff,request) ((8*1024)/TIFFScanlineSize(tiff)) #endif Image encode_image; int flags, sans_offset; register RunlengthPacket *p; register int i, j, x, y; register unsigned char *q; TIFF *tiff; uint16 compression, photometric; unsigned char *scanline; unsigned int scene, x_resolution, y_resolution; unsigned short units, value; /* Open TIFF file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); if ((image->file != stdout) && !image->pipe) (void) remove(image->filename); else { /* Write standard output or pipe to temporary file. */ encode_image=(*image); TemporaryFilename(image->filename); image->temporary=True; } CloseImage(image); tiff=TIFFOpen(image->filename,WriteBinaryType); if (tiff == (TIFF *) NULL) return(False); scene=0; do { /* Initialize TIFF fields. */ TIFFSetField(tiff,TIFFTAG_IMAGELENGTH,(uint32) image->rows); TIFFSetField(tiff,TIFFTAG_IMAGEWIDTH,(uint32) image->columns); TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,8); if (image->depth == 16) TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,16); compression=COMPRESSION_LZW; if (!image->matte) if (IsMonochromeImage(image)) { compression=COMPRESSION_CCITTFAX4; TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,1); } image->compression=image_info->compression; if (image->compression == NoCompression) compression=COMPRESSION_NONE; TIFFSetField(tiff,TIFFTAG_COMPRESSION,compression); if (!IsPseudoClass(image) && !IsGrayImage(image)) { /* Full color TIFF raster. */ photometric=PHOTOMETRIC_RGB; TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,(image->matte ? 4 : 3)); if (image->matte) { uint16 extra_samples, sample_info[1]; /* TIFF has a matte channel. */ extra_samples=1; sample_info[0]=EXTRASAMPLE_ASSOCALPHA; TIFFSetField(tiff,TIFFTAG_EXTRASAMPLES,extra_samples,&sample_info); } } else { /* Colormapped TIFF raster. */ photometric=PHOTOMETRIC_PALETTE; TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1); if (IsGrayImage(image)) { /* Grayscale TIFF raster. */ photometric=PHOTOMETRIC_MINISBLACK; if (IsMonochromeImage(image)) { photometric=PHOTOMETRIC_MINISWHITE; TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,1); } } } TIFFSetField(tiff,TIFFTAG_PHOTOMETRIC,photometric); TIFFSetField(tiff,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB); TIFFSetField(tiff,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT); TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,image->rows); if (photometric == PHOTOMETRIC_RGB) if ((image_info->interlace == PlaneInterlace) || (image_info->interlace == PartitionInterlace)) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_SEPARATE); flags=NoValue; if (image_info->density != (char *) NULL) flags=XParseGeometry(image_info->density,&sans_offset,&sans_offset, &x_resolution,&y_resolution); if (flags & WidthValue) image->x_resolution=x_resolution; if (flags & HeightValue) image->y_resolution=y_resolution; units=RESUNIT_NONE; if (image->units == PixelsPerInchResolution) units=RESUNIT_INCH; if (image->units == PixelsPerCentimeterResolution) units=RESUNIT_CENTIMETER; if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0)) { units=RESUNIT_NONE; image->x_resolution=image->columns; image->y_resolution=image->rows; } TIFFSetField(tiff,TIFFTAG_RESOLUTIONUNIT,(uint16) units); TIFFSetField(tiff,TIFFTAG_XRESOLUTION,image->x_resolution); TIFFSetField(tiff,TIFFTAG_YRESOLUTION,image->y_resolution); TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,image->filename); TIFFSetField(tiff,TIFFTAG_SOFTWARE,Version); if (image->number_scenes > 1) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,(unsigned short) image->scene, image->number_scenes); if (image->label != (char *) NULL) TIFFSetField(tiff,TIFFTAG_PAGENAME,image->label); if (image->comments != (char *) NULL) TIFFSetField(tiff,TIFFTAG_IMAGEDESCRIPTION,image->comments); /* Write image scanlines. */ scanline=(unsigned char *) malloc(TIFFScanlineSize(tiff)); if (scanline == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); p=image->pixels; q=scanline; x=0; y=0; if (photometric == PHOTOMETRIC_RGB) switch (image_info->interlace) { case NoneInterlace: default: { for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { /* Convert DirectClass packets to contiguous RGB scanlines. */ WriteQuantum(p->red,q); WriteQuantum(p->green,q); WriteQuantum(p->blue,q); if (image->matte) WriteQuantum(p->index,q); x++; if (x == image->columns) { if (TIFFWriteScanline(tiff,(char *) scanline,y,0) < 0) break; q=scanline; x=0; y++; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } break; } case PlaneInterlace: case PartitionInterlace: { /* Plane interlacing: RRRRRR...GGGGGG...BBBBBB... */ p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { WriteQuantum(p->red,q); x++; if (x == image->columns) { if (TIFFWriteScanline(tiff,(char *) scanline,y,0) < 0) break; q=scanline; x=0; y++; } } p++; } ProgressMonitor(SaveImageText,100,400); p=image->pixels; y=0; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { WriteQuantum(p->green,q); x++; if (x == image->columns) { if (TIFFWriteScanline(tiff,(char *) scanline,y,1) < 0) break; q=scanline; x=0; y++; } } p++; } ProgressMonitor(SaveImageText,200,400); p=image->pixels; y=0; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { WriteQuantum(p->blue,q); x++; if (x == image->columns) { if (TIFFWriteScanline(tiff,(char *) scanline,y,2) < 0) break; q=scanline; x=0; y++; } } p++; } ProgressMonitor(SaveImageText,300,400); p=image->pixels; y=0; if (image->matte) for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { WriteQuantum(p->index,q); x++; if (x == image->columns) { if (TIFFWriteScanline(tiff,(char *) scanline,y,3) < 0) break; q=scanline; x=0; y++; } } p++; } ProgressMonitor(SaveImageText,400,400); break; } } else if (photometric == PHOTOMETRIC_PALETTE) { unsigned short *blue, *green, *red; /* Allocate TIFF colormap. */ blue=(unsigned short *) malloc(image->colors*sizeof(unsigned short)); green=(unsigned short *) malloc(image->colors*sizeof(unsigned short)); red=(unsigned short *) malloc(image->colors*sizeof(unsigned short)); if ((blue == (unsigned short *) NULL) || (green == (unsigned short *) NULL) || (red == (unsigned short *) NULL)) PrematureExit("Unable to allocate memory",image); /* Initialize TIFF colormap. */ for (i=0; i < image->colors; i++) { red[i]=(unsigned int) (image->colormap[i].red*65535L)/MaxRGB; green[i]=(unsigned int) (image->colormap[i].green*65535L)/MaxRGB; blue[i]=(unsigned int) (image->colormap[i].blue*65535L)/MaxRGB; } TIFFSetField(tiff,TIFFTAG_COLORMAP,red,green,blue); /* Convert PseudoClass packets to contiguous indexed scanlines. */ for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { WriteQuantum(p->index,q); x++; if (x == image->columns) { if (TIFFWriteScanline(tiff,(char *) scanline,y,0) < 0) break; q=scanline; x=0; y++; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } free((char *) red); free((char *) green); free((char *) blue); } else if (image->colors > 2) for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { /* Convert PseudoClass packets to contiguous grayscale scanlines. */ WriteQuantum(Intensity(*p),q); x++; if (x == image->columns) { if (TIFFWriteScanline(tiff,(char *) scanline,y,0) < 0) break; q=scanline; x=0; y++; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } else { register unsigned char bit, byte, polarity; /* Convert PseudoClass packets to contiguous monochrome scanlines. */ polarity=0; if (image->colors == 2) if (photometric == PHOTOMETRIC_MINISBLACK) polarity= Intensity(image->colormap[0]) < Intensity(image->colormap[1]); else polarity= Intensity(image->colormap[0]) > Intensity(image->colormap[1]); bit=0; byte=0; x=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); if (TIFFWriteScanline(tiff,(char *) scanline,y,0) < 0) break; q=scanline; bit=0; byte=0; x=0; y++; } } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } free((char *) scanline); if (image_info->verbose == True) TIFFPrintDirectory(tiff,stderr,False); TIFFWriteDirectory(tiff); 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) TIFFClose(tiff); if (image->temporary) { FILE *file; int c; /* Copy temporary file to standard output or pipe. */ file=fopen(image->filename,ReadBinaryType); if (file == (FILE *) NULL) PrematureExit("Unable to open file",image); c=fgetc(file); while (c != EOF) { (void) putc(c,encode_image.file); c=fgetc(file); } (void) fclose(file); (void) remove(image->filename); CloseImage(&encode_image); } return(True); } #else static unsigned int WriteTIFFImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("TIFF library is not available",image->filename); status=WriteMIFFImage(image_info,image); return(status); } #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e T I L E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteTILEImage writes an image in the TILE encoded image format. % % The format of the WriteTILEImage routine is: % % status=WriteTILEImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteTILEImage 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 WriteTILEImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("Cannot write TILE images",image->filename); status=WriteMIFFImage(image_info,image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e U Y V Y I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteUYVYImage writes an image to a file in the digital UYVY % (16bit/pixel) format. This format, used by AccomWSD, is not dramatically % higher quality than the 12bit/pixel YUV format, but has better locality. % % The format of the WriteUYVYImage routine is: % % status=WriteUYVYImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteUYVYImage 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. % Implicit assumption: number of columns is even. % */ static unsigned int WriteUYVYImage(const ImageInfo *image_info,Image *image) { register int i, j; register RunlengthPacket *p; unsigned int full, y, u, v; /* Open output image file. */ if (!UncompressImage(image)) return(False); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Convert to YUV, at full resolution. */ RGBTransformImage(image,YCbCrColorspace); /* Accumulate two pixels, then output. */ full=False; u=0; v=0; y=0; full=False; full=False; p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (full) { (void) fputc(DownScale((u+p->green) >> 1),image->file); (void) fputc(DownScale(y),image->file); (void) fputc(DownScale((v+p->blue) >> 1),image->file); (void) fputc(DownScale(p->red),image->file); full=False; } else { y=p->red; u=p->green; v=p->blue; full=True; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } TransformRGBImage(image,YCbCrColorspace); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e V I C A R I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteVICARImage writes an image in the VICAR rasterfile format. % Vicar files contain a text header, followed by one or more planes of binary % grayscale image data. Vicar files are designed to allow many planes to be % stacked together to form image cubes. This routine only writes a single % grayscale plane. % % Function WriteVICARImage was written contributed by % gorelick@esther.la.asu.edu. % % The format of the WriteVICARImage routine is: % % status=WriteVICARImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteVICARImage 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 WriteVICARImage(const ImageInfo *image_info,Image *image) { char header[MaxTextExtent], label[16]; int label_size; 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); /* Make a header. */ (void) sprintf(header,"LBLSIZE= FORMAT='BYTE' TYPE='IMAGE'"); (void) sprintf(header+Extent(header)," BUFSIZE=20000 DIM=2 EOL=0"); (void) sprintf(header+Extent(header), " RECSIZE=%u ORG='BSQ' NL=%u NS=%u NB=1",image->columns,image->rows, image->columns); (void) sprintf(header+Extent(header), " N1=0 N2=0 N3=0 N4=0 NBB=0 NLB=0"); (void) sprintf(header+Extent(header)," TASK='ImageMagick'"); /* Compute the size of the label. */ label_size=(Extent(header)+image->columns-1)/image->columns*image->columns; (void) sprintf(label,"%d",label_size); for (i=0 ; i < Extent(label); i++) header[i+8]=label[i]; /* Print the header and enough spaces to pad to label size. */ (void) fprintf(image->file, "%-*s",label_size,header); /* Convert MIFF to VICAR raster pixels. */ RGBTransformImage(image,GRAYColorspace); p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) (void) fputc(p->red,image->file); p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e V I F F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteVIFFImage writes an image to a file in the VIFF image format. % % The format of the WriteVIFFImage routine is: % % status=WriteVIFFImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteVIFFImage 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 WriteVIFFImage(const ImageInfo *image_info,Image *image) { #define VFF_CM_genericRGB 15 #define VFF_CM_NONE 0 #define VFF_DEP_IEEEORDER 0x2 #define VFF_DES_RAW 0 #define VFF_LOC_IMPLICIT 1 #define VFF_MAPTYP_NONE 0 #define VFF_MAPTYP_1_BYTE 1 #define VFF_MS_NONE 0 #define VFF_MS_ONEPERBAND 1 #define VFF_TYP_BIT 0 #define VFF_TYP_1_BYTE 1 typedef struct _ViffHeader { char identifier, file_type, release, version, machine_dependency, reserve[3], comment[512]; unsigned long rows, columns, subrows; long x_offset, y_offset; unsigned int x_pixel_size, y_pixel_size; unsigned long location_type, location_dimension, number_of_images, number_data_bands, data_storage_type, data_encode_scheme, map_scheme, map_storage_type, map_rows, map_columns, map_subrows, map_enable, maps_per_cycle, color_space_model; } ViffHeader; register int i, j; register RunlengthPacket *p; register unsigned char *q; unsigned char buffer[8], *viff_pixels; unsigned int scene; unsigned long packets; ViffHeader viff_header; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); scene=0; do { /* Initialize VIFF image structure. */ viff_header.identifier=(char) 0xab; viff_header.file_type=1; viff_header.release=1; viff_header.version=3; viff_header.machine_dependency=VFF_DEP_IEEEORDER; /* IEEE byte ordering */ *viff_header.comment='\0'; if (image->comments != (char *) NULL) { (void) strncpy(viff_header.comment,image->comments, Min(Extent(image->comments),511)); viff_header.comment[Min(Extent(image->comments),511)]='\0'; } viff_header.rows=image->columns; viff_header.columns=image->rows; viff_header.subrows=0; viff_header.x_offset=(~0); viff_header.y_offset=(~0); viff_header.x_pixel_size=0; viff_header.y_pixel_size=0; viff_header.location_type=VFF_LOC_IMPLICIT; viff_header.location_dimension=0; viff_header.number_of_images=1; viff_header.data_encode_scheme=VFF_DES_RAW; viff_header.map_scheme=VFF_MS_NONE; viff_header.map_storage_type=VFF_MAPTYP_NONE; viff_header.map_rows=0; viff_header.map_columns=0; viff_header.map_subrows=0; viff_header.map_enable=1; /* no colormap */ viff_header.maps_per_cycle=0; if (!IsPseudoClass(image) && !IsGrayImage(image)) { /* Full color VIFF raster. */ viff_header.number_data_bands=image->matte ? 4 : 3; viff_header.color_space_model=VFF_CM_genericRGB; viff_header.data_storage_type=VFF_TYP_1_BYTE; packets=image->columns*image->rows*viff_header.number_data_bands; } else { viff_header.number_data_bands=1; viff_header.color_space_model=VFF_CM_NONE; viff_header.data_storage_type=VFF_TYP_1_BYTE; packets=image->columns*image->rows; if (!IsGrayImage(image)) { /* Colormapped VIFF raster. */ viff_header.map_scheme=VFF_MS_ONEPERBAND; viff_header.map_storage_type=VFF_MAPTYP_1_BYTE; viff_header.map_rows=3; viff_header.map_columns=image->colors; } else if (image->colors == 2) { /* Monochrome VIFF raster. */ viff_header.data_storage_type=VFF_TYP_BIT; packets=((image->columns+7) >> 3)*image->rows; } } /* Write VIFF image header (pad to 1024 bytes). */ buffer[0]=viff_header.identifier; buffer[1]=viff_header.file_type; buffer[2]=viff_header.release; buffer[3]=viff_header.version; buffer[4]=viff_header.machine_dependency; buffer[5]=viff_header.reserve[0]; buffer[6]=viff_header.reserve[1]; buffer[7]=viff_header.reserve[2]; (void) fwrite((char *) buffer,1,8,image->file); (void) fwrite((char *) viff_header.comment,1,512,image->file); MSBFirstWriteLong(viff_header.rows,image->file); MSBFirstWriteLong(viff_header.columns,image->file); MSBFirstWriteLong(viff_header.subrows,image->file); MSBFirstWriteLong((unsigned long) viff_header.x_offset,image->file); MSBFirstWriteLong((unsigned long) viff_header.y_offset,image->file); MSBFirstWriteLong((unsigned long) viff_header.x_pixel_size,image->file); MSBFirstWriteLong((unsigned long) viff_header.y_pixel_size,image->file); MSBFirstWriteLong(viff_header.location_type,image->file); MSBFirstWriteLong(viff_header.location_dimension,image->file); MSBFirstWriteLong(viff_header.number_of_images,image->file); MSBFirstWriteLong(viff_header.number_data_bands,image->file); MSBFirstWriteLong(viff_header.data_storage_type,image->file); MSBFirstWriteLong(viff_header.data_encode_scheme,image->file); MSBFirstWriteLong(viff_header.map_scheme,image->file); MSBFirstWriteLong(viff_header.map_storage_type,image->file); MSBFirstWriteLong(viff_header.map_rows,image->file); MSBFirstWriteLong(viff_header.map_columns,image->file); MSBFirstWriteLong(viff_header.map_subrows,image->file); MSBFirstWriteLong(viff_header.map_enable,image->file); MSBFirstWriteLong(viff_header.maps_per_cycle,image->file); MSBFirstWriteLong(viff_header.color_space_model,image->file); for (i=0; i < 420; i++) (void) fputc('\0',image->file); /* Convert MIFF to VIFF raster pixels. */ viff_pixels=(unsigned char *) malloc(packets*sizeof(unsigned char)); if (viff_pixels == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); p=image->pixels; q=viff_pixels; if (!IsPseudoClass(image) && !IsGrayImage(image)) { unsigned long offset; /* Convert DirectClass packet to VIFF RGB pixel. */ offset=image->columns*image->rows; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { *q=DownScale(p->red); *(q+offset)=DownScale(p->green); *(q+offset*2)=DownScale(p->blue); if (image->matte) *(q+offset*3)=DownScale(p->index); q++; } p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } else if (!IsGrayImage(image)) { unsigned char *viff_colormap; /* Dump colormap to file. */ viff_colormap=(unsigned char *) malloc(image->colors*3*sizeof(unsigned char)); if (viff_colormap == (unsigned char *) NULL) PrematureExit("Unable to allocate memory",image); q=viff_colormap; for (i=0; i < image->colors; i++) *q++=DownScale(image->colormap[i].red); for (i=0; i < image->colors; i++) *q++=DownScale(image->colormap[i].green); for (i=0; i < image->colors; i++) *q++=DownScale(image->colormap[i].blue); (void) fwrite((char *) viff_colormap,1,(int) image->colors*3, image->file); free((char *) viff_colormap); /* Convert PseudoClass packet to VIFF colormapped pixels. */ q=viff_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); } } else if (image->colors == 2) { register unsigned char bit, byte, polarity; register int x; /* Convert PseudoClass image to a VIFF monochrome image. */ polarity= Intensity(image->colormap[0]) > Intensity(image->colormap[1]); x=0; 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|=0x80; 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); } } else { /* Convert PseudoClass packet to VIFF grayscale pixel. */ for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) *q++=p->red; p++; if (QuantumTick(i,image) && (image->previous == (Image *) NULL)) ProgressMonitor(SaveImageText,i,image->packets); } } (void) fwrite((char *) viff_pixels,1,(int) packets,image->file); free((char *) viff_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 X I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteXImage writes an image to an X server. % % The format of the WriteXImage routine is: % % status=WriteXImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteXImage return True if the image is displayed on % the X server. 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 WriteXImage(const ImageInfo *image_info,Image *image) { Atom wm_delete_window, wm_protocols; char name[MaxTextExtent]; Display *display; register char *p; unsigned int status; Window root_window; XGCValues context_values; XResourceInfo resource_info; XrmDatabase resource_database; XEvent event; XPixelInfo pixel_info; XStandardColormap *map_info; XVisualInfo *visual_info; XWindowInfo window_info; /* Open X server connection. */ display=XOpenDisplay(image_info->server_name); if (display == (Display *) NULL) { Warning("Unable to connect to X server", XDisplayName(image_info->server_name)); return(False); } /* Set our forgiving error handler. */ XSetErrorHandler(XError); /* Get user defaults from X resource database. */ resource_database=XGetResourceDatabase(display,client_name); XGetResourceInfo(resource_database,client_name,&resource_info); /* Allocate standard colormap. */ map_info=XAllocStandardColormap(); if (map_info == (XStandardColormap *) NULL) Warning("Unable to create standard colormap","Memory allocation failed"); /* Initialize visual info. */ visual_info=XBestVisualInfo(display,map_info,&resource_info); if (visual_info == (XVisualInfo *) NULL) Warning("Unable to get visual",resource_info.visual_type); map_info->colormap=(Colormap) NULL; pixel_info.pixels=(unsigned long *) NULL; pixel_info.gamma_map=(XColor *) NULL; if ((map_info == (XStandardColormap *) NULL) || (visual_info == (XVisualInfo *) NULL)) { XFreeResources(display,visual_info,map_info,&pixel_info, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); DestroyImage(image); return(False); } /* Initialize Standard Colormap. */ ProgressMonitor(SaveImageText,100,400); XMakeStandardColormap(display,visual_info,&resource_info,image,map_info, &pixel_info); /* Initialize window info structure. */ window_info.id=(Window) NULL; XGetWindowInfo(display,visual_info,map_info,&pixel_info,(XFontStruct *) NULL, &resource_info,&window_info); window_info.name=name; p=image->filename+Extent(image->filename)-1; while ((p > image->filename) && (*(p-1) != *BasenameSeparator)) p--; (void) sprintf(window_info.name,"%s[%u]",p,image->scene); if (image->scene == 0) (void) sprintf(window_info.name,"%s",p); window_info.width=image->columns; window_info.height=image->rows; window_info.attributes.event_mask=ButtonPressMask | ExposureMask; XMakeWindow(display,XRootWindow(display,visual_info->screen),(char **) NULL,0, (XClassHint *) NULL,(XWMHints *) NULL,&window_info); root_window=XRootWindow(display,XDefaultScreen(display)); XSetTransientForHint(display,window_info.id,root_window); window_info.x=0; window_info.y=0; window_info.shared_memory=False; /* Graphic context. */ context_values.background=pixel_info.background_color.pixel; context_values.foreground=pixel_info.foreground_color.pixel; pixel_info.annotate_context=XCreateGC(display,window_info.id,GCBackground | GCForeground,&context_values); if (pixel_info.annotate_context == (GC) NULL) Error("Unable to create graphic context",(char *) NULL); window_info.annotate_context=pixel_info.annotate_context; context_values.background=pixel_info.foreground_color.pixel; context_values.foreground=pixel_info.background_color.pixel; pixel_info.highlight_context=XCreateGC(display,window_info.id,GCBackground | GCForeground,&context_values); if (pixel_info.annotate_context == (GC) NULL) Error("Unable to create graphic context",(char *) NULL); window_info.highlight_context=pixel_info.highlight_context; pixel_info.widget_context=(GC) NULL; window_info.widget_context=(GC) NULL; /* Initialize X image. */ ProgressMonitor(SaveImageText,250,400); status=XMakeImage(display,&resource_info,&window_info,image,image->columns, image->rows); if (status == False) { XFreeResources(display,visual_info,map_info,&pixel_info, (XFontStruct *) NULL,&resource_info,&window_info); PrematureExit("Unable to make X image",image); } free(window_info.ximage->data); window_info.ximage->data=(char *) NULL; /* Display image and wait for button press to exit. */ ProgressMonitor(SaveImageText,400,400); wm_protocols=XInternAtom(display,"WM_PROTOCOLS",False); wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",False); XMapWindow(display,window_info.id); for ( ; ; ) { XNextEvent(display,&event); if (event.type == ButtonPress) break; if (event.type == ClientMessage) if (event.xclient.message_type == wm_protocols) if (*event.xclient.data.l == wm_delete_window) if (event.xclient.window == window_info.id) break; if (event.type == Expose) XRefreshWindow(display,&window_info,&event); } XWithdrawWindow(display,window_info.id,window_info.screen); /* Free X resources. */ XFreeResources(display,visual_info,map_info,&pixel_info,(XFontStruct *) NULL, &resource_info,&window_info); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e X B M I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure WriteXBMImage writes an image to a file in the X bitmap format. % % The format of the WriteXBMImage routine is: % % status=WriteXBMImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteXBMImage 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 WriteXBMImage(const ImageInfo *image_info,Image *image) { char name[MaxTextExtent]; register int i, j, x; register char *q; register RunlengthPacket *p; register unsigned char bit, byte, polarity; unsigned int count; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Write X bitmap header. */ (void) strcpy(name,image->filename); q=name; while ((*q != '.') && (*q != '\0')) q++; if (*q == '.') *q='\0'; (void) fprintf(image->file,"#define %s_width %u\n",name,image->columns); (void) fprintf(image->file,"#define %s_height %u\n",name,image->rows); (void) fprintf(image->file,"static char %s_bits[] = {\n",name); (void) fprintf(image->file," "); /* Convert MIFF to X bitmap pixels. */ 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; count=0; x=0; p=image->pixels; (void) fprintf(image->file," "); 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) { /* Write a bitmap byte to the image file. */ (void) fprintf(image->file,"0x%02x, ",(unsigned int) (byte & 0xff)); count++; if (count == 12) { (void) fprintf(image->file,"\n "); count=0; }; bit=0; byte=0; } x++; if (x == image->columns) { if (bit != 0) { /* Write a bitmap byte to the image file. */ byte>>=(8-bit); (void) fprintf(image->file,"0x%02x, ",(unsigned int) (byte & 0xff)); count++; if (count == 12) { (void) fprintf(image->file,"\n "); count=0; }; bit=0; byte=0; }; x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } (void) fprintf(image->file,"};\n"); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e X C I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteXCImage writes an image in the X constant image format. % % The format of the WriteXCImage routine is: % % status=WriteXCImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteXCImage 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 WriteXCImage(const ImageInfo *image_info,Image *image) { unsigned int status; Warning("Cannot write XC images",image->filename); status=WriteMIFFImage(image_info,image); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e X P M I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure WriteXPMImage writes an image to a file in the X pixmap format. % % The format of the WriteXPMImage routine is: % % status=WriteXPMImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteXPMImage 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 WriteXPMImage(const ImageInfo *image_info,Image *image) { #define MaxCixels 92 static char Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; char name[MaxTextExtent], symbol[MaxTextExtent]; double distance_squared, min_distance; int distance, j, k, y; register int i, x; register RunlengthPacket *p; register XColorlist *q; unsigned int characters_per_pixel, colors, transparent; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); transparent=False; if (image->class == PseudoClass) { CompressColormap(image); colors=image->colors; } else { QuantizeInfo quantize_info; unsigned char *matte_image; /* Convert DirectClass to PseudoClass image. */ matte_image=(unsigned char *) NULL; if (image->matte) { /* Map 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 (matte_image[i]) transparent=True; p++; } } GetQuantizeInfo(&quantize_info); quantize_info.dither=image_info->dither; QuantizeImage(&quantize_info,image); SyncImage(image); CompressColormap(image); colors=image->colors; if (transparent) { if (!UncompressImage(image)) return(False); colors++; p=image->pixels; for (i=0; i < image->packets; i++) { if (matte_image[i]) p->index=image->colors; p++; } } if (matte_image != (unsigned char *) NULL) free((char *) matte_image); } /* Compute the character per pixel. */ characters_per_pixel=1; for (k=MaxCixels; colors > k; k*=MaxCixels) characters_per_pixel++; /* XPM header. */ (void) fprintf(image->file,"/* XPM */\n"); (void) fprintf(image->file,"static char *magick[] = {\n"); (void) fprintf(image->file,"/* columns rows colors chars-per-pixel */\n"); (void) fprintf(image->file,"\"%u %u %u %d\",\n",image->columns, image->rows,colors,characters_per_pixel); for (i=0; i < colors; i++) { ColorPacket *p; /* Define XPM color. */ p=image->colormap+i; (void) sprintf(name,"#%02x%02x%02x%c",(unsigned int) p->red, (unsigned int) p->green,(unsigned int) p->blue,'\0'); if (QuantumDepth > 8) (void) sprintf(name,"#%04x%04x%04x%c",(unsigned int) p->red, (unsigned int) p->green,(unsigned int) p->blue,'\0'); min_distance=3.0*65536.0*65536.0; for (q=XPMColorlist; q->name != (char *) NULL; q++) { distance=(int) DownScale(p->red)-(int) q->red; distance_squared=(unsigned int) (distance*distance); distance=(int) DownScale(p->green)-(int) q->green; distance_squared+=(unsigned int) (distance*distance); distance=(int) DownScale(p->blue)-(int) q->blue; distance_squared+=(unsigned int) (distance*distance); if (distance_squared <= min_distance) { min_distance=distance_squared; if (min_distance == 0.0) (void) strcpy(name,q->name); } } if (transparent) if (i == (colors-1)) (void) strcpy(name,"None"); /* Write XPM color. */ k=i % MaxCixels; symbol[0]=Cixel[k]; for (j=1; j < characters_per_pixel; j++) { k=((i-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) fprintf(image->file,"\"%s c %s\",\n",symbol,name); } /* Define XPM pixels. */ (void) fprintf(image->file,"/* pixels */\n"); p=image->pixels; image->runlength=p->length+1; for (y=0; y < image->rows; y++) { (void) fprintf(image->file,"\""); for (x=0; x < image->columns; x++) { if (image->runlength != 0) image->runlength--; else { p++; image->runlength=p->length; } k=p->index % MaxCixels; symbol[0]=Cixel[k]; for (j=1; j < characters_per_pixel; j++) { k=(((int) p->index-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) fprintf(image->file,"%s",symbol); } (void) fprintf(image->file,"\"%s\n",(y == (image->rows-1) ? "" : ",")); ProgressMonitor(SaveImageText,y,image->rows); } (void) fprintf(image->file,"};\n"); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e Y U V I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteYUVImage writes an image to a file in the digital YUV % (CCIR 601 4:1:1) format. % % The format of the WriteYUVImage routine is: % % status=WriteYUVImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteYUVImage 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 WriteYUVImage(const ImageInfo *image_info,Image *image) { Image *downsampled_image; register int i, j; register RunlengthPacket *p; 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); } /* Initialize Y channel. */ if (image_info->interlace == PartitionInterlace) { AppendImageFormat("Y",image->filename); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } RGBTransformImage(image,YCbCrColorspace); 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); p++; } /* Scale image. */ ProgressMonitor(SaveImageText,100,400); image->orphan=True; downsampled_image=MinifyImage(image); image->orphan=False; if (downsampled_image == (Image *) NULL) PrematureExit("Unable to scale image",image); /* Initialize U channel. */ if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("U",image->filename); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } ProgressMonitor(SaveImageText,200,400); p=downsampled_image->pixels; for (i=0; i < downsampled_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) (void) fputc(DownScale(p->green),image->file); p++; } /* Initialize V channel. */ if (image_info->interlace == PartitionInterlace) { CloseImage(image); AppendImageFormat("V",image->filename); OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); } ProgressMonitor(SaveImageText,300,400); p=downsampled_image->pixels; for (i=0; i < downsampled_image->packets; i++) { for (j=0; j <= ((int) p->length); j++) (void) fputc(DownScale(p->blue),image->file); p++; } DestroyImage(downsampled_image); TransformRGBImage(image,YCbCrColorspace); if (image_info->interlace == PartitionInterlace) (void) strcpy(image->filename,image_info->filename); ProgressMonitor(SaveImageText,400,400); CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e X W D I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteXWDImage writes an image to a file in X window dump % rasterfile format. % % The format of the WriteXWDImage routine is: % % status=WriteXWDImage(image_info,image) % % A description of each parameter follows. % % o status: Function WriteXWDImage 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 WriteXWDImage(const ImageInfo *image_info,Image *image) { int x; register int i, j, k; register RunlengthPacket *p; unsigned int bits_per_pixel, bytes_per_line, scanline_pad; unsigned long lsb_first; XWDFileHeader xwd_header; /* Open output image file. */ OpenImage(image_info,image,WriteBinaryType); if (image->file == (FILE *) NULL) PrematureExit("Unable to open file",image); /* Initialize XWD file header. */ xwd_header.header_size=sz_XWDheader+Extent(image->filename)+1; xwd_header.file_version=(CARD32) XWD_FILE_VERSION; xwd_header.pixmap_format=(CARD32) ZPixmap; xwd_header.pixmap_depth=(CARD32) (image->class == DirectClass ? 24 : 8); xwd_header.pixmap_width=(CARD32) image->columns; xwd_header.pixmap_height=(CARD32) image->rows; xwd_header.xoffset=(CARD32) 0; xwd_header.byte_order=(CARD32) MSBFirst; xwd_header.bitmap_unit=(CARD32) (image->class == DirectClass ? 32 : 8); xwd_header.bitmap_bit_order=(CARD32) MSBFirst; xwd_header.bitmap_pad=(CARD32) (image->class == DirectClass ? 32 : 8); bits_per_pixel=(image->class == DirectClass ? 24 : 8); xwd_header.bits_per_pixel=(CARD32) bits_per_pixel; bytes_per_line=(CARD32) ((((xwd_header.bits_per_pixel* xwd_header.pixmap_width)+((xwd_header.bitmap_pad)-1))/ (xwd_header.bitmap_pad))*((xwd_header.bitmap_pad) >> 3)); xwd_header.bytes_per_line=(CARD32) bytes_per_line; xwd_header.visual_class=(CARD32) (image->class == DirectClass ? DirectColor : PseudoColor); xwd_header.red_mask=(CARD32) (image->class == DirectClass ? 0xff0000 : 0); xwd_header.green_mask=(CARD32) (image->class == DirectClass ? 0xff00 : 0); xwd_header.blue_mask=(CARD32) (image->class == DirectClass ? 0xff : 0); xwd_header.bits_per_rgb=(CARD32) (image->class == DirectClass ? 24 : 8); xwd_header.colormap_entries=(CARD32) (image->class == DirectClass ? 256 : image->colors); xwd_header.ncolors=(image->class == DirectClass ? 0 : image->colors); xwd_header.window_width=(CARD32) image->columns; xwd_header.window_height=(CARD32) image->rows; xwd_header.window_x=0; xwd_header.window_y=0; xwd_header.window_bdrwidth=(CARD32) 0; /* Write XWD header. */ lsb_first=1; if (*(char *) &lsb_first) MSBFirstOrderLong((char *) &xwd_header,sizeof(xwd_header)); (void) fwrite((char *) &xwd_header,sz_XWDheader,1,image->file); (void) fwrite((char *) image->filename,1,Extent(image->filename)+1, image->file); if (image->class == PseudoClass) { XColor *colors; XWDColor color; /* Dump colormap to file. */ colors=(XColor *) malloc(image->colors*sizeof(XColor)); if (colors == (XColor *) NULL) PrematureExit("Unable to allocate memory",image); for (i=0; i < image->colors; i++) { colors[i].pixel=i; colors[i].red=XUpScale(image->colormap[i].red); colors[i].green=XUpScale(image->colormap[i].green); colors[i].blue=XUpScale(image->colormap[i].blue); colors[i].flags=DoRed | DoGreen | DoBlue; colors[i].pad=0; if (*(char *) &lsb_first) { MSBFirstOrderLong((char *) &colors[i].pixel,sizeof(long)); MSBFirstOrderShort((char *) &colors[i].red,3*sizeof(short)); } } for (i=0; i < image->colors; i++) { color.pixel=(unsigned int) colors[i].pixel; color.red=colors[i].red; color.green=colors[i].green; color.blue=colors[i].blue; color.flags=colors[i].flags; (void) fwrite((char *) &color,sz_XWDColor,1,image->file); } free((char *) colors); } /* Convert MIFF to XWD raster pixels. */ scanline_pad=(unsigned int) (bytes_per_line-((image->columns*bits_per_pixel) >> 3)); x=0; p=image->pixels; for (i=0; i < image->packets; i++) { for (j=0; j <= ((int) p->length); j++) { if (image->class == PseudoClass) (void) fputc(p->index,image->file); else { (void) fputc(DownScale(p->red),image->file); (void) fputc(DownScale(p->green),image->file); (void) fputc(DownScale(p->blue),image->file); } x++; if (x == image->columns) { for (k=0; k < scanline_pad; k++) (void) fputc(0,image->file); x=0; } } p++; if (QuantumTick(i,image)) ProgressMonitor(SaveImageText,i,image->packets); } CloseImage(image); return(True); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function WriteImage writes an image to a file. You can specify a % particular image format by prefixing the file with the image type and a % colon (i.e. ps:image) or specify the image type as the filename suffix % (i.e. image.ps). % % The format of the WriteImage routine is: % % status=WriteImage(image_info,image) % % A description of each parameter follows: % % o status: Function WriteImage 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. % % */ Export unsigned int WriteImage(ImageInfo *image_info,Image *image) { unsigned int status; /* Call appropriate image writer based on image type. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->filename != (char *) NULL); assert(image != (Image *) NULL); status=False; (void) strcpy(image_info->filename,image->filename); (void) strcpy(image_info->magick,image->magick); SetImageInfo(image_info,True); SetNumberScenes(image); (void) strcpy(image->filename,image_info->filename); switch (*image_info->magick) { case 'A': { status=WriteAVSImage(image_info,image); break; } case 'B': { if (strcmp(image_info->magick,"BIE") == 0) { status=WriteJBIGImage(image_info,image); break; } status=WriteBMPImage(image_info,image); break; } case 'C': { if (strcmp(image_info->magick,"CGM") == 0) { status=WriteCGMImage(image_info,image); break; } status=WriteCMYKImage(image_info,image); break; } case 'D': { if (strcmp(image_info->magick,"DCX") == 0) { status=WritePCXImage(image_info,image); break; } status=WriteBMPImage(image_info,image); break; } case 'E': { if (strcmp(image_info->magick,"EPS2") == 0) { status=WritePS2Image(image_info,image); break; } status=WritePSImage(image_info,image); break; } case 'F': { if (strcmp(image_info->magick,"FAX") == 0) { status=WriteFAXImage(image_info,image); break; } if (strcmp(image_info->magick,"FITS") == 0) { status=WriteFITSImage(image_info,image); break; } status=WriteHTMLImage(image_info,image); break; } case 'G': { if (strncmp(image_info->magick,"GIF",3) == 0) { status=WriteGIFImage(image_info,image); break; } if (strcmp(image_info->magick,"GRADATION") == 0) { status=WriteGRADATIONImage(image_info,image); break; } if (strcmp(image_info->magick,"GRANITE") == 0) { status=WriteLOGOImage(image_info,image); break; } if (strcmp(image_info->magick,"GRAY") == 0) { status=WriteGRAYImage(image_info,image); break; } status=WriteFAXImage(image_info,image); break; } case 'H': { if (strcmp(image_info->magick,"H") == 0) { status=WriteLOGOImage(image_info,image); break; } if (strcmp(image_info->magick,"HDF") == 0) { status=WriteHDFImage(image_info,image); break; } if (strcmp(image_info->magick,"HISTOGRAM") == 0) { status=WriteHISTOGRAMImage(image_info,image); break; } status=WriteHTMLImage(image_info,image); break; } case 'J': { if (strcmp(image_info->magick,"JBIG") == 0) { status=WriteJBIGImage(image_info,image); break; } status=WriteJPEGImage(image_info,image); break; } case 'L': { status=WriteLOGOImage(image_info,image); break; } case 'M': { if (strcmp(image_info->magick,"MAP") == 0) { status=WriteMAPImage(image_info,image); break; } if (strcmp(image_info->magick,"MATTE") == 0) { status=WriteMATTEImage(image_info,image); break; } if (strcmp(image_info->magick,"MIFF") == 0) { status=WriteMIFFImage(image_info,image); break; } if (strcmp(image_info->magick,"MNG") == 0) { status=WritePNGImage(image_info,image); break; } if (strcmp(image_info->magick,"MONO") == 0) { status=WriteMONOImage(image_info,image); break; } if ((strcmp(image_info->magick,"MPEG") == 0) || (strcmp(image_info->magick,"MPG") == 0)) { status=WriteMPEGImage(image_info,image); break; } status=WriteMTVImage(image_info,image); break; } case 'N': { if (strcmp(image_info->magick,"NETSCAPE") == 0) { status=WriteLOGOImage(image_info,image); break; } break; } case 'P': { if (strcmp(image_info->magick,"PCD") == 0) { status=WritePCDImage(image_info,image); break; } if (strcmp(image_info->magick,"PCL") == 0) { status=WritePCLImage(image_info,image); break; } if (strcmp(image_info->magick,"PCX") == 0) { status=WritePCXImage(image_info,image); break; } if (strcmp(image_info->magick,"PDF") == 0) { status=WritePDFImage(image_info,image); break; } if (strcmp(image_info->magick,"PICT") == 0) { status=WritePICTImage(image_info,image); break; } if (strcmp(image_info->magick,"PLASMA") == 0) { status=WritePLASMAImage(image_info,image); break; } if (strcmp(image_info->magick,"PM") == 0) { status=WriteXPMImage(image_info,image); break; } if (strcmp(image_info->magick,"PNG") == 0) { status=WritePNGImage(image_info,image); break; } if (strcmp(image_info->magick,"PREVIEW") == 0) { status=WritePREVIEWImage(image_info,image); break; } if (strcmp(image_info->magick,"PS") == 0) { status=WritePSImage(image_info,image); break; } if (strcmp(image_info->magick,"PS2") == 0) { status=WritePS2Image(image_info,image); break; } status=WritePNMImage(image_info,image); break; } case 'R': { if (strcmp(image_info->magick,"RAD") == 0) { status=WriteRADIANCEImage(image_info,image); break; } if (strcmp(image_info->magick,"RAS") == 0) { status=WriteSUNImage(image_info,image); break; } if (strncmp(image_info->magick,"RGB",3) == 0) { status=WriteRGBImage(image_info,image); break; } if (strncmp(image_info->magick,"RLA",3) == 0) { status=WriteRLAImage(image_info,image); break; } status=WriteRLEImage(image_info,image); break; } case 'S': { if (strcmp(image_info->magick,"SGI") == 0) { status=WriteSGIImage(image_info,image); break; } if (strcmp(image_info->magick,"SHTML") == 0) { status=WriteHTMLImage(image_info,image); break; } status=WriteSUNImage(image_info,image); break; } case 'T': { if (strcmp(image_info->magick,"TEXT") == 0) { status=WriteTEXTImage(image_info,image); break; } if (strcmp(image_info->magick,"TGA") == 0) { status=WriteTARGAImage(image_info,image); break; } if (strncmp(image_info->magick,"TIF",3) == 0) { status=WriteTIFFImage(image_info,image); break; } if (strcmp(image_info->magick,"TXT") == 0) { status=WriteTEXTImage(image_info,image); break; } status=WriteTILEImage(image_info,image); break; } case 'U': { status=WriteUYVYImage(image_info,image); break; } case 'V': { if (strcmp(image_info->magick,"VICAR") == 0) { status=WriteVICARImage(image_info,image); break; } if (strcmp(image_info->magick,"VID") == 0) { status=WriteMIFFImage(image_info,image); break; } status=WriteVIFFImage(image_info,image); break; } case 'X': { if (strcmp(image_info->magick,"X") == 0) { status=WriteXImage(image_info,image); break; } if (strcmp(image_info->magick,"XBM") == 0) { status=WriteXBMImage(image_info,image); break; } if (strcmp(image_info->magick,"XC") == 0) { status=WriteXCImage(image_info,image); break; } if (strcmp(image_info->magick,"XPM") == 0) { status=WriteXPMImage(image_info,image); break; } if (strcmp(image_info->magick,"XV") == 0) { status=WriteVIFFImage(image_info,image); break; } status=WriteXWDImage(image_info,image); break; } case 'Y': { status=WriteYUVImage(image_info,image); break; } default: status=WriteMIFFImage(image_info,image); } if (image->status) { Warning("An error has occurred writing to file",image->filename); return(False); } (void) strcpy(image->magick,image_info->magick); return(status); }