cristy@dupont.com (05/22/91)
Submitted-by: cristy@dupont.com Posting-number: Volume 13, Issue 20 Archive-name: imagemagic/part04 #!/bin/sh # this is img.04 (part 4 of ImageMagick) # do not concatenate these parts, unpack them in order with /bin/sh # file ImageMagick/image.c continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 4; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 if test ! -f _shar_wnt_.tmp; then echo 'x - still skipping ImageMagick/image.c' else echo 'x - continuing file ImageMagick/image.c' sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/image.c' && % % % % % % % D e s t r o y I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function DestroyImage deallocates memory associated with an image. % % The format of the DestroyImage routine is: % % DestroyImage(image) % % A description of each parameter follows: % % o image: The address of a structure of type Image. % % */ void DestroyImage(image) Image X *image; { X /* X Deallocate the image colormap. X */ X if (image->colormap != (ColorPacket *) NULL) X (void) free((char *) image->colormap); X /* X Deallocate the image pixels. X */ X if (image->pixels != (RunlengthPacket *) NULL) X (void) free((char *) image->pixels); X /* X Deallocate the image comments. X */ X if (image->comments != (char *) NULL) X (void) free((char *) image->comments); X /* X Deallocate the image structure. X */ X (void) free((char *) image); } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % E n h a n c e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function EnhanceImage creates a new image that is a copy of an existing % one with the noise reduced. It allocates the memory necessary for the new % Image structure and returns a pointer to the new image. % % EnhanceImage does a weighted average of pixels in a 5x5 cell around each % target pixel. Only pixels in the 5x5 cell that are within a RGB distance % threshold of the target pixel are averaged. % % Weights assume that the importance of neighboring pixels is inversely % proportional to the square of their distance from the target pixel. % % The scan only processes pixels that have a full set of neighbors. Pixels % in the top, bottom, left, and right pairs of rows and columns are omitted % from the scan. % % The format of the EnhanceImage routine is: % % enhanced_image=EnhanceImage(image) % % A description of each parameter follows: % % o enhanced_image: Function EnhanceImage returns a pointer to the image % after it is enhanced. A null image is returned if there is a memory % shortage. % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ Image *EnhanceImage(image) Image X *image; { #define Esum(weight) \ X red_distance=s->red-red; \ X green_distance=s->green-green; \ X blue_distance=s->blue-blue; \ X distance=red_distance*red_distance+green_distance*green_distance+ \ X blue_distance*blue_distance; \ X if (distance < Threshold) \ X { \ X total_red+=weight*(s->red); \ X total_green+=weight*(s->green); \ X total_blue+=weight*(s->blue); \ X total_weight+=weight; \ X } \ X s++; #define Threshold 2500 X X ColorPacket X *scanline; X X Image X *enhanced_image; X X int X blue_distance, X green_distance, X red_distance; X X register ColorPacket X *s, X *s0, X *s1, X *s2, X *s3, X *s4; X X register RunlengthPacket X *p, X *q; X X register unsigned int X x; X X unsigned char X blue, X green, X red; X X unsigned int X y; X X unsigned long X distance, X total_blue, X total_green, X total_red, X total_weight; X X if ((image->columns < 5) || (image->rows < 5)) X { X Warning("unable to enhance image","image size must exceed 4x4"); X return((Image *) NULL); X } X /* X Initialize enhanced image attributes. X */ X enhanced_image=CopyImage(image,image->columns,image->rows); X if (enhanced_image == (Image *) NULL) X { X Warning("unable to enhance image","memory allocation failed"); X return((Image *) NULL); X } X enhanced_image->class=DirectClass; X /* X Allocate scan line buffer for 5 rows of the image. X */ X scanline=(ColorPacket *) malloc(5*image->columns*sizeof(ColorPacket)); X if (scanline == (ColorPacket *) NULL) X { X Warning("unable to enhance image","memory allocation failed"); X DestroyImage(enhanced_image); X return((Image *) NULL); X } X /* X Read the first 4 rows of the image. X */ X p=image->pixels; X image->runlength=p->length+1; X s=scanline; X for (x=0; x < (image->columns*4); x++) X { X if (image->runlength > 0) X image->runlength--; X else X { X p++; X image->runlength=p->length; X } X s->red=p->red; X s->green=p->green; X s->blue=p->blue; X s->index=p->index; X s++; X } X /* X Dump first 2 scanlines of image. X */ X enhanced_image->packets=0; X q=enhanced_image->pixels; X q->length=MaxRunlength; X s=scanline; X for (x=0; x < (2*image->columns); x++) X { X if ((s->red == q->red) && (s->green == q->green) && (s->blue == q->blue) && X (q->length < MaxRunlength)) X q->length++; X else X { X if (enhanced_image->packets > 0) X q++; X enhanced_image->packets++; X q->red=s->red; X q->green=s->green; X q->blue=s->blue; X q->index=s->index; X q->length=0; X } X s++; X } X /* X Enhance each row. X */ X for (y=2; y < (image->rows-2); y++) X { X /* X Initialize sliding window pointers. X */ X s0=scanline+image->columns*((y-2) % 5); X s1=scanline+image->columns*((y-1) % 5); X s2=scanline+image->columns*(y % 5); X s3=scanline+image->columns*((y+1) % 5); X s4=scanline+image->columns*((y+2) % 5); X /* X Read another scan line. X */ X s=s4; X for (x=0; x < image->columns; x++) X { X if (image->runlength > 0) X image->runlength--; X else X { X p++; X image->runlength=p->length; X } X s->red=p->red; X s->green=p->green; X s->blue=p->blue; X s->index=p->index; X s++; X } X /* X Transfer first 2 pixels of the scanline. X */ X s=s2; X for (x=0; x < 2; x++) X { X if ((s->red == q->red) && (s->green == q->green) && X (s->blue == q->blue) && (q->length < MaxRunlength)) X q->length++; X else X { X if (enhanced_image->packets > 0) X q++; X enhanced_image->packets++; X q->red=0; X q->green=0; X q->blue=0; X q->index=0; X q->length=0; X } X s++; X } X for (x=2; x < (image->columns-2); x++) X { X /* X Compute weighted average of target pixel color components. X */ X total_red=0; X total_green=0; X total_blue=0; X total_weight=0; X s=s2+2; X red=s->red; X green=s->green; X blue=s->blue; X s=s0; X Esum(5); Esum(8); Esum(10); Esum(8); Esum(5); X s=s1; X Esum(8); Esum(20); Esum(40); Esum(20); Esum(8); X s=s2; X Esum(10); Esum(40); Esum(80); Esum(40); Esum(10); X s=s3; X Esum(8); Esum(20); Esum(40); Esum(20); Esum(8); X s=s4; X Esum(5); Esum(8); Esum(10); Esum(8); Esum(5); X red=(unsigned char) ((total_red+(total_weight >> 1)-1)/total_weight); X green=(unsigned char) ((total_green+(total_weight >> 1)-1)/total_weight); X blue=(unsigned char) ((total_blue+(total_weight >> 1)-1)/total_weight); X if ((red == q->red) && (green == q->green) && (blue == q->blue) && X (q->length < MaxRunlength)) X q->length++; X else X { X if (enhanced_image->packets > 0) X q++; X enhanced_image->packets++; X q->red=red; X q->green=green; X q->blue=blue; X q->index=0; X q->length=0; X } X s0++; X s1++; X s2++; X s3++; X s4++; X } X /* X Transfer last 2 pixels of the scanline. X */ X s=s2; X for (x=0; x < 2; x++) X { X if ((s->red == q->red) && (s->green == q->green) && X (s->blue == q->blue) && (q->length < MaxRunlength)) X q->length++; X else X { X if (enhanced_image->packets > 0) X q++; X enhanced_image->packets++; X q->red=s->red; X q->green=s->green; X q->blue=s->blue; X q->index=s->index; X q->length=0; X } X s++; X } X } X /* X Dump last 2 scanlines of pixels. X */ X s=scanline+image->columns*(y % 3); X for (x=0; x < (2*image->columns); x++) X { X if ((s->red == q->red) && (s->green == q->green) && X (s->blue == q->blue) && (q->length < MaxRunlength)) X q->length++; X else X { X if (enhanced_image->packets > 0) X q++; X enhanced_image->packets++; X q->red=s->red; X q->green=s->green; X q->blue=s->blue; X q->index=s->index; X q->length=0; X } X s++; X } X (void) free((char *) scanline); X enhanced_image->pixels=(RunlengthPacket *) realloc((char *) X enhanced_image->pixels,enhanced_image->packets*sizeof(RunlengthPacket)); X return(enhanced_image); } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % G a m m a I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure GammaImage converts the reference image to gamma corrected colors. % % The format of the GammaImage routine is: % % GammaImage(image,gamma) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % o gamma: A double precision value indicating the level of gamma % correction. % % */ void GammaImage(image,gamma) Image X *image; X double X gamma; { X register int X i; X X register RunlengthPacket X *p; X X unsigned char X gamma_map[MaxRgb+1]; X X /* X Initialize gamma table. X */ X for (i=0; i <= MaxRgb; i++) X gamma_map[i]=(unsigned char) X ((pow((double) i/MaxRgb,1.0/gamma)*MaxRgb)+0.5); X switch (image->class) X { X case DirectClass: X { X /* X Gamma-correct DirectClass image. X */ X p=image->pixels; X for (i=0; i < image->packets; i++) X { X p->red=gamma_map[p->red]; X p->green=gamma_map[p->green]; X p->blue=gamma_map[p->blue]; X p++; X } X break; X } X case PseudoClass: X { X register unsigned short X index; X X /* X Gamma-correct PseudoClass image. X */ X for (i=0; i < image->colors; i++) X { X image->colormap[i].red=gamma_map[image->colormap[i].red]; X image->colormap[i].green=gamma_map[image->colormap[i].green]; X image->colormap[i].blue=gamma_map[image->colormap[i].blue]; X } X p=image->pixels; X for (i=0; i < image->packets; i++) X { X index=p->index; X p->red=image->colormap[index].red; X p->green=image->colormap[index].green; X p->blue=image->colormap[index].blue; X p++; X } X break; X } X } } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % G r a y I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure GrayImage converts the reference image to gray scale colors. % % The format of the GrayImage routine is: % % GrayImage(image) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ void GrayImage(image) Image X *image; { X register int X i; X X register RunlengthPacket X *p; X X register unsigned char X gray_value; X X switch (image->class) X { X case DirectClass: X { X /* X Convert DirectClass packets to grayscale. X */ X p=image->pixels; X for (i=0; i < image->packets; i++) X { X gray_value=Intensity(*p); X p->red=gray_value; X p->green=gray_value; X p->blue=gray_value; X p++; X } X break; X } X case PseudoClass: X { X register unsigned short X index; X X /* X Convert PseudoClass packets to grayscale. X */ X for (i=0; i < image->colors; i++) X { X gray_value=Intensity(image->colormap[i]); X image->colormap[i].red=gray_value; X image->colormap[i].green=gray_value; X image->colormap[i].blue=gray_value; X } X p=image->pixels; X for (i=0; i < image->packets; i++) X { X index=p->index; X p->red=image->colormap[index].red; X p->green=image->colormap[index].green; X p->blue=image->colormap[index].blue; X p++; X } X break; X } X } } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % I n v e r s e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure InverseImage inverses the colors in the reference image. % % The format of the InverseImage routine is: % % InverseImage(image) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ void InverseImage(image) Image X *image; { X register int X i; X X register RunlengthPacket X *p; X X switch (image->class) X { X case DirectClass: X { X /* X Inverse DirectClass packets. X */ X p=image->pixels; X for (i=0; i < image->packets; i++) X { X p->red=(~p->red); X p->green=(~p->green); X p->blue=(~p->blue); X p++; X } X break; X } X case PseudoClass: X { X register unsigned short X index; X X /* X Inverse PseudoClass packets. X */ X for (i=0; i < image->colors; i++) X { X image->colormap[i].red=(~image->colormap[i].red); X image->colormap[i].green=(~image->colormap[i].green); X image->colormap[i].blue=(~image->colormap[i].blue); X } X p=image->pixels; X for (i=0; i < image->packets; i++) X { X index=p->index; X p->red=image->colormap[index].red; X p->green=image->colormap[index].green; X p->blue=image->colormap[index].blue; X p++; X } X break; X } X } } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % L i n e a r C o l o r m a p % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function LinearColormap sorts the colormap of a PseudoClass image by % linearly increasing intensity. % % The format of the LinearColormap routine is: % % LinearColormap(image) % % A description of each parameter follows: % % o image: A pointer to a Image structure. % % */ static int LinearCompare(color_1,color_2) register ColorPacket X *color_1, X *color_2; { X return((int) Intensity(*color_1)-(int) Intensity(*color_2)); } X void LinearColormap(image) Image X *image; { X register int X i; X X register RunlengthPacket X *p; X X register unsigned short X index; X X unsigned int X *pixels; X X if (image->class == DirectClass) X return; X /* X Allocate memory for pixel indexes. X */ X pixels=(unsigned int *) malloc(image->colors*sizeof(unsigned int)); X if (pixels == (unsigned int *) NULL) X { X Warning("unable to sort colormap","memory allocation failed"); X return; X } X /* X Assign index values to colormap entries. X */ X for (i=0; i < image->colors; i++) X image->colormap[i].index=i; X /* X Sort image colormap by increasing intensity. X */ X qsort((char *) image->colormap,(int) image->colors,sizeof(ColorPacket), X LinearCompare); X /* X Update image colormap indexes to sorted colormap order. X */ X for (i=0; i < image->colors; i++) X pixels[image->colormap[i].index]=i; X p=image->pixels; X for (i=0; i < image->packets; i++) X { X index=pixels[p->index]; X p->red=image->colormap[index].red; X p->green=image->colormap[index].green; X p->blue=image->colormap[index].blue; X p->index=index; X p++; X } X (void) free((char *) pixels); } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % N o i s y I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function NoisyImage creates a new image that is a copy of an existing % one with the noise reduced with a noise peak elimination filter. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The principal function of noise peak elimination filter is to smooth the % objects within an image without losing edge information and without % creating undesired structures. The central idea of the algorithm is to % replace a pixel with its next neighbor in value within a 3 x 3 window, % if this pixel has been found to be noise. A pixel is defined as noise % if and only if this pixel is a maximum or minimum within the 3 x 3 % window. % % The format of the NoisyImage routine is: % % noisy_image=NoisyImage(image) % % A description of each parameter follows: % % o noisy_image: Function NoisyImage returns a pointer to the image after % the noise is reduced. A null image is returned if there is a memory % shortage. % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ static int NoisyCompare(color_1,color_2) register ColorPacket X *color_1, X *color_2; { X return((int) Intensity(*color_1)-(int) Intensity(*color_2)); } X Image *NoisyImage(image) Image X *image; { X ColorPacket X pixel, X *scanline, X window[9]; X X Image X *noisy_image; X X int X i; X X register ColorPacket X *s, X *s0, X *s1, X *s2; X X register RunlengthPacket X *p, X *q; X X register unsigned int X x; X X unsigned int X y; X X if ((image->columns < 3) || (image->rows < 3)) X { X Warning("unable to reduce noise","the image size must exceed 2x2"); X return((Image *) NULL); X } X /* X Initialize noisy image attributes. X */ X noisy_image=CopyImage(image,image->columns,image->rows); X if (noisy_image == (Image *) NULL) X { X Warning("unable to reduce noise","memory allocation failed"); X return((Image *) NULL); X } X /* X Allocate scanline buffer for 3 rows of the image. X */ X scanline=(ColorPacket *) malloc(3*image->columns*sizeof(ColorPacket)); X if (scanline == (ColorPacket *) NULL) X { X Warning("unable to reduce noise","memory allocation failed"); X DestroyImage(noisy_image); X return((Image *) NULL); X } X /* X Preload the first 2 rows of the image. X */ X p=image->pixels; X image->runlength=p->length+1; X s=scanline; X for (x=0; x < (2*image->columns); x++) X { X if (image->runlength > 0) X image->runlength--; X else X { X p++; X image->runlength=p->length; X } X s->red=p->red; X s->green=p->green; X s->blue=p->blue; X s->index=p->index; X s++; X } X /* X Dump first scanline of image. X */ X noisy_image->packets=0; X q=noisy_image->pixels; X q->length=MaxRunlength; X s=scanline; X for (x=0; x < image->columns; x++) X { X if ((s->red == q->red) && (s->green == q->green) && (s->blue == q->blue) && X (q->length < MaxRunlength)) X q->length++; X else X { X if (noisy_image->packets > 0) X q++; X noisy_image->packets++; X q->red=s->red; X q->green=s->green; X q->blue=s->blue; X q->index=s->index; X q->length=0; X } X s++; X } X /* X Reduce noise in each row. X */ X for (y=1; y < (image->rows-1); y++) X { X /* X Initialize sliding window pointers. X */ X s0=scanline+image->columns*((y-1) % 3); X s1=scanline+image->columns*(y % 3); X s2=scanline+image->columns*((y+1) % 3); X /* X Read another scan line. X */ X s=s2; X for (x=0; x < image->columns; x++) X { X if (image->runlength > 0) X image->runlength--; X else X { X p++; X image->runlength=p->length; X } X s->red=p->red; X s->green=p->green; X s->blue=p->blue; X s->index=p->index; X s++; X } X /* X Transfer first pixel of the scanline. X */ X s=s1; X if ((s->red == q->red) && (s->green == q->green) && X (s->blue == q->blue) && (q->length < MaxRunlength)) X q->length++; X else X { X if (noisy_image->packets > 0) X q++; X noisy_image->packets++; X q->red=s->red; X q->green=s->green; X q->blue=s->blue; X q->index=s->index; X q->length=0; X } X for (x=1; x < (image->columns-1); x++) X { X /* X Sort window pixels by increasing intensity. X */ X s=s0; X window[0]=(*s++); X window[1]=(*s++); X window[2]=(*s++); X s=s1; X window[3]=(*s++); X window[4]=(*s++); X window[5]=(*s++); X s=s2; X window[6]=(*s++); X window[7]=(*s++); X window[8]=(*s++); X qsort((char *) window,9,sizeof(ColorPacket),NoisyCompare); X pixel=(*(s1+1)); X if (Intensity(pixel) == Intensity(window[0])) X { X /* X Pixel is minimum noise; replace with next neighbor in value. X */ X for (i=1; i < 8; i++) X if (Intensity(window[i]) != Intensity(window[0])) X break; X pixel=window[i]; X } X else X if (Intensity(pixel) == Intensity(window[8])) X { X /* X Pixel is maximum noise; replace with next neighbor in value. X */ X for (i=7; i > 0; i--) X if (Intensity(window[i]) != Intensity(window[8])) X break; X pixel=window[i]; X } X if ((pixel.red == q->red) && (pixel.green == q->green) && X (pixel.blue == q->blue) && (q->length < MaxRunlength)) X q->length++; X else X { X if (noisy_image->packets > 0) X q++; X noisy_image->packets++; X q->red=pixel.red; X q->green=pixel.green; X q->blue=pixel.blue; X q->index=pixel.index; X q->length=0; X } X s0++; X s1++; X s2++; X } X /* X Transfer last pixel of the scanline. X */ X s=s1; X if ((s->red == q->red) && (s->green == q->green) && X (s->blue == q->blue) && (q->length < MaxRunlength)) X q->length++; X else X { X if (noisy_image->packets > 0) X q++; X noisy_image->packets++; X q->red=s->red; X q->green=s->green; X q->blue=s->blue; X q->index=s->index; X q->length=0; X } X } X /* X Dump last scanline of pixels. X */ X s=scanline+image->columns*(y % 3); X for (x=0; x < image->columns; x++) X { X if ((s->red == q->red) && (s->green == q->green) && (s->blue == q->blue) && X (q->length < MaxRunlength)) X q->length++; X else X { X if (noisy_image->packets > 0) X q++; X noisy_image->packets++; X q->red=s->red; X q->green=s->green; X q->blue=s->blue; X q->index=s->index; X q->length=0; X } X s++; X } X (void) free((char *) scanline); X noisy_image->pixels=(RunlengthPacket *) realloc((char *) X noisy_image->pixels,noisy_image->packets*sizeof(RunlengthPacket)); X return(noisy_image); } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % N o r m a l i z e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure NormalizeImage normalizes the pixel values to span the full % range of color values. % % The format of the NormalizeImage routine is: % % NormalizeImage(image) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ void NormalizeImage(image) Image X *image; { X double X factor; X X register int X i; X X register int X max_intensity, X min_intensity, X intensity; X X register RunlengthPacket X *p; X X unsigned char X normalize_map[MaxRgb+1]; X X switch (image->class) X { X case DirectClass: X { X /* X Determine min and max intensity. X */ X p=image->pixels; X min_intensity=p->red; X max_intensity=p->red; X for (i=0; i < image->packets; i++) X { X if (p->red < min_intensity) X min_intensity=p->red; X else X if (p->red > max_intensity) X max_intensity=p->red; X if (p->green < min_intensity) X min_intensity=p->green; X else X if (p->green > max_intensity) X max_intensity=p->green; X if (p->blue < min_intensity) X min_intensity=p->blue; X else X if (p->blue > max_intensity) X max_intensity=p->blue; X p++; X } X if ((min_intensity == 0) && (max_intensity == MaxRgb)) X break; X /* X Initialize normalize table. X */ X factor=(double) MaxRgb/(double) (max_intensity-min_intensity); X for (i=min_intensity; i <= max_intensity; i++) X { X intensity=(i-min_intensity)*factor; X if (intensity < 0) X intensity=0; X else X if (intensity > MaxRgb) X intensity=MaxRgb; X normalize_map[i]=(unsigned char) intensity; X } X /* X Normalize DirectClass image. X */ X p=image->pixels; X for (i=0; i < image->packets; i++) X { X p->red=normalize_map[p->red]; X p->green=normalize_map[p->green]; X p->blue=normalize_map[p->blue]; X p++; X } X break; X } X case PseudoClass: X { X register unsigned short X index; X X /* X Determine min and max intensity. X */ X min_intensity=image->colormap[0].red; X max_intensity=image->colormap[0].red; X for (i=0; i < image->colors; i++) X { X if (image->colormap[i].red < min_intensity) X min_intensity=image->colormap[i].red; X else X if (image->colormap[i].red > max_intensity) X max_intensity=image->colormap[i].red; X if (image->colormap[i].green < min_intensity) X min_intensity=image->colormap[i].green; X else X if (image->colormap[i].green > max_intensity) X max_intensity=image->colormap[i].green; X if (image->colormap[i].blue < min_intensity) X min_intensity=image->colormap[i].blue; X else X if (image->colormap[i].blue > max_intensity) X max_intensity=image->colormap[i].blue; X } X if ((min_intensity == 0) && (max_intensity == MaxRgb)) X break; X /* X Initialize normalize table. X */ X factor=(double) MaxRgb/(double) (max_intensity-min_intensity); X for (i=min_intensity; i <= max_intensity; i++) X { X intensity=(i-min_intensity)*factor; X if (intensity < 0) X intensity=0; X else X if (intensity > MaxRgb) X intensity=MaxRgb; X normalize_map[i]=(unsigned char) intensity; X } X /* X Normalize PseudoClass image. X */ X for (i=0; i < image->colors; i++) X { X image->colormap[i].red=normalize_map[image->colormap[i].red]; X image->colormap[i].green=normalize_map[image->colormap[i].green]; X image->colormap[i].blue=normalize_map[image->colormap[i].blue]; X } X p=image->pixels; X for (i=0; i < image->packets; i++) X { X index=p->index; X p->red=image->colormap[index].red; X p->green=image->colormap[index].green; X p->blue=image->colormap[index].blue; X p++; X } X break; X } X } } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % P r i n t I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function PrintImage translates a MIFF image to encapsulated Postscript 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 PrintImage routine is: % % status=PrintImage(image,geometry) % % A description of each parameter follows: % % o status: Function PrintImage return True if the image is printed. % False is returned if the image file cannot be opened for printing. % % o image: The address of a structure of type Image; returned from % ReadImage. % % o geometry: A pointer to a standard window geometry string. % % */ unsigned int PrintImage(image,geometry) Image X *image; X char X *geometry; { #define PageBottomMargin 92 #define PageLeftMargin 16 #define PageWidth 612 #define PageHeight 792 X X static char X *Postscript[]= X { X "%", X "% Display a color image. The image is displayed in color on", X "% Postscript viewers or printers that support color, otherwise", X "% it is displayed as grayscale.", X "%", X "/buffer 512 string def", X "/byte 1 string def", X "/color_packet 3 string def", X "/compression 1 string def", X "/gray_packet 1 string def", X "/pixels 768 string def", X "", X "/DirectClassPacket", X "{", X " %", X " % Get a DirectClass packet.", X " %", X " % Parameters: ", X " % red.", X " % green.", X " % blue.", X " % length: number of pixels minus one of this color (optional).", X " %", X " currentfile color_packet readhexstring pop pop", X " compression 0 gt", X " {", X " /number_pixels 3 def", X " }", X " {", X " currentfile byte readhexstring pop 0 get", X " /number_pixels exch 1 add 3 mul def", X " } ifelse", X " 0 3 number_pixels 1 sub", X " {", X " pixels exch color_packet putinterval", X " } for", X " pixels 0 number_pixels getinterval", X "} bind def", X "", X "/DirectClassImage", X "{", X " %", X " % Display a DirectClass image.", X " %", X " systemdict /colorimage known", X " {", X " columns rows 8", X " [", X " columns 0 0", X " rows neg 0 rows", X " ]", X " { DirectClassPacket } false 3 colorimage", X " }", X " {", X " %", X " % No colorimage operator; convert to grayscale.", X " %", X " columns rows 8", X " [", X " columns 0 0", X " rows neg 0 rows", X " ]", X " { GrayDirectClassPacket } image", X " } ifelse", X "} bind def", X "", X "/GrayDirectClassPacket", X "{", X " %", X " % Get a DirectClass packet; convert to grayscale.", X " %", X " % Parameters: ", X " % red", X " % green", X " % blue", X " % length: number of pixels minus one of this color (optional).", X " %", X " currentfile color_packet readhexstring pop pop", X " color_packet 0 get 0.299 mul", X " color_packet 1 get 0.587 mul add", X " color_packet 2 get 0.114 mul add", X " cvi", X " /gray_packet exch def", X " compression 0 gt", X " {", X " /number_pixels 1 def", X " }", X " {", X " currentfile byte readhexstring pop 0 get", X " /number_pixels exch 1 add def", X " } ifelse", X " 0 1 number_pixels 1 sub", X " {", X " pixels exch gray_packet put", X " } for", X " pixels 0 number_pixels getinterval", X "} bind def", X "", X "/GrayPseudoClassPacket", X "{", X " %", X " % Get a PseudoClass packet; convert to grayscale.", X " %", X " % Parameters: ", X " % index: index into the colormap.", X " % length: number of pixels minus one of this color (optional).", X " %", X " currentfile byte readhexstring pop 0 get", X " /offset exch 3 mul def", X " /color_packet colormap offset 3 getinterval def", X " color_packet 0 get 0.299 mul", X " color_packet 1 get 0.587 mul add", X " color_packet 2 get 0.114 mul add", X " cvi", X " /gray_packet exch def", X " compression 0 gt", X " {", X " /number_pixels 1 def", X " }", X " {", X " currentfile byte readhexstring pop 0 get", X " /number_pixels exch 1 add def", X " } ifelse", X " 0 1 number_pixels 1 sub", X " {", X " pixels exch gray_packet put", X " } for", X " pixels 0 number_pixels getinterval", X "} bind def", X "", X "/PseudoClassPacket", X "{", X " %", X " % Get a PseudoClass packet.", X " %", X " % Parameters: ", X " % index: index into the colormap.", X " % length: number of pixels minus one of this color (optional).", X " %", X " %", X " currentfile byte readhexstring pop 0 get", X " /offset exch 3 mul def", X " /color_packet colormap offset 3 getinterval def", X " compression 0 gt", X " {", X " /number_pixels 3 def", X " }", X " {", X " currentfile byte readhexstring pop 0 get", X " /number_pixels exch 1 add 3 mul def", X " } ifelse", X " 0 3 number_pixels 1 sub", X " {", X " pixels exch color_packet putinterval", X " } for", X " pixels 0 number_pixels getinterval", X "} bind def", X "", X "/PseudoClassImage", X "{", X " %", X " % Display a PseudoClass image.", X " %", X " % Parameters: ", X " % colors: number of colors in the colormap.", X " % colormap: red, green, blue color packets.", X " %", X " currentfile buffer readline pop", X " token pop /colors exch def pop", X " /colors colors 3 mul def", X " /colormap colors string def", X " currentfile colormap readhexstring pop pop", X " systemdict /colorimage known", X " {", X " columns rows 8", X " [", X " columns 0 0", X " rows neg 0 rows", X " ]", X " { PseudoClassPacket } false 3 colorimage", X " }", X " {", X " %", X " % No colorimage operator; convert to grayscale.", X " %", X " columns rows 8", X " [", X " columns 0 0", X " rows neg 0 rows", X " ]", X " { GrayPseudoClassPacket } image", X " } ifelse", X "} bind def", X "", X "/DisplayImage", X "{", X " %", X " % Display a DirectClass or PseudoClass image.", X " %", X " % Parameters: ", X " % x & y translation.", X " % x & y scale.", X " % image columns & rows.", X " % class: 0-DirectClass or 1-PseudoClass.", X " % compression: 0-RunlengthEncodedCompression or 1-NoCompression.", X " % hex color packets.", X " %", X " gsave", X " currentfile buffer readline pop", X " token pop /x exch def", X " token pop /y exch def pop", X " x y translate", X " currentfile buffer readline pop", X " token pop /x exch def", X " token pop /y exch def pop", X " x y scale", X " currentfile buffer readline pop", X " token pop /columns exch def", X " token pop /rows exch def pop", X " currentfile buffer readline pop", X " token pop /class exch def pop", X " currentfile buffer readline pop", X " token pop /compression exch def pop", X " class 0 gt { PseudoClassImage } { DirectClassImage } ifelse", X " grestore", X " showpage", X "} bind def", X "", X "DisplayImage", X NULL X }; X X char X **q; X X int X center, X x, X y; X X register RunlengthPacket X *p; X X register int X i, X j; X X unsigned int X height, X width; X X /* X Open output image file. X */ X if (*image->filename == '-') X image->file=stdout; X else X image->file=fopen(image->filename,"w"); X if (image->file == (FILE *) NULL) X { X (void) fprintf(stderr,"%s: unable to print image, cannot open %s.\n", X application_name,image->filename); X return(False); X } X width=image->columns; X height=image->rows; X center=True; X if (geometry != (char *) NULL) X { X int X flags; X X /* X User specified Postscript page position. X */ X x=0; X y=0; X flags=XParseGeometry(geometry,&x,&y,&width,&height); X center=(flags & (XValue | YValue)) == 0; X if (flags & XValue) X if (flags & XNegative) X x=PageWidth+x-width; X if (flags & YValue) X if (flags & YNegative) X y=PageHeight+y-height; X y=PageHeight-y-height; X } X if (center) X { X int X delta_x, X delta_y; X X unsigned long X scale; X X /* X Center image on Postscript page. X */ X if (width > (PageWidth-(2*PageLeftMargin))) X { X scale=((PageWidth-(2*PageLeftMargin)) << 14)/width; X width=(width*scale) >> 14; X height=(height*scale) >> 14; X } X if (height > (PageHeight-(2*PageBottomMargin))) X { X scale=((PageHeight-(2*PageBottomMargin)) << 14)/height; X width=(width*scale) >> 14; X height=(height*scale) >> 14; X } X delta_x=PageWidth-(width+(2*PageLeftMargin)); X delta_y=PageHeight-(height+(2*PageBottomMargin)); X if (delta_x >= 0) X x=delta_x/2+PageLeftMargin; X else X x=PageLeftMargin; X if (delta_y >= 0) X y=delta_y/2+PageBottomMargin; X else X y=PageBottomMargin; X } X /* X Output encapsulated Postscript header. X */ X (void) fprintf(image->file,"%%!PS-Adobe-2.0 EPSF-2.0\n"); X (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n",x,y,x+width, X y+height); X (void) fprintf(image->file,"%%%%Creator: ImageMagick\n"); X (void) fprintf(image->file,"%%%%Title: %s\n",image->filename); X (void) fprintf(image->file,"%%%%EndComments\n"); X /* X Output encapsulated Postscript commands. X */ X for (q=Postscript; *q; q++) X (void) fprintf(image->file,"%s\n",*q); X /* X Output image data. X */ X (void) fprintf(image->file,"%d %d\n%d %d\n%d %d\n%d\n%d\n",x,y,width,height, X image->columns,image->rows,(image->class == PseudoClass), X image->compression == NoCompression); X x=0; X p=image->pixels; X switch (image->class) X { X case DirectClass: X { X switch (image->compression) X { X case RunlengthEncodedCompression: X default: X { X /* X Dump runlength-encoded DirectColor packets. X */ X for (i=0; i < image->packets; i++) X { X x++; X (void) fprintf(image->file,"%02x%02x%02x%02x",p->red,p->green, X p->blue,p->length); X if (x == 9) X { X x=0; X (void) fprintf(image->file,"\n"); X } X p++; X } X break; X } X case NoCompression: X { X /* X Dump DirectColor packets. X */ X for (i=0; i < image->packets; i++) X { X for (j=0; j <= p->length; j++) X { X x++; X (void) fprintf(image->file,"%02x%02x%02x",p->red,p->green, X p->blue); X if (x == 12) X { X x=0; X (void) fprintf(image->file,"\n"); X } X } X p++; X } X break; X } X } X break; X } X case PseudoClass: X { X /* X Dump number of colors, colormap, PseudoColor packets. X */ X (void) fprintf(image->file,"%d\n",image->colors); X for (i=0; i < image->colors; i++) X (void) fprintf(image->file,"%02x%02x%02x\n",image->colormap[i].red, X image->colormap[i].green,image->colormap[i].blue); X switch (image->compression) X { X case RunlengthEncodedCompression: X default: X { X for (i=0; i < image->packets; i++) X { X x++; X (void) fprintf(image->file,"%02x%02x",p->index,p->length); X if (x == 18) X { X x=0; X (void) fprintf(image->file,"\n"); X } X p++; X } X break; X } X case NoCompression: X { X for (i=0; i < image->packets; i++) X { X for (j=0; j <= p->length; j++) X { X x++; X (void) fprintf(image->file,"%02x",p->index); X if (x == 36) X { X x=0; X (void) fprintf(image->file,"\n"); X } X } X p++; X } X } X break; X } X } X } X (void) fprintf(image->file,"\n\n"); X (void) fprintf(image->file,"%%%%Trailer\n"); X if (image->file != stdin) X (void) fclose(image->file); X return(True); } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d D a t a % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadData reads data from the image file and returns it. If it % cannot read the requested number of items, False is returned indicating % an error. % % The format of the ReadData routine is: % % status=ReadData(data,size,number_items,file) % % A description of each parameter follows: % % o status: Function ReadData returns True if all the data requested % is obtained without error, otherwise False. % % o data: Specifies an area to place the information reuested from % the file. % % o size: Specifies an integer representing the length of an % individual item to be read from the file. % % o numer_items: Specifies an integer representing the number of items % to read from the file. % % o file: Specifies a file to read the data. % % */ unsigned int ReadData(data,size,number_items,file) char X *data; X int X size, X number_items; X FILE X *file; { X size*=number_items; X while (size > 0) X { X number_items=fread(data,1,size,file); X if (number_items <= 0) X return(False); X size-=number_items; X data+=number_items; X } X return(True); } X /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function ReadImage reads an 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 ReadImage routine is: % % image=ReadImage(filename) % % A description of each parameter follows: % % o image: Function ReadImage returns a pointer to the image after reading. % A null image is returned if there is a a memory shortage or if the % image cannot be read. % % o filename: Specifies the name of the image to read. % % */ Image *ReadImage(filename) char X *filename; { #define MaxKeywordLength 256 X X char X keyword[MaxKeywordLength], X value[MaxKeywordLength]; X X Image X *image; X X long int X count; X X register int X c, X i; X X register RunlengthPacket X *q; X X register unsigned char X blue, X green, X *p, X red; X X unsigned char X *pixels; X X unsigned int X packets, X packet_size, X status; X X /* X Allocate image structure. X */ X image=(Image *) malloc(sizeof(Image)); X if (image == (Image *) NULL) X return((Image *) NULL); X /* X Initialize Image structure. X */ X image->id=UnknownId; X image->class=DirectClass; X image->compression=NoCompression; X image->columns=0; X image->rows=0; X image->packets=0; X image->colors=0; X image->scene=0; X image->colormap=(ColorPacket *) NULL; X image->pixels=(RunlengthPacket *) NULL; X image->comments=(char *) NULL; X /* X Open image file. X */ X (void) strcpy(image->filename,filename); X if (*image->filename == '-') X image->file=stdin; X else X if (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0) X image->file=fopen(image->filename,"r"); X else X { X char X command[256]; X X /* X Image file is compressed-- uncompress it. X */ X (void) sprintf(command,"uncompress -c %s",image->filename); X image->file=(FILE *) popen(command,"r"); X } X if (image->file == (FILE *) NULL) X { X Warning("unable to open file",image->filename); X (void) DestroyImage(image); X return((Image *) NULL); X } X /* X Decode image header; header terminates one character beyond a ':'. X */ X do { c=fgetc(image->file); } while (isspace(c)); X while ((c > 0) && (c != ':')) X { X register char X *p; X X if (c == '{') X { X register char X *q; X X /* X Comment. X */ X if (image->comments == (char *) NULL) X { X /* X Allocate initial memory for a comment. X */ X image->comments=(char *) malloc(256); X if (image->comments == (char *) NULL) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X *image->comments=(char) NULL; X } X p=image->comments+strlen(image->comments); X q=p+(255-(strlen(image->comments) % 256)); X c=fgetc(image->file); X while ((c > 0) && (c != '}')) X { X if (p == q) X { X /* X Allocate more memory for the comment. X */ X image->comments=(char *) realloc((char *) image->comments, X (unsigned int) (strlen(image->comments)+256)); X if (image->comments == (char *) NULL) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X q=p+255; X } X *p++=c; X c=fgetc(image->file); X } X *p=(char) NULL; X c=fgetc(image->file); X } X else X if (isalnum(c)) X { X /* X Determine a keyword and its value. X */ X p=keyword; X do X { X if ((p-keyword) < (MaxKeywordLength-1)) X *p++=c; X c=fgetc(image->file); X } while (isalnum(c)); X *p=(char) NULL; X while (isspace(c) || (c == '=')) X c=fgetc(image->file); X p=value; X while (isalnum(c)) X { X if ((p-value) < (MaxKeywordLength-1)) X *p++=c; X c=fgetc(image->file); X } X *p=(char) NULL; X /* X Assign a value to the specified keyword. X */ X if (strcmp(keyword,"class") == 0) X if (strcmp(value,"PseudoClass") == 0) X image->class=PseudoClass; X else X if (strcmp(value,"DirectClass") == 0) X image->class=DirectClass; X else X image->class=UnknownClass; X if (strcmp(keyword,"compression") == 0) X if (strcmp(value,"QEncoded") == 0) X image->compression=QEncodedCompression; X else X if (strcmp(value,"RunlengthEncoded") == 0) X image->compression=RunlengthEncodedCompression; X else X image->compression=UnknownCompression; X if (strcmp(keyword,"colors") == 0) X image->colors=(unsigned int) atoi(value); X if (strcmp(keyword,"columns") == 0) X image->columns=(unsigned int) atoi(value); X if (strcmp(keyword,"id") == 0) X if ((strcmp(value,"ImageMagick") == 0) || X (strcmp(value,"XImager") == 0)) X image->id=ImageMagickId; X else X image->id=UnknownId; X if (strcmp(keyword,"packets") == 0) X image->packets=(unsigned int) atoi(value); X if (strcmp(keyword,"rows") == 0) X image->rows=(unsigned int) atoi(value); X if (strcmp(keyword,"scene") == 0) X image->scene=(unsigned int) atoi(value); X } X else X c=fgetc(image->file); X while (isspace(c)) X c=fgetc(image->file); X } X (void) fgetc(image->file); X /* X Verify that required image information is valid. X */ X if ((image->id == UnknownId) || X (image->class == UnknownClass) || X (image->compression == UnknownCompression) || X ((image->columns*image->rows) == 0)) X { X Warning("incorrect image header in file",image->filename); X DestroyImage(image); X return((Image *) NULL); X } X if ((image->columns*image->rows) > MaxImageSize) X { X Warning("unable to read image","image size too large"); X DestroyImage(image); X return((Image *) NULL); X } X /* X Read image from disk and convert to runlength-encoded packets. X */ X switch (image->class) X { X case DirectClass: X { X /* X Transfer pixels to DirectClass image pixel buffer. X */ X switch (image->compression) X { X case NoCompression: X { X /* X Allocate image buffers and read image from disk. X */ X image->packets=image->columns*image->rows; X packet_size=3; X pixels=(unsigned char *) X malloc((unsigned int) image->packets*packet_size); X image->pixels=(RunlengthPacket *) X malloc(image->packets*sizeof(RunlengthPacket)); X if ((pixels == (unsigned char *) NULL) || X (image->pixels == (RunlengthPacket *) NULL)) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X status=ReadData((char *) pixels,(int) packet_size,(int) X image->packets,image->file); X if (status == False) X { X Warning("insufficient image data in file",image->filename); X DestroyImage(image); X return((Image *) NULL); X } X /* X Convert to runlength-encoded DirectClass packets. X */ X image->packets=image->columns*image->rows; X p=pixels; X q=image->pixels; X for (i=0; i < image->packets; i++) X { X q->red=(*p++); X q->green=(*p++); X q->blue=(*p++); X q->index=0; X q->length=0; X q++; X } X break; X } X case QEncodedCompression: X { X extern unsigned int X QDecodeImage(); X X unsigned char X *compressed_pixels; X X /* X Allocate image buffers and read image from disk. X */ X packet_size=1; X if (image->packets == 0) X image->packets=image->columns*image->rows*3; X pixels=(unsigned char *) X malloc((unsigned int) image->packets*packet_size); X image->pixels=(RunlengthPacket *) X malloc(image->columns*image->rows*sizeof(RunlengthPacket)); X if ((pixels == (unsigned char *) NULL) || X (image->pixels == (RunlengthPacket *) NULL)) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X status=ReadData((char *) pixels,(int) packet_size, X (int) image->packets,image->file); X /* X Uncompress image. X */ X image->packets=image->columns*image->rows; X packet_size=3; X compressed_pixels=pixels; X pixels=(unsigned char *) X malloc((unsigned int) image->packets*packet_size); X if (pixels == (unsigned char *) NULL) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X packets=QDecodeImage(compressed_pixels,pixels, X image->columns*(int) packet_size,image->rows); X if (packets != (image->packets*packet_size)) X { X Warning("insufficient image data in file",image->filename); X DestroyImage(image); X return((Image *) NULL); X } X (void) free((char *) compressed_pixels); X /* X Convert to runlength-encoded DirectClass packets. X */ X p=pixels; X image->packets=0; X q=image->pixels; X q->length=MaxRunlength; X for (i=0; i < (image->columns*image->rows); i++) X { X red=(*p++); X green=(*p++); X blue=(*p++); X if ((red == q->red) && (green == q->green) && (blue == q->blue) && X (q->length < MaxRunlength)) X q->length++; X else X { X if (image->packets > 0) X q++; X image->packets++; X q->red=red; X q->green=green; X q->blue=blue; X q->index=0; X q->length=0; X } X } X image->pixels=(RunlengthPacket *) realloc((char *) image->pixels, X image->packets*sizeof(RunlengthPacket)); X break; X } X case RunlengthEncodedCompression: X { X /* X Allocate image buffers and read image from disk. X */ X packet_size=4; X if (image->packets == 0) X { X /* X Number of packets is unspecified. X */ X pixels=(unsigned char *) X malloc((unsigned int) (image->columns*image->rows*packet_size)); X image->pixels=(RunlengthPacket *) X malloc(image->columns*image->rows*sizeof(RunlengthPacket)); X if ((pixels == (unsigned char *) NULL) || X (image->pixels == (RunlengthPacket *) NULL)) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X count=0; X image->packets=0; X p=pixels; X do X { X (void) ReadData((char *) p,(int) packet_size,1,image->file); X image->packets++; X p+=(packet_size-1); X count+=(*p+1); X p++; X } X while (count < (image->columns*image->rows)); X p=pixels; X } X else X { X pixels=(unsigned char *) X malloc((unsigned int) image->packets*packet_size); X image->pixels=(RunlengthPacket *) X malloc(image->packets*sizeof(RunlengthPacket)); X if ((pixels == (unsigned char *) NULL) || X (image->pixels == (RunlengthPacket *) NULL)) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X (void) ReadData((char *) pixels,(int) packet_size, X (int) image->packets,image->file); X } X count=0; X p=pixels; X q=image->pixels; X for (i=0; i < image->packets; i++) X { X q->red=(*p++); X q->green=(*p++); X q->blue=(*p++); X q->index=0; X q->length=(*p++); X count+=(q->length+1); X q++; X } X /* X Guarentee the correct number of runlength packets. X */ X if (count > (image->columns*image->rows)) X { X Warning("insufficient image data in file",image->filename); X DestroyImage(image); X return((Image *) NULL); X } X else X if (count < (image->columns*image->rows)) X { X Warning("too much image data in file",image->filename); X DestroyImage(image); X return((Image *) NULL); X } X break; X } X } X break; X } X case PseudoClass: X { X register unsigned short X index; X X if (image->colors == 0) X { X /* X Create grayscale map. X */ X image->colors=256; X image->colormap=(ColorPacket *) X malloc(image->colors*sizeof(ColorPacket)); X if (image->colormap == (ColorPacket *) NULL) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X for (i=0; i < image->colors; i++) X { X image->colormap[i].red=(unsigned char) i; X image->colormap[i].green=(unsigned char) i; X image->colormap[i].blue=(unsigned char) i; X } X } X else X { X unsigned char X *colormap; X X /* X Read colormap from disk. X */ X packet_size=3; X colormap=(unsigned char *) X malloc((unsigned int) image->colors*packet_size); X image->colormap=(ColorPacket *) X malloc(image->colors*sizeof(ColorPacket)); X if ((colormap == (unsigned char *) NULL) || X (image->colormap == (ColorPacket *) NULL)) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X (void) ReadData((char *) colormap,(int) packet_size, X (int) image->colors,image->file); X p=colormap; X for (i=0; i < image->colors; i++) X { X image->colormap[i].red=(*p++); X image->colormap[i].green=(*p++); X image->colormap[i].blue=(*p++); X } X (void) free((char *) colormap); X } X /* X Transfer pixels to PseudoClass image pixel buffer. X */ X switch (image->compression) X { X case NoCompression: X { X /* X Allocate image buffers and read image from disk. X */ X image->packets=image->columns*image->rows; X packet_size=1; X if (image->colors > 256) X packet_size++; X pixels=(unsigned char *) X malloc((unsigned int) image->packets*packet_size); X image->pixels=(RunlengthPacket *) X malloc(image->packets*sizeof(RunlengthPacket)); X if ((pixels == (unsigned char *) NULL) || X (image->pixels == (RunlengthPacket *) NULL)) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X status=ReadData((char *) pixels,(int) packet_size, X (int) (image->columns*image->rows),image->file); X if (status == False) X { X Warning("insufficient image data in file",image->filename); X DestroyImage(image); X return((Image *) NULL); X } X /* X Convert to runlength-encoded PseudoClass packets. X */ X image->packets=image->columns*image->rows; X p=pixels; X q=image->pixels; X if (image->colors <= 256) X for (i=0; i < image->packets; i++) X { X index=(*p++); X q->red=image->colormap[index].red; X q->green=image->colormap[index].green; X q->blue=image->colormap[index].blue; X q->index=index; X q->length=0; X q++; X } X else X for (i=0; i < image->packets; i++) X { X index=(*p++) << 8; X index|=(*p++); X q->red=image->colormap[index].red; X q->green=image->colormap[index].green; X q->blue=image->colormap[index].blue; X q->index=index; X q->length=0; X q++; X } X break; X } X case QEncodedCompression: X { X extern unsigned int X QDecodeImage(); X X unsigned char X *compressed_pixels; X X /* X Allocate image buffers and read image from disk. X */ X packet_size=1; X if (image->packets == 0) X image->packets=(image->columns*image->rows)* X (image->colors > 256 ? 2 : 1); X pixels=(unsigned char *) X malloc((unsigned int) image->packets*packet_size); X image->pixels=(RunlengthPacket *) X malloc(image->columns*image->rows*sizeof(RunlengthPacket)); X if ((pixels == (unsigned char *) NULL) || X (image->pixels == (RunlengthPacket *) NULL)) X { X Warning("unable to allocate memory",(char *) NULL); X DestroyImage(image); X return((Image *) NULL); X } X status=ReadData((char *) pixels,(int) packet_size, X (int) image->packets,image->file); X /* X Uncompress image. X */ X image->packets=image->columns*image->rows; X packet_size=1; X if (image->colors > 256) X packet_size++; X compressed_pixels=pixels; X pixels=(unsigned char *) X malloc((unsigned int) image->packets*packet_size); X if (pixels == (unsigned char *) NULL) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X packets=QDecodeImage(compressed_pixels,pixels,image->columns* X (int) packet_size,image->rows); X if (packets != (image->packets*packet_size)) X { X Warning("insufficient image data in file",image->filename); X DestroyImage(image); X return((Image *) NULL); X } X (void) free((char *) compressed_pixels); X /* X Convert to runlength-encoded PseudoClass packets. X */ X p=pixels; X image->packets=0; X q=image->pixels; X q->length=MaxRunlength; X if (image->colors <= 256) X for (i=0; i < (image->columns*image->rows); i++) X { X index=(*p++); X red=image->colormap[index].red; X green=image->colormap[index].green; X blue=image->colormap[index].blue; X if ((red == q->red) && (green == q->green) && (blue == q->blue) && X (q->length < MaxRunlength)) X q->length++; X else X { X if (image->packets > 0) X q++; X image->packets++; X q->red=red; X q->green=green; X q->blue=blue; X q->index=index; X q->length=0; X } X } X else X for (i=0; i < (image->columns*image->rows); i++) X { X index=(*p++) << 8; X index|=(*p++); X red=image->colormap[index].red; X green=image->colormap[index].green; X blue=image->colormap[index].blue; X if ((red == q->red) && (green == q->green) && (blue == q->blue) && X (q->length < MaxRunlength)) X q->length++; X else X { X if (image->packets > 0) X q++; X image->packets++; X q->red=red; X q->green=green; X q->blue=blue; X q->index=index; X q->length=0; X } X } X image->pixels=(RunlengthPacket *) realloc((char *) image->pixels, X image->packets*sizeof(RunlengthPacket)); X break; X } X case RunlengthEncodedCompression: X { X packet_size=2; X if (image->colors > 256) X packet_size++; X if (image->packets == 0) X { X /* X Number of packets is unspecified. X */ X pixels=(unsigned char *) X malloc((unsigned int) (image->columns*image->rows*packet_size)); X image->pixels=(RunlengthPacket *) X malloc((unsigned int) packets*sizeof(RunlengthPacket)); X if ((pixels == (unsigned char *) NULL) || X (image->pixels == (RunlengthPacket *) NULL)) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X count=0; X image->packets=0; X p=pixels; X do X { X (void) ReadData((char *) p,(int) packet_size,1,image->file); X image->packets++; X p+=(packet_size-1); X count+=(*p+1); X p++; X } X while (count < (image->columns*image->rows)); X } X else X { X pixels=(unsigned char *) X malloc((unsigned int) image->packets*packet_size); X image->pixels=(RunlengthPacket *) X malloc(image->packets*sizeof(RunlengthPacket)); X if ((pixels == (unsigned char *) NULL) || X (image->pixels == (RunlengthPacket *) NULL)) X { X Warning("unable to read image","memory allocation failed"); X DestroyImage(image); X return((Image *) NULL); X } X (void) ReadData((char *) pixels,(int) packet_size, X (int) image->packets,image->file); X } X count=0; X p=pixels; X q=image->pixels; X if (image->colors <= 256) X for (i=0; i < image->packets; i++) X { X index=(*p++); X q->red=image->colormap[index].red; X q->green=image->colormap[index].green; X q->blue=image->colormap[index].blue; X q->index=index; X q->length=(*p++); X count+=(q->length+1); X q++; X } X else X for (i=0; i < image->packets; i++) X { X index=(*p++) << 8; X index|=(*p++); X q->red=image->colormap[index].red; X q->green=image->colormap[index].green; X q->blue=image->colormap[index].blue; X q->index=index; X q->length=(*p++); SHAR_EOF true || echo 'restore of ImageMagick/image.c failed' fi echo 'End of ImageMagick part 4' echo 'File ImageMagick/image.c is continued in part 5' echo 5 > _shar_seq_.tmp exit 0 -- Dan Heller O'Reilly && Associates Z-Code Software Comp-sources-x: Senior Writer President comp-sources-x@uunet.uu.net argv@ora.com argv@zipcode.com