/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d Y U V I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method ReadYUVImage reads an image with digital YUV (CCIR 601 4:1:1) bytes % and returns it. It allocates the memory necessary for the new Image % structure and returns a pointer to the new image. % % The format of the ReadYUVImage method is: % % Image *ReadYUVImage(const ImageInfo *image_info) % % A description of each parameter follows: % % o image: Method ReadYUVImage returns a pointer to the image after % reading. A null image is returned if there is a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ Export Image *ReadYUVImage(const ImageInfo *image_info) { Image *chroma_image, *image, *zoom_image; int count, y; register int i, x; register PixelPacket *q, *r; register unsigned char *p; unsigned char *scanline; unsigned int status; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); if ((image->columns == 0) || (image->rows == 0)) ReaderExit(OptionWarning,"Must specify image size",image); image->depth=8; if (image_info->interlace != PartitionInterlace) { /* Open image file. */ status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); for (i=0; i < image->offset; i++) (void) ReadByte(image); } /* Allocate memory for a scanline. */ scanline=(unsigned char *) AllocateMemory(image->columns*sizeof(unsigned char)); if (scanline == (unsigned char *) NULL) ReaderExit(ResourceLimitWarning,"Memory allocation failed",image); do { /* Convert raster image to pixel packets. */ if (image_info->interlace == PartitionInterlace) { AppendImageFormat("Y",image->filename); status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); } for (y=0; y < (int) image->rows; y++) { if ((y > 0) || (image->previous == (Image *) NULL)) (void) ReadBlob(image,image->columns,scanline); p=scanline; q=SetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->red=UpScale(*p++); q->green=0; q->blue=0; q++; } if (!SyncPixelCache(image)) break; if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,y,image->rows); } if (image_info->interlace == PartitionInterlace) { CloseBlob(image); AppendImageFormat("U",image->filename); status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); } chroma_image=CloneImage(image,image->columns/2,image->rows/2,True); if (chroma_image == (Image *) NULL) ReaderExit(ResourceLimitWarning,"Memory allocation failed",image); for (y=0; y < (int) chroma_image->rows; y++) { (void) ReadBlob(image,chroma_image->columns,scanline); p=scanline; q=SetPixelCache(chroma_image,0,y,chroma_image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) chroma_image->columns; x++) { q->red=0; q->green=UpScale(*p++); q->blue=0; q++; } if (!SyncPixelCache(chroma_image)) break; } if (image_info->interlace == PartitionInterlace) { CloseBlob(image); AppendImageFormat("V",image->filename); status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); } for (y=0; y < (int) chroma_image->rows; y++) { (void) ReadBlob(image,chroma_image->columns,scanline); p=scanline; q=GetPixelCache(chroma_image,0,y,chroma_image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) chroma_image->columns; x++) { q->blue=UpScale(*p++); q++; } if (!SyncPixelCache(chroma_image)) break; } /* Scale image. */ chroma_image->orphan=True; zoom_image=SampleImage(chroma_image,image->columns,image->rows); DestroyImage(chroma_image); if (zoom_image == (Image *) NULL) ReaderExit(ResourceLimitWarning,"Memory allocation failed",image); for (y=0; y < (int) image->rows; y++) { q=GetPixelCache(image,0,y,image->columns,1); r=GetPixelCache(zoom_image,0,y,zoom_image->columns,1); if ((q == (PixelPacket *) NULL) || (r == (PixelPacket *) NULL)) break; for (x=0; x < (int) image->columns; x++) { q->green=r->green; q->blue=r->blue; r++; q++; } if (!SyncPixelCache(image)) break; } DestroyImage(zoom_image); TransformRGBImage(image,YCbCrColorspace); if (image_info->interlace == PartitionInterlace) (void) strcpy(image->filename,image_info->filename); /* Proceed to next image. */ if (image_info->subrange != 0) if (image->scene >= (image_info->subimage+image_info->subrange-1)) break; count=ReadBlob(image,image->columns,(char *) scanline); if (count > 0) { /* Allocate next image structure. */ AllocateNextImage(image_info,image); if (image->next == (Image *) NULL) { DestroyImages(image); return((Image *) NULL); } image=image->next; ProgressMonitor(LoadImagesText,TellBlob(image),image->filesize); } } while (count > 0); FreeMemory(scanline); while (image->previous != (Image *) NULL) image=image->previous; CloseBlob(image); return(image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % C o n t r a s t I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method ContrastImage enhances the intensity differences between the % lighter and darker elements of the image. % % The format of the ContrastImage method is: % % void ContrastImage(Image *image,const unsigned int sharpen) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % o sharpen: If True, the intensity is increased otherwise it is % decreased. % % */ Export void ContrastImage(Image *image,const unsigned int sharpen) { #define DullContrastImageText " Dulling image contrast... " #define SharpenContrastImageText " Sharpening image contrast... " int sign, y; register int i, x; register PixelPacket *q; assert(image != (Image *) NULL); sign=sharpen ? 1 : -1; switch (image->class) { case DirectClass: default: { /* Contrast enhance DirectClass image. */ for (y=0; y < (int) image->rows; y++) { q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { Contrast(sign,&q->red,&q->green,&q->blue); q++; } if (!SyncPixelCache(image)) break; if (QuantumTick(y,image->rows)) { if (sharpen) ProgressMonitor(SharpenContrastImageText,y,image->rows); else ProgressMonitor(DullContrastImageText,y,image->rows); } } break; } case PseudoClass: { Quantum blue, green, red; /* Contrast enhance PseudoClass image. */ for (i=0; i < (int) image->colors; i++) { red=image->colormap[i].red; green=image->colormap[i].green; blue=image->colormap[i].blue; Contrast(sign,&red,&green,&blue); image->colormap[i].red=red; image->colormap[i].green=green; image->colormap[i].blue=blue; } SyncImage(image); break; } } }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e Y U V I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method WriteYUVImage writes an image to a file in the digital YUV % (CCIR 601 4:1:1) format. % % The format of the WriteYUVImage method is: % % unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o status: Method WriteYUVImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ Export unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image) { Image *chroma_image, *yuv_image; int y; register int x; register PixelPacket *p; unsigned int height, scene, status, width; if (image_info->interlace != PartitionInterlace) { /* Open output image file. */ status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); } if (image_info->interlace == PartitionInterlace) { AppendImageFormat("Y",image->filename); status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); } scene=0; do { /* Sample image to an even width and height. */ TransformRGBImage(image,RGBColorspace); width=image->columns+(image->columns & 0x01); height=image->rows+(image->rows & 0x01); image->orphan=True; yuv_image=SampleImage(image,width,height); if (yuv_image == (Image *) NULL) WriterExit(ResourceLimitWarning,"Unable to zoom image",image); RGBTransformImage(yuv_image,YCbCrColorspace); /* Initialize Y channel. */ for (y=0; y < (int) yuv_image->rows; y++) { p=GetPixelCache(yuv_image,0,y,yuv_image->columns,1); if (p == (PixelPacket *) NULL) break; for (x=0; x < (int) yuv_image->columns; x++) { (void) WriteByte(image,DownScale(p->red)); p++; } if (image->previous == (Image *) NULL) if (QuantumTick(y,image->rows)) ProgressMonitor(SaveImageText,y,image->rows); } DestroyImage(yuv_image); /* Downsample image. */ image->orphan=True; chroma_image=SampleImage(image,width/2,height/2); if (chroma_image == (Image *) NULL) WriterExit(ResourceLimitWarning,"Unable to zoom image",image); RGBTransformImage(chroma_image,YCbCrColorspace); /* Initialize U channel. */ if (image_info->interlace == PartitionInterlace) { CloseBlob(image); AppendImageFormat("U",image->filename); status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); } for (y=0; y < (int) chroma_image->rows; y++) { p=GetPixelCache(chroma_image,0,y,chroma_image->columns,1); if (p == (PixelPacket *) NULL) break; for (x=0; x < (int) chroma_image->columns; x++) { (void) WriteByte(image,DownScale(p->green)); p++; } } /* Initialize V channel. */ if (image_info->interlace == PartitionInterlace) { CloseBlob(image); AppendImageFormat("V",image->filename); status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); } for (y=0; y < (int) chroma_image->rows; y++) { p=GetPixelCache(chroma_image,0,y,chroma_image->columns,1); if (p == (PixelPacket *) NULL) break; for (x=0; x < (int) chroma_image->columns; x++) { (void) WriteByte(image,DownScale(p->blue)); p++; } } DestroyImage(chroma_image); if (image_info->interlace == PartitionInterlace) (void) strcpy(image->filename,image_info->filename); if (image->next == (Image *) NULL) break; image=GetNextImage(image); ProgressMonitor(SaveImagesText,scene++,GetNumberScenes(image)); } while (image_info->adjoin); if (image_info->adjoin) while (image->previous != (Image *) NULL) image=image->previous; CloseBlob(image); return(True); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % N e g a t e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method NegateImage negates the colors in the reference image. The % Grayscale option means that only grayscale values within the image are % negated. % % The format of the NegateImage method is: % % void NegateImage(Image *image,const unsigned int grayscale) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ Export void NegateImage(Image *image,const unsigned int grayscale) { #define NegateImageText " Negating the image colors... " int y; register int i, x; register PixelPacket *q; assert(image != (Image *) NULL); switch (image->class) { case DirectClass: default: { /* Negate DirectClass packets. */ for (y=0; y < (int) image->rows; y++) { q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { if (grayscale) if ((q->red != q->green) || (q->green != q->blue)) { q++; continue; } q->red=(~q->red); q->green=(~q->green); q->blue=(~q->blue); q->opacity=(~q->opacity); q++; } if (!SyncPixelCache(image)) break; if (QuantumTick(y,image->rows)) ProgressMonitor(NegateImageText,y,image->rows); } break; } case PseudoClass: { /* Negate PseudoClass packets. */ for (i=0; i < (int) image->colors; i++) { if (grayscale) if ((image->colormap[i].red != image->colormap[i].green) || (image->colormap[i].green != image->colormap[i].blue)) continue; image->colormap[i].red=(Quantum) (~image->colormap[i].red); image->colormap[i].green=(Quantum) (~image->colormap[i].green); image->colormap[i].blue=(Quantum) (~image->colormap[i].blue); } SyncImage(image); break; } } }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % N o r m a l i z e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method NormalizeImage normalizes the pixel values to span the full % range of color values. This is a contrast enhancement technique. % % The format of the NormalizeImage method is: % % void NormalizeImage(Image *image) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ Export void NormalizeImage(Image *image) { #define NormalizeImageText " Normalizing image... " int *histogram, threshold_intensity, y; Quantum gray_value, *normalize_map; register int i, intensity, x; register PixelPacket *p, *q; unsigned int high, low; /* Allocate histogram and normalize map. */ assert(image != (Image *) NULL); histogram=(int *) AllocateMemory((MaxRGB+1)*sizeof(int)); normalize_map=(Quantum *) AllocateMemory((MaxRGB+1)*sizeof(Quantum)); if ((histogram == (int *) NULL) || (normalize_map == (Quantum *) NULL)) { MagickWarning(ResourceLimitWarning,"Unable to normalize image", "Memory allocation failed"); return; } /* Form histogram. */ for (i=0; i <= MaxRGB; i++) histogram[i]=0; for (y=0; y < (int) image->rows; y++) { p=GetPixelCache(image,0,y,image->columns,1); if (p == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { gray_value=Intensity(*p); histogram[gray_value]++; p++; } } /* Find the histogram boundaries by locating the 1 percent levels. */ threshold_intensity=(image->columns*image->rows)/100; intensity=0; for (low=0; low < MaxRGB; low++) { intensity+=histogram[low]; if (intensity > threshold_intensity) break; } intensity=0; for (high=MaxRGB; high != 0; high--) { intensity+=histogram[high]; if (intensity > threshold_intensity) break; } if (low == high) { /* Unreasonable contrast; use zero threshold to determine boundaries. */ threshold_intensity=0; intensity=0; for (low=0; low < MaxRGB; low++) { intensity+=histogram[low]; if (intensity > threshold_intensity) break; } intensity=0; for (high=MaxRGB; high != 0; high--) { intensity+=histogram[high]; if (intensity > threshold_intensity) break; } if (low == high) return; /* zero span bound */ } /* Stretch the histogram to create the normalized image mapping. */ for (i=0; i <= MaxRGB; i++) if (i < (int) low) normalize_map[i]=0; else if (i > (int) high) normalize_map[i]=MaxRGB; else normalize_map[i]=(MaxRGB-1)*(i-low)/(high-low); /* Normalize the image. */ switch (image->class) { case DirectClass: default: { /* Normalize DirectClass image. */ for (y=0; y < (int) image->rows; y++) { q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->red=normalize_map[q->red]; q->green=normalize_map[q->green]; q->blue=normalize_map[q->blue]; q++; } if (!SyncPixelCache(image)) break; if (QuantumTick(y,image->rows)) ProgressMonitor(NormalizeImageText,y,image->rows); } break; } case PseudoClass: { /* Normalize PseudoClass image. */ for (i=0; i < (int) image->colors; i++) { image->colormap[i].red=normalize_map[image->colormap[i].red]; image->colormap[i].green=normalize_map[image->colormap[i].green]; image->colormap[i].blue=normalize_map[image->colormap[i].blue]; } SyncImage(image); break; } } FreeMemory(normalize_map); FreeMemory(histogram); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % M o d u l a t e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method ModulateImage modulates the hue, saturation, and brightness of an % image. % % The format of the ModulateImage method is: % % void ModulateImage(Image *image,const char *modulate) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % o modulate: A character string indicating the percent change in brightness, % saturation, and hue in floating point notation separated by commas % (e.g. 10.1,0.0,3.1). % % */ Export void ModulateImage(Image *image,const char *modulate) { #define ModulateImageText " Modulating image... " double percent_brightness, percent_hue, percent_saturation; int y; register int i, x; register PixelPacket *q; /* Initialize gamma table. */ assert(image != (Image *) NULL); if (modulate == (char *) NULL) return; percent_hue=0.0; percent_brightness=0.0; percent_saturation=0.0; (void) sscanf(modulate,"%lf,%lf,%lf",&percent_brightness,&percent_saturation, &percent_hue); (void) sscanf(modulate,"%lf/%lf/%lf",&percent_brightness,&percent_saturation, &percent_hue); switch (image->class) { case DirectClass: default: { /* Modulate the color for a DirectClass image. */ for (y=0; y < (int) image->rows; y++) { q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { Modulate(percent_hue,percent_saturation,percent_brightness, &q->red,&q->green,&q->blue); q++; } if (!SyncPixelCache(image)) break; if (QuantumTick(y,image->rows)) ProgressMonitor(ModulateImageText,y,image->rows); } break; } case PseudoClass: { Quantum blue, green, red; /* Modulate the color for a PseudoClass image. */ for (i=0; i < (int) image->colors; i++) { red=image->colormap[i].red; green=image->colormap[i].green; blue=image->colormap[i].blue; Modulate(percent_hue,percent_saturation,percent_brightness, &red,&green,&blue); image->colormap[i].red=red; image->colormap[i].green=green; image->colormap[i].blue=blue; } SyncImage(image); break; } } }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % G a m m a I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method GammaImage converts the reference image to gamma corrected colors. % % The format of the GammaImage method is: % % void GammaImage(Image *image,const char *gamma) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % o gamma: A character string indicating the level of gamma correction. % % */ Export void GammaImage(Image *image,const char *gamma) { #define GammaImageText " Gamma correcting the image... " double blue_gamma, green_gamma, opacity_gamma, red_gamma; int count, y; register int i, x; register PixelPacket *q; PixelPacket *gamma_map; assert(image != (Image *) NULL); if (gamma == (char *) NULL) return; red_gamma=1.0; green_gamma=1.0; blue_gamma=1.0; opacity_gamma=1.0; count=sscanf(gamma,"%lf,%lf,%lf,%lf",&red_gamma,&green_gamma,&blue_gamma, &opacity_gamma); count=sscanf(gamma,"%lf/%lf/%lf/%lf",&red_gamma,&green_gamma,&blue_gamma, &opacity_gamma); if (count == 1) { if (red_gamma == 1.0) return; green_gamma=red_gamma; blue_gamma=red_gamma; } /* Allocate and initialize gamma maps. */ gamma_map=(PixelPacket *) AllocateMemory((MaxRGB+1)*sizeof(PixelPacket)); if (gamma_map == (PixelPacket *) NULL) { MagickWarning(ResourceLimitWarning,"Unable to gamma correct image", "Memory allocation failed"); return; } for (i=0; i <= MaxRGB; i++) { gamma_map[i].red=0; gamma_map[i].green=0; gamma_map[i].blue=0; gamma_map[i].opacity=0; } /* Initialize gamma table. */ for (i=0; i <= MaxRGB; i++) { if (red_gamma != 0.0) gamma_map[i].red=(Quantum) ((pow((double) i/MaxRGB,1.0/red_gamma)*MaxRGB)+0.5); if (green_gamma != 0.0) gamma_map[i].green=(Quantum) ((pow((double) i/MaxRGB,1.0/green_gamma)*MaxRGB)+0.5); if (blue_gamma != 0.0) gamma_map[i].blue=(Quantum) ((pow((double) i/MaxRGB,1.0/blue_gamma)*MaxRGB)+0.5); if (opacity_gamma != 0.0) gamma_map[i].opacity=(Quantum) ((pow((double) i/MaxRGB,1.0/opacity_gamma)*MaxRGB)+0.5); } switch (image->class) { case DirectClass: default: { /* Gamma-correct DirectClass image. */ for (y=0; y < (int) image->rows; y++) { q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->red=gamma_map[q->red].red; q->green=gamma_map[q->green].green; q->blue=gamma_map[q->blue].blue; q->opacity=gamma_map[q->opacity].opacity; q++; } if (!SyncPixelCache(image)) break; if (QuantumTick(y,image->rows)) ProgressMonitor(GammaImageText,y,image->rows); } break; } case PseudoClass: { /* Gamma-correct PseudoClass image. */ for (i=0; i < (int) image->colors; i++) { image->colormap[i].red=gamma_map[image->colormap[i].red].red; image->colormap[i].green=gamma_map[image->colormap[i].green].green; image->colormap[i].blue=gamma_map[image->colormap[i].blue].blue; } SyncImage(image); break; } } if (image->gamma != 0.0) image->gamma*=(red_gamma+green_gamma+blue_gamma)/3.0; FreeMemory(gamma_map); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % E q u a l i z e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method EqualizeImage performs histogram equalization on the reference % image. % % The format of the EqualizeImage method is: % % void EqualizeImage(Image *image) % % A description of each parameter follows: % % o image: The address of a structure of type Image; returned from % ReadImage. % % */ Export void EqualizeImage(Image *image) { #define EqualizeImageText " Equalizing image... " int j, y; Quantum *equalize_map; register int i, x; register PixelPacket *p, *q; unsigned int high, *histogram, low, *map; /* Allocate and initialize histogram arrays. */ assert(image != (Image *) NULL); histogram=(unsigned int *) AllocateMemory((MaxRGB+1)*sizeof(unsigned int)); map=(unsigned int *) AllocateMemory((MaxRGB+1)*sizeof(unsigned int)); equalize_map=(Quantum *) AllocateMemory((MaxRGB+1)*sizeof(Quantum)); if ((histogram == (unsigned int *) NULL) || (map == (unsigned int *) NULL) || (equalize_map == (Quantum *) NULL)) { MagickWarning(ResourceLimitWarning,"Unable to equalize image", "Memory allocation failed"); return; } /* Form histogram. */ for (i=0; i <= MaxRGB; i++) histogram[i]=0; for (y=0; y < (int) image->rows; y++) { p=GetPixelCache(image,0,y,image->columns,1); if (p == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { histogram[Intensity(*p)]++; p++; } } /* Integrate the histogram to get the equalization map. */ j=0; for (i=0; i <= MaxRGB; i++) { j+=histogram[i]; map[i]=j; } FreeMemory(histogram); if (map[MaxRGB] == 0) { FreeMemory(equalize_map); FreeMemory(map); return; } /* Equalize. */ low=map[0]; high=map[MaxRGB]; for (i=0; i <= MaxRGB; i++) equalize_map[i]=(Quantum) ((((double) (map[i]-low))*MaxRGB)/Max(high-low,1)); FreeMemory(map); /* Stretch the histogram. */ switch (image->class) { case DirectClass: default: { /* Equalize DirectClass packets. */ for (y=0; y < (int) image->rows; y++) { q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->red=equalize_map[q->red]; q->green=equalize_map[q->green]; q->blue=equalize_map[q->blue]; q++; } if (!SyncPixelCache(image)) break; if (QuantumTick(y,image->rows)) ProgressMonitor(EqualizeImageText,y,image->rows); } break; } case PseudoClass: { /* Equalize PseudoClass packets. */ for (i=0; i < (int) image->colors; i++) { image->colormap[i].red=equalize_map[image->colormap[i].red]; image->colormap[i].green=equalize_map[image->colormap[i].green]; image->colormap[i].blue=equalize_map[image->colormap[i].blue]; } SyncImage(image); break; } } FreeMemory(equalize_map); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e H T M L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method WriteHTMLImage writes an image in the HTML encoded image format. % % The format of the WriteHTMLImage method is: % % unsigned int WriteHTMLImage(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o status: Method WriteHTMLImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ Export unsigned int WriteHTMLImage(const ImageInfo *image_info,Image *image) { char buffer[MaxTextExtent], filename[MaxTextExtent], mapname[MaxTextExtent], url[MaxTextExtent]; Image *next; ImageInfo *local_info; int x, y; register char *p; register PixelPacket *q; unsigned int height, status, width; /* Open image. */ status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); CloseBlob(image); TransformRGBImage(image,RGBColorspace); *url='\0'; if ((Latin1Compare(image_info->magick,"FTP") == 0) || (Latin1Compare(image_info->magick,"HTTP") == 0)) { /* Extract URL base from filename. */ p=strrchr(image->filename,'/'); if (p) { p++; (void) strcpy(url,image_info->magick); (void) strcat(url,":"); url[Extent(url)+p-image->filename]='\0'; (void) strncat(url,image->filename,p-image->filename); (void) strcpy(image->filename,p); } } /* Refer to image map file. */ (void) strcpy(filename,image->filename); AppendImageFormat("map",filename); (void) strcpy(mapname,BaseFilename(filename)); (void) strcpy(image->filename,image_info->filename); (void) strcpy(filename,image->filename); local_info=CloneImageInfo(image_info); if (local_info == (ImageInfo *) NULL) WriterExit(FileOpenWarning,"Unable to allocate memory",image); local_info->adjoin=True; status=True; if (Latin1Compare(image_info->magick,"SHTML") != 0) { /* Open output image file. */ status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); /* Write the HTML image file. */ (void) strcpy(buffer,"<html version=\"2.0\">\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"<head>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) sprintf(buffer,"<title>%.1024s</title>\n", image->label ? image->label : BaseFilename(image->filename)); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"</head>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"<body>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"<center>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) sprintf(buffer,"<h1>%.1024s</h1>\n",image->filename); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"<br><br>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(filename,image->filename); AppendImageFormat("gif",filename); (void) sprintf(buffer, "<img ismap usemap=#%.1024s src=\"%.1024s\" border=0>\n", mapname,filename); (void) WriteBlob(image,strlen(buffer),buffer); /* Determine the size and location of each image tile. */ width=image->columns; height=image->rows; x=0; y=0; if (image->montage != (char *) NULL) (void) ParseGeometry(image->montage,&x,&y,&width,&height); /* Write an image map. */ (void) sprintf(buffer,"<map name=%.1024s>\n",mapname); (void) WriteBlob(image,strlen(buffer),buffer); (void) sprintf(buffer," <area href=""%.1024s""",url); (void) WriteBlob(image,strlen(buffer),buffer); if (image->directory == (char *) NULL) { (void) sprintf(buffer,"%.1024s shape=rect coords=0,0,%u,%u>\n", image->filename,width-1,height-1); (void) WriteBlob(image,strlen(buffer),buffer); } else for (p=image->directory; *p != '\0'; p++) if (*p != '\n') (void) WriteByte(image,*p); else { (void) sprintf(buffer," shape=rect coords=%d,%d,%d,%d>\n", x,y,x+(int) width-1,y+(int) height-1); (void) WriteBlob(image,strlen(buffer),buffer); if (*(p+1) != '\0') { (void) sprintf(buffer," <area href=""%.1024s""",url); (void) WriteBlob(image,strlen(buffer),buffer); } x+=width; if (x >= (int) image->columns) { x=0; y+=height; } } (void) strcpy(buffer,"</map>\n"); (void) WriteBlob(image,strlen(buffer),buffer); if (image->montage != (char *) NULL) { char color[MaxTextExtent] = "#000"; /* Make montage background transparent. */ q=GetPixelCache(image,0,0,1,1); if (q != (PixelPacket *) NULL) FormatString(color,HexColorFormat,q->red,q->green,q->blue); TransparentImage(image,color); } (void) strcpy(filename,image->filename); (void) strcpy(buffer,"</center>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"</body>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"</html>\n"); status=WriteBlob(image,strlen(buffer),buffer); CloseBlob(image); /* Write the image as transparent GIF. */ (void) strcpy(image->filename,filename); AppendImageFormat("gif",image->filename); next=image->next; image->next=(Image *) NULL; status|=WriteGIFImage(local_info,image); image->next=next; /* Determine image map filename. */ (void) strcpy(image->filename,filename); for (p=filename+Extent(filename)-1; p > (filename+1); p--) if (*p == '.') { (void) strncpy(image->filename,filename,p-filename); image->filename[p-filename]='\0'; break; } (void) strcat(image->filename,"_map.shtml"); } /* Open image map. */ status=OpenBlob(local_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); DestroyImageInfo(local_info); /* Determine the size and location of each image tile. */ width=image->columns; height=image->rows; x=0; y=0; if (image->montage != (char *) NULL) (void) ParseGeometry(image->montage,&x,&y,&width,&height); /* Write an image map. */ (void) sprintf(buffer,"<map name=%.1024s>\n",mapname); (void) WriteBlob(image,strlen(buffer),buffer); (void) sprintf(buffer," <area href=""%.1024s""",url); (void) WriteBlob(image,strlen(buffer),buffer); if (image->directory == (char *) NULL) { (void) sprintf(buffer,"%.1024s shape=rect coords=0,0,%u,%u>\n", image->filename,width-1,height-1); (void) WriteBlob(image,strlen(buffer),buffer); } else for (p=image->directory; *p != '\0'; p++) if (*p != '\n') (void) WriteByte(image,*p); else { (void) sprintf(buffer," shape=rect coords=%d,%d,%d,%d>\n",x,y, x+(int) width-1,y+(int) height-1); (void) WriteBlob(image,strlen(buffer),buffer); if (*(p+1) != '\0') { (void) sprintf(buffer," <area href=""%.1024s""",url); (void) WriteBlob(image,strlen(buffer),buffer); } x+=width; if (x >= (int) image->columns) { x=0; y+=height; } } (void) strcpy(buffer,"</map>\n"); (void) WriteBlob(image,strlen(buffer),buffer); CloseBlob(image); (void) strcpy(image->filename,filename); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d S C T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method ReadSCTImage reads a Scitex 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 ReadSCTImage method is: % % Image *ReadSCTImage(const ImageInfo *image_info) % % A description of each parameter follows: % % o image: Method ReadSCTImage returns a pointer to the image after % reading. A null image is returned if there is a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ Export Image *ReadSCTImage(const ImageInfo *image_info) { char buffer[768], magick[2]; Image *image; int y; register int x; register PixelPacket *q; unsigned int status; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); /* Open image file. */ status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); /* Read control block. */ (void) ReadBlob(image,80,(char *) buffer); (void) ReadBlob(image,2,(char *) magick); if ((strncmp((char *) magick,"CT",2) != 0) && (strncmp((char *) magick,"LW",2) != 0) && (strncmp((char *) magick,"BM",2) != 0) && (strncmp((char *) magick,"PG",2) != 0) && (strncmp((char *) magick,"TX",2) != 0)) ReaderExit(CorruptImageWarning,"Not a SCT image file",image); if ((strncmp((char *) magick,"LW",2) == 0) || (strncmp((char *) magick,"BM",2) == 0) || (strncmp((char *) magick,"PG",2) == 0) || (strncmp((char *) magick,"TX",2) == 0)) ReaderExit(CorruptImageWarning,"only Continuous Tone Picture supported", image); (void) ReadBlob(image,174,(char *) buffer); (void) ReadBlob(image,768,(char *) buffer); /* Read paramter block. */ (void) ReadBlob(image,32,(char *) buffer); (void) ReadBlob(image,14,(char *) buffer); image->rows=atoi(buffer); (void) ReadBlob(image,14,(char *) buffer); image->columns=atoi(buffer); (void) ReadBlob(image,196,(char *) buffer); (void) ReadBlob(image,768,(char *) buffer); if (image_info->ping) { CloseBlob(image); return(image); } /* Convert SCT raster image to pixel packets. */ image->colorspace=CMYKColorspace; for (y=0; y < (int) image->rows; y++) { q=SetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->red=MaxRGB-UpScale(ReadByte(image)); q++; } if ((image->columns % 2) != 0) (void) ReadByte(image); /* pad */ q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->green=MaxRGB-UpScale(ReadByte(image)); q++; } if ((image->columns % 2) != 0) (void) ReadByte(image); /* pad */ q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->blue=MaxRGB-UpScale(ReadByte(image)); q++; } if ((image->columns % 2) != 0) (void) ReadByte(image); /* pad */ q=GetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->opacity=MaxRGB-UpScale(ReadByte(image)); q++; } if (!SyncPixelCache(image)) break; if ((image->columns % 2) != 0) (void) ReadByte(image); /* pad */ if (QuantumTick(y,image->rows)) ProgressMonitor(LoadImageText,y,image->rows); } return(image); }