home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
x
/
volume13
/
imagemagic
/
part04
< prev
next >
Wrap
Internet Message Format
|
1991-05-22
|
75KB
Path: uunet!cs.utexas.edu!sun-barr!newstop!exodus!dupont.com!cristy
From: cristy@dupont.com
Newsgroups: comp.sources.x
Subject: v13i020: ImageMagick - Graphics display programs, Part04/21
Message-ID: <13790@exodus.Eng.Sun.COM>
Date: 22 May 91 08:57:29 GMT
References: <csx-13i017:imagemagic@uunet.UU.NET>
Sender: news@exodus.Eng.Sun.COM
Lines: 2555
Approved: argv@sun.com
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