MagickExport void ConvertHSLToRGB(const double hue,const double saturation, const double lightness,Quantum *red,Quantum *green,Quantum *blue) { MagickRealType b, g, r, m1, m2; /* Convert HSL to RGB colorspace. */ assert(red != (Quantum *) NULL); assert(green != (Quantum *) NULL); assert(blue != (Quantum *) NULL); if (saturation == 0) { *red=ClampToQuantum((MagickRealType) QuantumRange*lightness); *green=(*red); *blue=(*red); return; } if (lightness < 0.5) m2=lightness*(saturation+1.0); else m2=(lightness+saturation)-(lightness*saturation); m1=2.0*lightness-m2; r=ConvertHueToRGB(m1,m2,hue+1.0/3.0); g=ConvertHueToRGB(m1,m2,hue); b=ConvertHueToRGB(m1,m2,hue-1.0/3.0); *red=ClampToQuantum((MagickRealType) QuantumRange*r); *green=ClampToQuantum((MagickRealType) QuantumRange*g); *blue=ClampToQuantum((MagickRealType) QuantumRange*b); }
void sanpera_magick_pixel_from_doubles(MagickPixelPacket *pixel, double in[4]) { SetPixelRed(pixel, ClampToQuantum(in[0] * QuantumRange)); SetPixelGreen(pixel, ClampToQuantum(in[1] * QuantumRange)); SetPixelBlue(pixel, ClampToQuantum(in[2] * QuantumRange)); // Distinct from "opacity", which treats 0 as opaque SetPixelAlpha(pixel, ClampToQuantum(in[3] * QuantumRange)); }
void sanpera_magick_pixel_from_doubles_channel( MagickPixelPacket *pixel, double in[4], ChannelType channels) { if (channels & RedChannel) SetPixelRed(pixel, ClampToQuantum(in[0] * QuantumRange)); if (channels & GreenChannel) SetPixelGreen(pixel, ClampToQuantum(in[1] * QuantumRange)); if (channels & BlueChannel) SetPixelBlue(pixel, ClampToQuantum(in[2] * QuantumRange)); // Distinct from "opacity", which treats 0 as opaque if (channels & AlphaChannel) SetPixelAlpha(pixel, ClampToQuantum(in[3] * QuantumRange)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % G e t O n e C a c h e V i e w V i r t u a l P i x e l % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetOneCacheViewVirtualPixel() returns a single pixel at the specified (x,y) % location. The image background color is returned if an error occurs. If % you plan to modify the pixel, use GetOneCacheViewAuthenticPixel() instead. % % The format of the GetOneCacheViewVirtualPixel method is: % % MagickBooleanType GetOneCacheViewVirtualPixel( % const CacheView *cache_view,const ssize_t x,const ssize_t y, % Quantum *pixel,ExceptionInfo *exception) % % A description of each parameter follows: % % o cache_view: the cache view. % % o x,y: These values define the offset of the pixel. % % o pixel: return a pixel at the specified (x,y) location. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType GetOneCacheViewVirtualPixel( const CacheView *cache_view,const ssize_t x,const ssize_t y,Quantum *pixel, ExceptionInfo *exception) { const int id = GetOpenMPThreadId(); register const Quantum *magick_restrict p; register ssize_t i; assert(cache_view != (CacheView *) NULL); assert(cache_view->signature == MagickCoreSignature); assert(id < (int) cache_view->number_threads); (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel)); p=GetVirtualPixelsFromNexus(cache_view->image, cache_view->virtual_pixel_method,x,y,1,1,cache_view->nexus_info[id], exception); if (p == (const Quantum *) NULL) { PixelInfo background_color; background_color=cache_view->image->background_color; pixel[RedPixelChannel]=ClampToQuantum(background_color.red); pixel[GreenPixelChannel]=ClampToQuantum(background_color.green); pixel[BluePixelChannel]=ClampToQuantum(background_color.blue); pixel[BlackPixelChannel]=ClampToQuantum(background_color.black); pixel[AlphaPixelChannel]=ClampToQuantum(background_color.alpha); return(MagickFalse); } for (i=0; i < (ssize_t) GetPixelChannels(cache_view->image); i++) { PixelChannel channel=GetPixelChannelChannel(cache_view->image,i); pixel[channel]=p[i]; } return(MagickTrue); }
static int PrintChannelStatistics(FILE *file,const ChannelType channel, const char *name,const double scale, const ChannelStatistics *channel_statistics) { #define StatisticsFormat " %s:\n min: " QuantumFormat \ " (%g)\n max: " QuantumFormat " (%g)\n" \ " mean: %g (%g)\n standard deviation: %g (%g)\n" \ " kurtosis: %g\n skewness: %g\n" int status; if (channel == AlphaChannel) { status=fprintf(file,StatisticsFormat,name,ClampToQuantum(scale* (QuantumRange-channel_statistics[channel].maxima)), (QuantumRange-channel_statistics[channel].maxima)/(double) QuantumRange, ClampToQuantum(scale*(QuantumRange-channel_statistics[channel].minima)), (QuantumRange-channel_statistics[channel].minima)/(double) QuantumRange, scale*(QuantumRange-channel_statistics[channel].mean),(QuantumRange- channel_statistics[channel].mean)/(double) QuantumRange,scale* channel_statistics[channel].standard_deviation, channel_statistics[channel].standard_deviation/(double) QuantumRange, channel_statistics[channel].kurtosis, channel_statistics[channel].skewness); return(status); } status=fprintf(file,StatisticsFormat,name,ClampToQuantum(scale* channel_statistics[channel].minima),channel_statistics[channel].minima/ (double) QuantumRange,ClampToQuantum(scale* channel_statistics[channel].maxima),channel_statistics[channel].maxima/ (double) QuantumRange,scale*channel_statistics[channel].mean, channel_statistics[channel].mean/(double) QuantumRange,scale* channel_statistics[channel].standard_deviation, channel_statistics[channel].standard_deviation/(double) QuantumRange, channel_statistics[channel].kurtosis,channel_statistics[channel].skewness); return(status); }
static ssize_t PrintChannelStatistics(FILE *file,const PixelChannel channel, const char *name,const double scale, const ChannelStatistics *channel_statistics) { #define StatisticsFormat " %s:\n min: " QuantumFormat \ " (%g)\n max: " QuantumFormat " (%g)\n" \ " mean: %g (%g)\n standard deviation: %g (%g)\n" \ " kurtosis: %g\n skewness: %g\n" ssize_t n; n=FormatLocaleFile(file,StatisticsFormat,name,ClampToQuantum(scale* channel_statistics[channel].minima),channel_statistics[channel].minima/ (double) QuantumRange,ClampToQuantum(scale* channel_statistics[channel].maxima),channel_statistics[channel].maxima/ (double) QuantumRange,scale*channel_statistics[channel].mean, channel_statistics[channel].mean/(double) QuantumRange,scale* channel_statistics[channel].standard_deviation, channel_statistics[channel].standard_deviation/(double) QuantumRange, channel_statistics[channel].kurtosis,channel_statistics[channel].skewness); return(n); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % C o n v e r t H W B T o R G B % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green, % blue) triple. % % The format of the ConvertHWBToRGBImage method is: % % void ConvertHWBToRGB(const double hue,const double whiteness, % const double blackness,Quantum *red,Quantum *green,Quantum *blue) % % A description of each parameter follows: % % o hue, whiteness, blackness: A double value representing a % component of the HWB color space. % % o red, green, blue: A pointer to a pixel component of type Quantum. % */ MagickExport void ConvertHWBToRGB(const double hue,const double whiteness, const double blackness,Quantum *red,Quantum *green,Quantum *blue) { MagickRealType b, f, g, n, r, v; register ssize_t i; /* Convert HWB to RGB colorspace. */ assert(red != (Quantum *) NULL); assert(green != (Quantum *) NULL); assert(blue != (Quantum *) NULL); v=1.0-blackness; if (hue == 0.0) { *red=ClampToQuantum((MagickRealType) QuantumRange*v); *green=ClampToQuantum((MagickRealType) QuantumRange*v); *blue=ClampToQuantum((MagickRealType) QuantumRange*v); return; } i=(ssize_t) floor(6.0*hue); f=6.0*hue-i; if ((i & 0x01) != 0) f=1.0-f; n=whiteness+f*(v-whiteness); /* linear interpolation */ switch (i) { default: case 6: case 0: r=v; g=n; b=whiteness; break; case 1: r=n; g=v; b=whiteness; break; case 2: r=whiteness; g=v; b=n; break; case 3: r=whiteness; g=n; b=v; break; case 4: r=n; g=whiteness; b=v; break; case 5: r=v; g=whiteness; b=n; break; } *red=ClampToQuantum((MagickRealType) QuantumRange*r); *green=ClampToQuantum((MagickRealType) QuantumRange*g); *blue=ClampToQuantum((MagickRealType) QuantumRange*b); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d E X R I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadEXRImage reads an image in the high dynamic-range (HDR) file format % developed by Industrial Light & Magic. It allocates the memory necessary % for the new Image structure and returns a pointer to the new image. % % The format of the ReadEXRImage method is: % % Image *ReadEXRImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadEXRImage(const ImageInfo *image_info,ExceptionInfo *exception) { const ImfHeader *hdr_info; Image *image; ImageInfo *read_info; ImfInputFile *file; ImfRgba *scanline; int max_x, max_y, min_x, min_y; MagickBooleanType status; register ssize_t x; register Quantum *q; ssize_t y; /* Open image. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info,exception); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } read_info=CloneImageInfo(image_info); if (IsPathAccessible(read_info->filename) == MagickFalse) { (void) AcquireUniqueFilename(read_info->filename); (void) ImageToFile(image,read_info->filename,exception); } file=ImfOpenInputFile(read_info->filename); if (file == (ImfInputFile *) NULL) { ThrowFileException(exception,BlobError,"UnableToOpenBlob", ImfErrorMessage()); read_info=DestroyImageInfo(read_info); return((Image *) NULL); } hdr_info=ImfInputHeader(file); ImfHeaderDataWindow(hdr_info,&min_x,&min_y,&max_x,&max_y); image->columns=max_x-min_x+1UL; image->rows=max_y-min_y+1UL; image->matte=MagickTrue; if (image_info->ping != MagickFalse) { (void) ImfCloseInputFile(file); if (LocaleCompare(image_info->filename,read_info->filename) != 0) (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); (void) CloseBlob(image); return(GetFirstImageInList(image)); } scanline=(ImfRgba *) AcquireQuantumMemory(image->columns,sizeof(*scanline)); if (scanline == (ImfRgba *) NULL) { (void) ImfCloseInputFile(file); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; ImfInputSetFrameBuffer(file,scanline-min_x-image->columns*(min_y+y),1, image->columns); ImfInputReadPixels(file,min_y+y,min_y+y); for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange* ImfHalfToFloat(scanline[x].r)),q); SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange* ImfHalfToFloat(scanline[x].g)),q); SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange* ImfHalfToFloat(scanline[x].b)),q); SetPixelAlpha(image,ClampToQuantum((MagickRealType) QuantumRange* ImfHalfToFloat(scanline[x].a)),q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; } scanline=(ImfRgba *) RelinquishMagickMemory(scanline); (void) ImfCloseInputFile(file); if (LocaleCompare(image_info->filename,read_info->filename) != 0) (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % C o n v e r t H C L T o R G B % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green, % blue) triple. % % The format of the ConvertHCLToRGBImage method is: % % void ConvertHCLToRGB(const double hue,const double chroma, % const double luma,Quantum *red,Quantum *green,Quantum *blue) % % A description of each parameter follows: % % o hue, chroma, luma: A double value representing a % component of the HCL color space. % % o red, green, blue: A pointer to a pixel component of type Quantum. % */ MagickExport void ConvertHCLToRGB(const double hue,const double chroma, const double luma,Quantum *red,Quantum *green,Quantum *blue) { double b, c, g, h, m, r, x; /* Convert HCL to RGB colorspace. */ assert(red != (Quantum *) NULL); assert(green != (Quantum *) NULL); assert(blue != (Quantum *) NULL); h=6.0*hue; c=chroma; x=c*(1.0-fabs(fmod(h,2.0)-1.0)); r=0.0; g=0.0; b=0.0; if ((0.0 <= h) && (h < 1.0)) { r=c; g=x; } else if ((1.0 <= h) && (h < 2.0)) { r=x; g=c; } else if ((2.0 <= h) && (h < 3.0)) { g=c; b=x; } else if ((3.0 <= h) && (h < 4.0)) { g=x; b=c; } else if ((4.0 <= h) && (h < 5.0)) { r=x; b=c; } else if ((5.0 <= h) && (h < 6.0)) { r=c; b=x; } m=luma-(0.298839f*r+0.586811f*g+0.114350f*b); *red=ClampToQuantum(QuantumRange*(r+m)); *green=ClampToQuantum(QuantumRange*(g+m)); *blue=ClampToQuantum(QuantumRange*(b+m)); }
static MagickBooleanType ForwardFourier(const FourierInfo *fourier_info, Image *image,double *magnitude,double *phase,ExceptionInfo *exception) { CacheView *magnitude_view, *phase_view; double *magnitude_source, *phase_source; Image *magnitude_image, *phase_image; MagickBooleanType status; register IndexPacket *indexes; register ssize_t x; register PixelPacket *q; ssize_t i, y; magnitude_image=GetFirstImageInList(image); phase_image=GetNextImageInList(image); if (phase_image == (Image *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(),ImageError, "ImageSequenceRequired","`%s'",image->filename); return(MagickFalse); } /* Create "Fourier Transform" image from constituent arrays. */ magnitude_source=(double *) AcquireQuantumMemory((size_t) fourier_info->height,fourier_info->width*sizeof(*magnitude_source)); if (magnitude_source == (double *) NULL) return(MagickFalse); (void) ResetMagickMemory(magnitude_source,0,fourier_info->height* fourier_info->width*sizeof(*magnitude_source)); phase_source=(double *) AcquireQuantumMemory((size_t) fourier_info->height, fourier_info->width*sizeof(*phase_source)); if (phase_source == (double *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); magnitude_source=(double *) RelinquishMagickMemory(magnitude_source); return(MagickFalse); } status=ForwardQuadrantSwap(fourier_info->height,fourier_info->height, magnitude,magnitude_source); if (status != MagickFalse) status=ForwardQuadrantSwap(fourier_info->height,fourier_info->height,phase, phase_source); CorrectPhaseLHS(fourier_info->height,fourier_info->height,phase_source); if (fourier_info->modulus != MagickFalse) { i=0L; for (y=0L; y < (ssize_t) fourier_info->height; y++) for (x=0L; x < (ssize_t) fourier_info->width; x++) { phase_source[i]/=(2.0*MagickPI); phase_source[i]+=0.5; i++; } } magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception); i=0L; for (y=0L; y < (ssize_t) fourier_info->height; y++) { q=GetCacheViewAuthenticPixels(magnitude_view,0L,y,fourier_info->height,1UL, exception); if (q == (PixelPacket *) NULL) break; indexes=GetCacheViewAuthenticIndexQueue(magnitude_view); for (x=0L; x < (ssize_t) fourier_info->width; x++) { switch (fourier_info->channel) { case RedChannel: default: { SetPixelRed(q,ClampToQuantum(QuantumRange* magnitude_source[i])); break; } case GreenChannel: { SetPixelGreen(q,ClampToQuantum(QuantumRange* magnitude_source[i])); break; } case BlueChannel: { SetPixelBlue(q,ClampToQuantum(QuantumRange* magnitude_source[i])); break; } case OpacityChannel: { SetPixelOpacity(q,ClampToQuantum(QuantumRange* magnitude_source[i])); break; } case IndexChannel: { SetPixelIndex(indexes+x,ClampToQuantum(QuantumRange* magnitude_source[i])); break; } case GrayChannels: { SetPixelGray(q,ClampToQuantum(QuantumRange* magnitude_source[i])); break; } } i++; q++; } status=SyncCacheViewAuthenticPixels(magnitude_view,exception); if (status == MagickFalse) break; } magnitude_view=DestroyCacheView(magnitude_view); i=0L; phase_view=AcquireAuthenticCacheView(phase_image,exception); for (y=0L; y < (ssize_t) fourier_info->height; y++) { q=GetCacheViewAuthenticPixels(phase_view,0L,y,fourier_info->height,1UL, exception); if (q == (PixelPacket *) NULL) break; indexes=GetCacheViewAuthenticIndexQueue(phase_view); for (x=0L; x < (ssize_t) fourier_info->width; x++) { switch (fourier_info->channel) { case RedChannel: default: { SetPixelRed(q,ClampToQuantum(QuantumRange*phase_source[i])); break; } case GreenChannel: { SetPixelGreen(q,ClampToQuantum(QuantumRange*phase_source[i])); break; } case BlueChannel: { SetPixelBlue(q,ClampToQuantum(QuantumRange*phase_source[i])); break; } case OpacityChannel: { SetPixelOpacity(q,ClampToQuantum(QuantumRange*phase_source[i])); break; } case IndexChannel: { SetPixelIndex(indexes+x,ClampToQuantum(QuantumRange*phase_source[i])); break; } case GrayChannels: { SetPixelGray(q,ClampToQuantum(QuantumRange*phase_source[i])); break; } } i++; q++; } status=SyncCacheViewAuthenticPixels(phase_view,exception); if (status == MagickFalse) break; } phase_view=DestroyCacheView(phase_view); phase_source=(double *) RelinquishMagickMemory(phase_source); magnitude_source=(double *) RelinquishMagickMemory(magnitude_source); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d H A L D I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadHALDImage() creates a Hald color lookup table image 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 ReadHALDImage method is: % % Image *ReadHALDImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadHALDImage(const ImageInfo *image_info, ExceptionInfo *exception) { Image *image; MagickBooleanType status; size_t cube_size, level; ssize_t y; /* Create HALD color lookup table image. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); level=0; if (*image_info->filename != '\0') level=StringToUnsignedLong(image_info->filename); if (level < 2) level=8; status=MagickTrue; cube_size=level*level; image->columns=(size_t) (level*cube_size); image->rows=(size_t) (level*cube_size); for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) level) { ssize_t blue, green, red; register PixelPacket *restrict q; if (status == MagickFalse) continue; q=QueueAuthenticPixels(image,0,y,image->columns,(size_t) level, exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } blue=y/(ssize_t) level; for (green=0; green < (ssize_t) cube_size; green++) { for (red=0; red < (ssize_t) cube_size; red++) { SetPixelRed(q,ClampToQuantum(QuantumRange*red/ (cube_size-1.0))); SetPixelGreen(q,ClampToQuantum(QuantumRange*green/ (cube_size-1.0))); SetPixelBlue(q,ClampToQuantum(QuantumRange*blue/ (cube_size-1.0))); SetPixelOpacity(q,OpaqueOpacity); q++; } } if (SyncAuthenticPixels(image,exception) == MagickFalse) status=MagickFalse; } return(GetFirstImageInList(image)); }
MagickExport MagickBooleanType OpaquePaintImageChannel(Image *image, const ChannelType channel,const MagickPixelPacket *target, const MagickPixelPacket *fill,const MagickBooleanType invert) { #define OpaquePaintImageTag "Opaque/Image" CacheView *image_view; ExceptionInfo *exception; MagickBooleanType status; MagickOffsetType progress; MagickPixelPacket zero; ssize_t y; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(target != (MagickPixelPacket *) NULL); assert(fill != (MagickPixelPacket *) NULL); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if (SetImageStorageClass(image,DirectClass) == MagickFalse) return(MagickFalse); if ((IsGrayColorspace(image->colorspace) != MagickFalse) && (IsMagickGray(fill) != MagickFalse)) (void) TransformImageColorspace(image,sRGBColorspace); if ((fill->opacity != OpaqueOpacity) && (image->matte == MagickFalse)) (void) SetImageAlphaChannel(image,OpaqueAlphaChannel); /* Make image color opaque. */ status=MagickTrue; progress=0; exception=(&image->exception); GetMagickPixelPacket(image,&zero); image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(progress,status) \ IsConcurrentDos(image->columns,image->rows,64) #endif for (y=0; y < (ssize_t) image->rows; y++) { MagickPixelPacket pixel; register IndexPacket *restrict indexes; register ssize_t x; register PixelPacket *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } indexes=GetCacheViewAuthenticIndexQueue(image_view); pixel=zero; for (x=0; x < (ssize_t) image->columns; x++) { SetMagickPixelPacket(image,q,indexes+x,&pixel); if (IsMagickColorSimilar(&pixel,target) != invert) { if ((channel & RedChannel) != 0) SetPixelRed(q,ClampToQuantum(fill->red)); if ((channel & GreenChannel) != 0) SetPixelGreen(q,ClampToQuantum(fill->green)); if ((channel & BlueChannel) != 0) SetPixelBlue(q,ClampToQuantum(fill->blue)); if ((channel & OpacityChannel) != 0) SetPixelOpacity(q,ClampToQuantum(fill->opacity)); if (((channel & IndexChannel) != 0) && (image->colorspace == CMYKColorspace)) SetPixelIndex(indexes+x,ClampToQuantum(fill->index)); } q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_OpaquePaintImageChannel) #endif proceed=SetImageProgress(image,OpaquePaintImageTag,progress++, image->rows); if (proceed == MagickFalse) status=MagickFalse; } } image_view=DestroyCacheView(image_view); return(status); }
static MagickBooleanType InverseFourierTransform(FourierInfo *fourier_info, fftw_complex *fourier,Image *image,ExceptionInfo *exception) { CacheView *image_view; double *source; fftw_plan fftw_c2r_plan; register IndexPacket *indexes; register PixelPacket *q; register ssize_t i, x; ssize_t y; source=(double *) AcquireQuantumMemory((size_t) fourier_info->height, fourier_info->width*sizeof(*source)); if (source == (double *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); return(MagickFalse); } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_InverseFourierTransform) #endif { fftw_c2r_plan=fftw_plan_dft_c2r_2d(fourier_info->width,fourier_info->height, fourier,source,FFTW_ESTIMATE); fftw_execute(fftw_c2r_plan); fftw_destroy_plan(fftw_c2r_plan); } i=0L; image_view=AcquireAuthenticCacheView(image,exception); for (y=0L; y < (ssize_t) fourier_info->height; y++) { if (y >= (ssize_t) image->rows) break; q=GetCacheViewAuthenticPixels(image_view,0L,y,fourier_info->width > image->columns ? image->columns : fourier_info->width,1UL,exception); if (q == (PixelPacket *) NULL) break; indexes=GetCacheViewAuthenticIndexQueue(image_view); for (x=0L; x < (ssize_t) fourier_info->width; x++) { if (x < (ssize_t) image->columns) switch (fourier_info->channel) { case RedChannel: default: { SetPixelRed(q,ClampToQuantum(QuantumRange*source[i])); break; } case GreenChannel: { SetPixelGreen(q,ClampToQuantum(QuantumRange*source[i])); break; } case BlueChannel: { SetPixelBlue(q,ClampToQuantum(QuantumRange*source[i])); break; } case OpacityChannel: { SetPixelOpacity(q,ClampToQuantum(QuantumRange*source[i])); break; } case IndexChannel: { SetPixelIndex(indexes+x,ClampToQuantum(QuantumRange*source[i])); break; } case GrayChannels: { SetPixelGray(q,ClampToQuantum(QuantumRange*source[i])); break; } } i++; q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) break; } image_view=DestroyCacheView(image_view); source=(double *) RelinquishMagickMemory(source); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % C o m b i n e I m a g e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % CombineImages() combines one or more images into a single image. The % grayscale value of the pixels of each image in the sequence is assigned in % order to the specified channels of the combined image. The typical % ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc. % % The format of the CombineImages method is: % % Image *CombineImages(const Image *image,const ChannelType channel, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *CombineImages(const Image *image,const ChannelType channel, ExceptionInfo *exception) { #define CombineImageTag "Combine/Image" CacheView *combine_view; const Image *next; Image *combine_image; MagickBooleanType status; MagickOffsetType progress; ssize_t y; /* Ensure the image are the same size. */ assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); for (next=image; next != (Image *) NULL; next=GetNextImageInList(next)) { if ((next->columns != image->columns) || (next->rows != image->rows)) ThrowImageException(OptionError,"ImagesAreNotTheSameSize"); } combine_image=CloneImage(image,0,0,MagickTrue,exception); if (combine_image == (Image *) NULL) return((Image *) NULL); if (SetImageStorageClass(combine_image,DirectClass) == MagickFalse) { InheritException(exception,&combine_image->exception); combine_image=DestroyImage(combine_image); return((Image *) NULL); } if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse) (void) SetImageColorspace(combine_image,sRGBColorspace); if ((channel & OpacityChannel) != 0) combine_image->matte=MagickTrue; (void) SetImageBackgroundColor(combine_image); /* Combine images. */ status=MagickTrue; progress=0; combine_view=AcquireAuthenticCacheView(combine_image,exception); for (y=0; y < (ssize_t) combine_image->rows; y++) { CacheView *image_view; const Image *next; PixelPacket *pixels; register const PixelPacket *restrict p; register PixelPacket *restrict q; register ssize_t x; if (status == MagickFalse) continue; pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns, 1,exception); if (pixels == (PixelPacket *) NULL) { status=MagickFalse; continue; } next=image; if (((channel & RedChannel) != 0) && (next != (Image *) NULL)) { image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; q=pixels; for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelRed(q,ClampToQuantum(GetPixelIntensity(image,p))); p++; q++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (((channel & GreenChannel) != 0) && (next != (Image *) NULL)) { image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; q=pixels; for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelGreen(q,ClampToQuantum(GetPixelIntensity(image,p))); p++; q++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (((channel & BlueChannel) != 0) && (next != (Image *) NULL)) { image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; q=pixels; for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelBlue(q,ClampToQuantum(GetPixelIntensity(image,p))); p++; q++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (((channel & OpacityChannel) != 0) && (next != (Image *) NULL)) { image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; q=pixels; for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelAlpha(q,ClampToQuantum(GetPixelIntensity(image,p))); p++; q++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (((channel & IndexChannel) != 0) && (image->colorspace == CMYKColorspace) && (next != (Image *) NULL)) { IndexPacket *indexes; image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; indexes=GetCacheViewAuthenticIndexQueue(combine_view); for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelIndex(indexes+x,ClampToQuantum(GetPixelIntensity(image,p))); p++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; proceed=SetImageProgress(image,CombineImageTag,progress++, combine_image->rows); if (proceed == MagickFalse) status=MagickFalse; } } combine_view=DestroyCacheView(combine_view); if (IsGrayColorspace(combine_image->colorspace) != MagickFalse) (void) TransformImageColorspace(combine_image,sRGBColorspace); if (status == MagickFalse) combine_image=DestroyImage(combine_image); return(combine_image); }
MagickExport MagickBooleanType SeparateImageChannel(Image *image, const ChannelType channel) { #define SeparateImageTag "Separate/Image" CacheView *image_view; ExceptionInfo *exception; MagickBooleanType status; MagickOffsetType progress; ssize_t y; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if (SetImageStorageClass(image,DirectClass) == MagickFalse) return(MagickFalse); if (channel == GrayChannels) image->matte=MagickTrue; /* Separate image channels. */ status=MagickTrue; progress=0; exception=(&image->exception); image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(progress,status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register IndexPacket *restrict indexes; register PixelPacket *restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } indexes=GetCacheViewAuthenticIndexQueue(image_view); switch (channel) { case RedChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelGreen(q,GetPixelRed(q)); SetPixelBlue(q,GetPixelRed(q)); q++; } break; } case GreenChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelGreen(q)); SetPixelBlue(q,GetPixelGreen(q)); q++; } break; } case BlueChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelBlue(q)); SetPixelGreen(q,GetPixelBlue(q)); q++; } break; } case OpacityChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelOpacity(q)); SetPixelGreen(q,GetPixelOpacity(q)); SetPixelBlue(q,GetPixelOpacity(q)); q++; } break; } case BlackChannel: { if ((image->storage_class != PseudoClass) && (image->colorspace != CMYKColorspace)) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelIndex(indexes+x)); SetPixelGreen(q,GetPixelIndex(indexes+x)); SetPixelBlue(q,GetPixelIndex(indexes+x)); q++; } break; } case TrueAlphaChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelAlpha(q)); SetPixelGreen(q,GetPixelAlpha(q)); SetPixelBlue(q,GetPixelAlpha(q)); q++; } break; } case GrayChannels: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelAlpha(q,ClampToQuantum(GetPixelIntensity(image,q))); q++; } break; } default: break; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_SeparateImageChannel) #endif proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } image_view=DestroyCacheView(image_view); if (channel != GrayChannels) image->matte=MagickFalse; (void) SetImageColorspace(image,GRAYColorspace); return(status); }
MagickExport MagickBooleanType SetImageAlphaChannel(Image *image, const AlphaChannelOption alpha_type,ExceptionInfo *exception) { CacheView *image_view; MagickBooleanType status; ssize_t y; assert(image != (Image *) NULL); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(image->signature == MagickSignature); status=MagickTrue; switch (alpha_type) { case ActivateAlphaChannel: { image->alpha_trait=BlendPixelTrait; break; } case AssociateAlphaChannel: { /* Associate alpha. */ status=SetImageStorageClass(image,DirectClass,exception); if (status == MagickFalse) break; image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register Quantum *restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, exception); if (q == (Quantum *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { double Sa; register ssize_t i; if (GetPixelReadMask(image,q) == 0) { q+=GetPixelChannels(image); continue; } Sa=QuantumScale*GetPixelAlpha(image,q); for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { PixelChannel channel=GetPixelChannelChannel(image,i); PixelTrait traits=GetPixelChannelTraits(image,channel); if ((traits & UpdatePixelTrait) == 0) continue; q[i]=ClampToQuantum(Sa*q[i]); } q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; } image_view=DestroyCacheView(image_view); image->alpha_trait=CopyPixelTrait; return(status); } case BackgroundAlphaChannel: { /* Set transparent pixels to background color. */ if (image->alpha_trait != BlendPixelTrait) break; status=SetImageStorageClass(image,DirectClass,exception); if (status == MagickFalse) break; image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register Quantum *restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, exception); if (q == (Quantum *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { if (GetPixelAlpha(image,q) == TransparentAlpha) { SetPixelInfoPixel(image,&image->background_color,q); SetPixelChannel(image,AlphaPixelChannel,TransparentAlpha,q); } q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; } image_view=DestroyCacheView(image_view); return(status); } case CopyAlphaChannel: case ShapeAlphaChannel: { /* Copy pixel intensity to the alpha channel. */ status=CompositeImage(image,image,IntensityCompositeOp,MagickTrue,0,0, exception); if (alpha_type == ShapeAlphaChannel) (void) LevelImageColors(image,&image->background_color, &image->background_color,MagickTrue,exception); break; } case DeactivateAlphaChannel: { image->alpha_trait=CopyPixelTrait; break; } case DisassociateAlphaChannel: { /* Disassociate alpha. */ status=SetImageStorageClass(image,DirectClass,exception); if (status == MagickFalse) break; image->alpha_trait=BlendPixelTrait; image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register Quantum *restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, exception); if (q == (Quantum *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { double gamma, Sa; register ssize_t i; if (GetPixelReadMask(image,q) == 0) { q+=GetPixelChannels(image); continue; } Sa=QuantumScale*GetPixelAlpha(image,q); gamma=PerceptibleReciprocal(Sa); for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { PixelChannel channel=GetPixelChannelChannel(image,i); PixelTrait traits=GetPixelChannelTraits(image,channel); if ((traits & UpdatePixelTrait) == 0) continue; q[i]=ClampToQuantum(gamma*q[i]); } q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; } image_view=DestroyCacheView(image_view); return(status); } case DiscreteAlphaChannel: { image->alpha_trait=UpdatePixelTrait; break; } case ExtractAlphaChannel: { status=CompositeImage(image,image,AlphaCompositeOp,MagickTrue,0,0, exception); image->alpha_trait=CopyPixelTrait; break; } case OpaqueAlphaChannel: { status=SetImageAlpha(image,OpaqueAlpha,exception); break; } case RemoveAlphaChannel: { /* Remove transparency. */ if (image->alpha_trait != BlendPixelTrait) break; status=SetImageStorageClass(image,DirectClass,exception); if (status == MagickFalse) break; image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register Quantum *restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, exception); if (q == (Quantum *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { FlattenPixelInfo(image,&image->background_color, image->background_color.alpha,q,(double) GetPixelAlpha(image,q),q); q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; } image_view=DestroyCacheView(image_view); image->alpha_trait=image->background_color.alpha_trait; return(status); } case SetAlphaChannel: { if (image->alpha_trait != BlendPixelTrait) status=SetImageAlpha(image,OpaqueAlpha,exception); break; } case TransparentAlphaChannel: { status=SetImageAlpha(image,TransparentAlpha,exception); break; } case UndefinedAlphaChannel: break; } if (status == MagickFalse) return(status); return(SyncImagePixelCache(image,exception)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d H D R I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadHDRImage() reads the Radiance RGBE image format 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 ReadHDRImage method is: % % Image *ReadHDRImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadHDRImage(const ImageInfo *image_info,ExceptionInfo *exception) { char format[MaxTextExtent], keyword[MaxTextExtent], tag[MaxTextExtent], value[MaxTextExtent]; double gamma; Image *image; int c; MagickBooleanType status, value_expected; register PixelPacket *q; register unsigned char *p; register ssize_t i, x; ssize_t count, y; unsigned char *end, pixel[4], *pixels; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } /* Decode image header. */ image->columns=0; image->rows=0; *format='\0'; c=ReadBlobByte(image); if (c == EOF) { image=DestroyImage(image); return((Image *) NULL); } while (isgraph(c) && (image->columns == 0) && (image->rows == 0)) { if (c == (int) '#') { char *comment; register char *p; size_t length; /* Read comment-- any text between # and end-of-line. */ length=MaxTextExtent; comment=AcquireString((char *) NULL); for (p=comment; comment != (char *) NULL; p++) { c=ReadBlobByte(image); if ((c == EOF) || (c == (int) '\n')) break; if ((size_t) (p-comment+1) >= length) { *p='\0'; length<<=1; comment=(char *) ResizeQuantumMemory(comment,length+ MaxTextExtent,sizeof(*comment)); if (comment == (char *) NULL) break; p=comment+strlen(comment); } *p=(char) c; } if (comment == (char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); *p='\0'; (void) SetImageProperty(image,"comment",comment); comment=DestroyString(comment); c=ReadBlobByte(image); } else if (isalnum(c) == MagickFalse) c=ReadBlobByte(image); else { register char *p; /* Determine a keyword and its value. */ p=keyword; do { if ((size_t) (p-keyword) < (MaxTextExtent-1)) *p++=c; c=ReadBlobByte(image); } while (isalnum(c) || (c == '_')); *p='\0'; value_expected=MagickFalse; while ((isspace((int) ((unsigned char) c)) != 0) || (c == '=')) { if (c == '=') value_expected=MagickTrue; c=ReadBlobByte(image); } if (LocaleCompare(keyword,"Y") == 0) value_expected=MagickTrue; if (value_expected == MagickFalse) continue; p=value; while ((c != '\n') && (c != '\0') && (c != EOF)) { if ((size_t) (p-value) < (MaxTextExtent-1)) *p++=c; c=ReadBlobByte(image); } *p='\0'; /* Assign a value to the specified keyword. */ switch (*keyword) { case 'F': case 'f': { if (LocaleCompare(keyword,"format") == 0) { (void) CopyMagickString(format,value,MaxTextExtent); break; } (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword); (void) SetImageProperty(image,tag,value); break; } case 'G': case 'g': { if (LocaleCompare(keyword,"gamma") == 0) { image->gamma=StringToDouble(value,(char **) NULL); break; } (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword); (void) SetImageProperty(image,tag,value); break; } case 'P': case 'p': { if (LocaleCompare(keyword,"primaries") == 0) { float chromaticity[6], white_point[2]; int count; count=sscanf(value,"%g %g %g %g %g %g %g %g",&chromaticity[0], &chromaticity[1],&chromaticity[2],&chromaticity[3], &chromaticity[4],&chromaticity[5],&white_point[0], &white_point[1]); if (count == 8) { image->chromaticity.red_primary.x=chromaticity[0]; image->chromaticity.red_primary.y=chromaticity[1]; image->chromaticity.green_primary.x=chromaticity[2]; image->chromaticity.green_primary.y=chromaticity[3]; image->chromaticity.blue_primary.x=chromaticity[4]; image->chromaticity.blue_primary.y=chromaticity[5]; image->chromaticity.white_point.x=white_point[0], image->chromaticity.white_point.y=white_point[1]; } break; } (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword); (void) SetImageProperty(image,tag,value); break; } case 'Y': case 'y': { char target[] = "Y"; if (strcmp(keyword,target) == 0) { int height, width; if (sscanf(value,"%d +X %d",&height,&width) == 2) { image->columns=(size_t) width; image->rows=(size_t) height; } break; } (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword); (void) SetImageProperty(image,tag,value); break; } default: { (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword); (void) SetImageProperty(image,tag,value); break; } } } if ((image->columns == 0) && (image->rows == 0)) while (isspace((int) ((unsigned char) c)) != 0) c=ReadBlobByte(image); } if ((LocaleCompare(format,"32-bit_rle_rgbe") != 0) && (LocaleCompare(format,"32-bit_rle_xyze") != 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); if ((image->columns == 0) || (image->rows == 0)) ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize"); (void) SetImageColorspace(image,RGBColorspace); if (LocaleCompare(format,"32-bit_rle_xyze") == 0) (void) SetImageColorspace(image,XYZColorspace); image->compression=(image->columns < 8) || (image->columns > 0x7ffff) ? NoCompression : RLECompression; if (image_info->ping != MagickFalse) { (void) CloseBlob(image); return(GetFirstImageInList(image)); } status=SetImageExtent(image,image->columns,image->rows); if (status == MagickFalse) { InheritException(exception,&image->exception); return(DestroyImageList(image)); } /* Read RGBE (red+green+blue+exponent) pixels. */ pixels=(unsigned char *) AcquireQuantumMemory(image->columns,4* sizeof(*pixels)); if (pixels == (unsigned char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); for (y=0; y < (ssize_t) image->rows; y++) { if (image->compression != RLECompression) { count=ReadBlob(image,4*image->columns*sizeof(*pixels),pixels); if (count != (ssize_t) (4*image->columns*sizeof(*pixels))) break; } else { count=ReadBlob(image,4*sizeof(*pixel),pixel); if (count != 4) break; if ((size_t) ((((size_t) pixel[2]) << 8) | pixel[3]) != image->columns) { (void) memcpy(pixels,pixel,4*sizeof(*pixel)); (void) ReadBlob(image,4*(image->columns-1)*sizeof(*pixels),pixels+4); image->compression=NoCompression; } else { p=pixels; for (i=0; i < 4; i++) { end=&pixels[(i+1)*image->columns]; while (p < end) { count=ReadBlob(image,2*sizeof(*pixel),pixel); if (count < 1) break; if (pixel[0] > 128) { count=(ssize_t) pixel[0]-128; if ((count == 0) || (count > (ssize_t) (end-p))) break; while (count-- > 0) *p++=pixel[1]; } else { count=(ssize_t) pixel[0]; if ((count == 0) || (count > (ssize_t) (end-p))) break; *p++=pixel[1]; if (--count > 0) { count=ReadBlob(image,(size_t) count*sizeof(*p),p); if (count < 1) break; p+=count; } } } } } } q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; i=0; for (x=0; x < (ssize_t) image->columns; x++) { if (image->compression == RLECompression) { pixel[0]=pixels[x]; pixel[1]=pixels[x+image->columns]; pixel[2]=pixels[x+2*image->columns]; pixel[3]=pixels[x+3*image->columns]; } else { pixel[0]=pixels[i++]; pixel[1]=pixels[i++]; pixel[2]=pixels[i++]; pixel[3]=pixels[i++]; } SetPixelRed(q,0); SetPixelGreen(q,0); SetPixelBlue(q,0); if (pixel[3] != 0) { gamma=pow(2.0,pixel[3]-(128.0+8.0)); SetPixelRed(q,ClampToQuantum(QuantumRange*gamma*pixel[0])); SetPixelGreen(q,ClampToQuantum(QuantumRange*gamma*pixel[1])); SetPixelBlue(q,ClampToQuantum(QuantumRange*gamma*pixel[2])); } q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } pixels=(unsigned char *) RelinquishMagickMemory(pixels); if (EOFBlob(image) != MagickFalse) ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
static inline void FlattenPixelInfo(const Image *image,const PixelInfo *p, const double alpha,const Quantum *q,const double beta, Quantum *composite) { double Da, gamma, Sa; register ssize_t i; /* Compose pixel p over pixel q with the given alpha. */ Sa=QuantumScale*alpha; Da=QuantumScale*beta, gamma=Sa*(-Da)+Sa+Da; gamma=PerceptibleReciprocal(gamma); for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { PixelChannel channel=GetPixelChannelChannel(image,i); PixelTrait traits=GetPixelChannelTraits(image,channel); if (traits == UndefinedPixelTrait) continue; switch (channel) { case RedPixelChannel: { composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta, (double) p->red,alpha)); break; } case GreenPixelChannel: { composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta, (double) p->green,alpha)); break; } case BluePixelChannel: { composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta, (double) p->blue,alpha)); break; } case BlackPixelChannel: { composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta, (double) p->black,alpha)); break; } case AlphaPixelChannel: { composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da)); break; } default: break; } } }
MagickExport Image *ChannelFxImage(const Image *image,const char *expression, ExceptionInfo *exception) { #define ChannelFxImageTag "ChannelFx/Image" ChannelFx channel_op; ChannelType channel_mask; char token[MaxTextExtent]; const char *p; const Image *source_image; double pixel; Image *destination_image; MagickBooleanType status; PixelChannel source_channel, destination_channel; ssize_t channels; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); source_image=image; destination_image=CloneImage(source_image,0,0,MagickTrue,exception); if (destination_image == (Image *) NULL) return((Image *) NULL); if (expression == (const char *) NULL) return(destination_image); destination_channel=RedPixelChannel; channel_mask=UndefinedChannel; pixel=0.0; p=(char *) expression; GetMagickToken(p,&p,token); channel_op=ExtractChannelOp; for (channels=0; *token != '\0'; ) { ssize_t i; /* Interpret channel expression. */ switch (*token) { case ',': { GetMagickToken(p,&p,token); break; } case '|': { if (GetNextImageInList(source_image) != (Image *) NULL) source_image=GetNextImageInList(source_image); else source_image=GetFirstImageInList(source_image); GetMagickToken(p,&p,token); break; } case ';': { Image *canvas; SetPixelChannelMask(destination_image,channel_mask); if ((channel_op == ExtractChannelOp) && (channels == 1)) (void) SetImageColorspace(destination_image,GRAYColorspace,exception); status=SetImageStorageClass(destination_image,DirectClass,exception); if (status == MagickFalse) { destination_image=DestroyImageList(destination_image); return(destination_image); } canvas=CloneImage(source_image,0,0,MagickTrue,exception); if (canvas == (Image *) NULL) { destination_image=DestroyImageList(destination_image); return(destination_image); } AppendImageToList(&destination_image,canvas); destination_image=GetLastImageInList(destination_image); GetMagickToken(p,&p,token); channels=0; destination_channel=RedPixelChannel; channel_mask=UndefinedChannel; break; } default: break; } i=ParsePixelChannelOption(token); if (i < 0) { (void) ThrowMagickException(exception,GetMagickModule(),OptionError, "UnrecognizedChannelType","`%s'",token); destination_image=DestroyImageList(destination_image); return(destination_image); } source_channel=(PixelChannel) i; channel_op=ExtractChannelOp; GetMagickToken(p,&p,token); if (*token == '<') { channel_op=ExchangeChannelOp; GetMagickToken(p,&p,token); } if (*token == '=') { if (channel_op != ExchangeChannelOp) channel_op=AssignChannelOp; GetMagickToken(p,&p,token); } if (*token == '>') { if (channel_op != ExchangeChannelOp) channel_op=TransferChannelOp; GetMagickToken(p,&p,token); } switch (channel_op) { case AssignChannelOp: { pixel=StringToDoubleInterval(token,(double) QuantumRange+1.0); GetMagickToken(p,&p,token); break; } case ExchangeChannelOp: case TransferChannelOp: { i=ParsePixelChannelOption(token); if (i < 0) { (void) ThrowMagickException(exception,GetMagickModule(),OptionError, "UnrecognizedChannelType","`%s'",token); destination_image=DestroyImageList(destination_image); return(destination_image); } destination_channel=(PixelChannel) i; switch (destination_channel) { case RedPixelChannel: case GreenPixelChannel: case BluePixelChannel: case BlackPixelChannel: case IndexPixelChannel: break; case AlphaPixelChannel: { destination_image->alpha_trait=BlendPixelTrait; break; } case ReadMaskPixelChannel: { destination_image->read_mask=MagickTrue; break; } case WriteMaskPixelChannel: { destination_image->write_mask=MagickTrue; break; } case MetaPixelChannel: default: { (void) SetPixelMetaChannels(destination_image,(size_t) (i- GetPixelChannels(destination_image)+1),exception); break; } } channel_mask=(ChannelType) (channel_mask | ParseChannelOption(token)); if (((channels >= 1) || (destination_channel >= 1)) && (IsGrayColorspace(destination_image->colorspace) != MagickFalse)) (void) SetImageColorspace(destination_image,sRGBColorspace,exception); GetMagickToken(p,&p,token); break; } default: break; } status=ChannelImage(destination_image,destination_channel,channel_op, source_image,source_channel,ClampToQuantum(pixel),exception); if (status == MagickFalse) { destination_image=DestroyImageList(destination_image); break; } channels++; if (channel_op == ExchangeChannelOp) { status=ChannelImage(destination_image,source_channel,channel_op, source_image,destination_channel,ClampToQuantum(pixel),exception); if (status == MagickFalse) { destination_image=DestroyImageList(destination_image); break; } channels++; } switch (channel_op) { case ExtractChannelOp: { channel_mask=(ChannelType) (channel_mask | (1 << destination_channel)); destination_channel=(PixelChannel) (destination_channel+1); break; } default: break; } status=SetImageProgress(source_image,ChannelFxImageTag,p-expression, strlen(expression)); if (status == MagickFalse) break; } SetPixelChannelMask(destination_image,channel_mask); if ((channel_op == ExtractChannelOp) && (channels == 1)) (void) SetImageColorspace(destination_image,GRAYColorspace,exception); status=SetImageStorageClass(destination_image,DirectClass,exception); if (status == MagickFalse) { destination_image=GetLastImageInList(destination_image); return((Image *) NULL); } return(GetFirstImageInList(destination_image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d R L E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadRLEImage() reads a run-length encoded Utah Raster Toolkit % 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 ReadRLEImage method is: % % Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % % */ static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception) { #define SkipLinesOp 0x01 #define SetColorOp 0x02 #define SkipPixelsOp 0x03 #define ByteDataOp 0x05 #define RunDataOp 0x06 #define EOFOp 0x07 char magick[12]; Image *image; int opcode, operand, status; MagickStatusType flags; MagickSizeType number_pixels; MemoryInfo *pixel_info; Quantum index; register ssize_t x; register Quantum *q; register ssize_t i; register unsigned char *p; size_t bits_per_pixel, map_length, number_colormaps, number_planes, number_planes_filled, one, offset, pixel_info_length; ssize_t count, y; unsigned char background_color[256], *colormap, pixel, plane, *pixels; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); image=AcquireImage(image_info,exception); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) return(DestroyImageList(image)); /* Determine if this a RLE file. */ count=ReadBlob(image,2,(unsigned char *) magick); if ((count != 2) || (memcmp(magick,"\122\314",2) != 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); do { /* Read image header. */ image->page.x=ReadBlobLSBShort(image); image->page.y=ReadBlobLSBShort(image); image->columns=ReadBlobLSBShort(image); image->rows=ReadBlobLSBShort(image); flags=(MagickStatusType) ReadBlobByte(image); image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait; number_planes=(size_t) ReadBlobByte(image); bits_per_pixel=(size_t) ReadBlobByte(image); number_colormaps=(size_t) ReadBlobByte(image); map_length=(unsigned char) ReadBlobByte(image); if (map_length >= 64) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); one=1; map_length=one << map_length; if ((number_planes == 0) || (number_planes == 2) || ((flags & 0x04) && (number_colormaps > 254)) || (bits_per_pixel != 8) || (image->columns == 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); if (flags & 0x02) { /* No background color-- initialize to black. */ for (i=0; i < (ssize_t) number_planes; i++) background_color[i]=0; (void) ReadBlobByte(image); } else { /* Initialize background color. */ p=background_color; for (i=0; i < (ssize_t) number_planes; i++) *p++=(unsigned char) ReadBlobByte(image); } if ((number_planes & 0x01) == 0) (void) ReadBlobByte(image); if (EOFBlob(image) != MagickFalse) { ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); break; } colormap=(unsigned char *) NULL; if (number_colormaps != 0) { /* Read image colormaps. */ colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps, 3*map_length*sizeof(*colormap)); if (colormap == (unsigned char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); p=colormap; for (i=0; i < (ssize_t) number_colormaps; i++) for (x=0; x < (ssize_t) map_length; x++) *p++=(unsigned char) ScaleShortToQuantum(ReadBlobLSBShort(image)); } if ((flags & 0x08) != 0) { char *comment; size_t length; /* Read image comment. */ length=ReadBlobLSBShort(image); if (length != 0) { comment=(char *) AcquireQuantumMemory(length,sizeof(*comment)); if (comment == (char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); count=ReadBlob(image,length-1,(unsigned char *) comment); comment[length-1]='\0'; (void) SetImageProperty(image,"comment",comment,exception); comment=DestroyString(comment); if ((length & 0x01) == 0) (void) ReadBlobByte(image); } } if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) return(DestroyImageList(image)); /* Allocate RLE pixels. */ if (image->alpha_trait != UndefinedPixelTrait) number_planes++; number_pixels=(MagickSizeType) image->columns*image->rows; number_planes_filled=(number_planes % 2 == 0) ? number_planes : number_planes+1; if ((number_pixels*number_planes_filled) != (size_t) (number_pixels* number_planes_filled)) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); if (image->rows < (image->rows*number_planes_filled*sizeof(*pixels))) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); pixel_info=AcquireVirtualMemory(image->columns,image->rows* number_planes_filled*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); pixel_info_length=image->columns*image->rows*number_planes_filled; pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); if ((flags & 0x01) && !(flags & 0x02)) { ssize_t j; /* Set background color. */ p=pixels; for (i=0; i < (ssize_t) number_pixels; i++) { if (image->alpha_trait == UndefinedPixelTrait) for (j=0; j < (ssize_t) number_planes; j++) *p++=background_color[j]; else { for (j=0; j < (ssize_t) (number_planes-1); j++) *p++=background_color[j]; *p++=0; /* initialize matte channel */ } } } /* Read runlength-encoded image. */ plane=0; x=0; y=0; opcode=ReadBlobByte(image); do { switch (opcode & 0x3f) { case SkipLinesOp: { operand=ReadBlobByte(image); if (opcode & 0x40) operand=(int) ReadBlobLSBShort(image); x=0; y+=operand; break; } case SetColorOp: { operand=ReadBlobByte(image); plane=(unsigned char) operand; if (plane == 255) plane=(unsigned char) (number_planes-1); x=0; break; } case SkipPixelsOp: { operand=ReadBlobByte(image); if (opcode & 0x40) operand=(int) ReadBlobLSBShort(image); x+=operand; break; } case ByteDataOp: { operand=ReadBlobByte(image); if (opcode & 0x40) operand=(int) ReadBlobLSBShort(image); offset=((image->rows-y-1)*image->columns*number_planes)+x* number_planes+plane; operand++; if (offset+((size_t) operand*number_planes) > pixel_info_length) { if (number_colormaps != 0) colormap=(unsigned char *) RelinquishMagickMemory(colormap); pixel_info=RelinquishVirtualMemory(pixel_info); ThrowReaderException(CorruptImageError,"UnableToReadImageData"); } p=pixels+offset; for (i=0; i < (ssize_t) operand; i++) { pixel=(unsigned char) ReadBlobByte(image); if ((y < (ssize_t) image->rows) && ((x+i) < (ssize_t) image->columns)) *p=pixel; p+=number_planes; } if (operand & 0x01) (void) ReadBlobByte(image); x+=operand; break; } case RunDataOp: { operand=ReadBlobByte(image); if (opcode & 0x40) operand=(int) ReadBlobLSBShort(image); pixel=(unsigned char) ReadBlobByte(image); (void) ReadBlobByte(image); offset=((image->rows-y-1)*image->columns*number_planes)+x* number_planes+plane; operand++; if (offset+((size_t) operand*number_planes) > pixel_info_length) { if (number_colormaps != 0) colormap=(unsigned char *) RelinquishMagickMemory(colormap); pixel_info=RelinquishVirtualMemory(pixel_info); ThrowReaderException(CorruptImageError,"UnableToReadImageData"); } p=pixels+offset; for (i=0; i < (ssize_t) operand; i++) { if ((y < (ssize_t) image->rows) && ((x+i) < (ssize_t) image->columns)) *p=pixel; p+=number_planes; } x+=operand; break; } default: break; } opcode=ReadBlobByte(image); } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF)); if (number_colormaps != 0) { MagickStatusType mask; /* Apply colormap affineation to image. */ mask=(MagickStatusType) (map_length-1); p=pixels; x=(ssize_t) number_planes; if (number_colormaps == 1) for (i=0; i < (ssize_t) number_pixels; i++) { if (IsValidColormapIndex(image,*p & mask,&index,exception) == MagickFalse) break; *p=colormap[(ssize_t) index]; p++; } else if ((number_planes >= 3) && (number_colormaps >= 3)) for (i=0; i < (ssize_t) number_pixels; i++) for (x=0; x < (ssize_t) number_planes; x++) { if (IsValidColormapIndex(image,(size_t) (x*map_length+ (*p & mask)),&index,exception) == MagickFalse) break; *p=colormap[(ssize_t) index]; p++; } if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes)) { colormap=(unsigned char *) RelinquishMagickMemory(colormap); pixel_info=RelinquishVirtualMemory(pixel_info); ThrowReaderException(CorruptImageError,"UnableToReadImageData"); } } /* Initialize image structure. */ if (number_planes >= 3) { /* Convert raster image to DirectClass pixel packets. */ p=pixels; for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(image,ScaleCharToQuantum(*p++),q); SetPixelGreen(image,ScaleCharToQuantum(*p++),q); SetPixelBlue(image,ScaleCharToQuantum(*p++),q); if (image->alpha_trait != UndefinedPixelTrait) SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } } else { /* Create colormap. */ if (number_colormaps == 0) map_length=256; if (AcquireImageColormap(image,map_length,exception) == MagickFalse) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); p=colormap; if (number_colormaps == 1) for (i=0; i < (ssize_t) image->colors; i++) { /* Pseudocolor. */ image->colormap[i].red=(MagickRealType) ScaleCharToQuantum((unsigned char) i); image->colormap[i].green=(MagickRealType) ScaleCharToQuantum((unsigned char) i); image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum((unsigned char) i); } else if (number_colormaps > 1) for (i=0; i < (ssize_t) image->colors; i++) { image->colormap[i].red=(MagickRealType) ScaleCharToQuantum(*p); image->colormap[i].green=(MagickRealType) ScaleCharToQuantum(*(p+map_length)); image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum(*(p+map_length*2)); p++; } p=pixels; if (image->alpha_trait == UndefinedPixelTrait) { /* Convert raster image to PseudoClass pixel packets. */ for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelIndex(image,*p++,q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,image->rows); if (status == MagickFalse) break; } } (void) SyncImage(image,exception); } else { /* Image has a matte channel-- promote to DirectClass. */ for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { if (IsValidColormapIndex(image,(ssize_t) *p++,&index, exception) == MagickFalse) break; SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t) index].red),q); if (IsValidColormapIndex(image,(ssize_t) *p++,&index, exception) == MagickFalse) break; SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t) index].green),q); if (IsValidColormapIndex(image,(ssize_t) *p++,&index, exception) == MagickFalse) break; SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t) index].blue),q); SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); q+=GetPixelChannels(image); } if (x < (ssize_t) image->columns) break; if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,image->rows); if (status == MagickFalse) break; } } image->colormap=(PixelInfo *) RelinquishMagickMemory( image->colormap); image->storage_class=DirectClass; image->colors=0; } } if (number_colormaps != 0) colormap=(unsigned char *) RelinquishMagickMemory(colormap); pixel_info=RelinquishVirtualMemory(pixel_info); if (EOFBlob(image) != MagickFalse) { ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); break; } /* Proceed to next image. */ if (image_info->number_scenes != 0) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; (void) ReadBlobByte(image); count=ReadBlob(image,2,(unsigned char *) magick); if ((count != 0) && (memcmp(magick,"\122\314",2) == 0)) { /* Allocate next image structure. */ AcquireNextImage(image_info,image,exception); if (GetNextImageInList(image) == (Image *) NULL) { image=DestroyImageList(image); return((Image *) NULL); } image=SyncNextImageInList(image); status=SetImageProgress(image,LoadImagesTag,TellBlob(image), GetBlobSize(image)); if (status == MagickFalse) break; } } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0)); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % G e t I m a g e D e p t h % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetImageDepth() returns the depth of a particular image channel. % % The format of the GetImageDepth method is: % % size_t GetImageDepth(const Image *image,ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o exception: return any errors or warnings in this structure. % */ MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception) { CacheView *image_view; MagickBooleanType status; register ssize_t id; size_t *current_depth, depth, number_threads; ssize_t y; /* Compute image depth. */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); number_threads=(size_t) GetMagickResourceLimit(ThreadResource); current_depth=(size_t *) AcquireQuantumMemory(number_threads, sizeof(*current_depth)); if (current_depth == (size_t *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); status=MagickTrue; for (id=0; id < (ssize_t) number_threads; id++) current_depth[id]=1; if ((image->storage_class == PseudoClass) && (image->alpha_trait != BlendPixelTrait)) { register ssize_t i; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ if ((image->colors) > 256) \ num_threads(GetMagickResourceLimit(ThreadResource)) #endif for (i=0; i < (ssize_t) image->colors; i++) { const int id = GetOpenMPThreadId(); if (status == MagickFalse) continue; while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH) { MagickStatusType status; QuantumAny range; status=0; range=GetQuantumRange(current_depth[id]); if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) status|=ClampToQuantum(image->colormap[i].red) != ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum( image->colormap[i].red),range),range); if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) status|=ClampToQuantum(image->colormap[i].green) != ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum( image->colormap[i].green),range),range); if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) status|=ClampToQuantum(image->colormap[i].blue) != ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum( image->colormap[i].blue),range),range); if (status == 0) break; current_depth[id]++; } } depth=current_depth[0]; for (id=1; id < (ssize_t) number_threads; id++) if (depth < current_depth[id]) depth=current_depth[id]; current_depth=(size_t *) RelinquishMagickMemory(current_depth); return(depth); } image_view=AcquireVirtualCacheView(image,exception); #if !defined(MAGICKCORE_HDRI_SUPPORT) if (QuantumRange <= MaxMap) { register ssize_t i; size_t *depth_map; /* Scale pixels to desired (optimized with depth map). */ depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map)); if (depth_map == (size_t *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); for (i=0; i <= (ssize_t) MaxMap; i++) { unsigned int depth; for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++) { Quantum pixel; QuantumAny range; range=GetQuantumRange(depth); pixel=(Quantum) i; if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range)) break; } depth_map[i]=depth; } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { const int id = GetOpenMPThreadId(); register const Quantum *restrict p; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) continue; for (x=0; x < (ssize_t) image->columns; x++) { register ssize_t i; if (GetPixelReadMask(image,p) == 0) { p+=GetPixelChannels(image); continue; } for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { PixelChannel channel=GetPixelChannelChannel(image,i); PixelTrait traits=GetPixelChannelTraits(image,channel); if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) || (channel == ReadMaskPixelChannel) || (channel == MetaPixelChannel)) continue; if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id]) current_depth[id]=depth_map[ScaleQuantumToMap(p[i])]; } p+=GetPixelChannels(image); } if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH) status=MagickFalse; } image_view=DestroyCacheView(image_view); depth=current_depth[0]; for (id=1; id < (ssize_t) number_threads; id++) if (depth < current_depth[id]) depth=current_depth[id]; depth_map=(size_t *) RelinquishMagickMemory(depth_map); current_depth=(size_t *) RelinquishMagickMemory(current_depth); return(depth); } #endif /* Compute pixel depth. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { const int id = GetOpenMPThreadId(); register const Quantum *restrict p; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) continue; for (x=0; x < (ssize_t) image->columns; x++) { register ssize_t i; if (GetPixelReadMask(image,p) == 0) { p+=GetPixelChannels(image); continue; } for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { PixelChannel channel; PixelTrait traits; channel=GetPixelChannelChannel(image,i); traits=GetPixelChannelTraits(image,channel); if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) || (channel == ReadMaskPixelChannel)) continue; while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH) { QuantumAny range; range=GetQuantumRange(current_depth[id]); if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range)) break; current_depth[id]++; } } p+=GetPixelChannels(image); } if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH) status=MagickFalse; } image_view=DestroyCacheView(image_view); depth=current_depth[0]; for (id=1; id < (ssize_t) number_threads; id++) if (depth < current_depth[id]) depth=current_depth[id]; current_depth=(size_t *) RelinquishMagickMemory(current_depth); return(depth); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % F l o o d f i l l P a i n t I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % FloodfillPaintImage() changes the color value of any pixel that matches % target and is an immediate neighbor. If the method FillToBorderMethod is % specified, the color value is changed for any neighbor pixel that does not % match the bordercolor member of image. % % By default target must match a particular pixel color exactly. % However, in many cases two colors may differ by a small amount. The % fuzz member of image defines how much tolerance is acceptable to % consider two colors as the same. For example, set fuzz to 10 and the % color red at intensities of 100 and 102 respectively are now % interpreted as the same color for the purposes of the floodfill. % % The format of the FloodfillPaintImage method is: % % MagickBooleanType FloodfillPaintImage(Image *image, % const ChannelType channel,const DrawInfo *draw_info, % const MagickPixelPacket target,const ssize_t x_offset, % const ssize_t y_offset,const MagickBooleanType invert) % % A description of each parameter follows: % % o image: the image. % % o channel: the channel(s). % % o draw_info: the draw info. % % o target: the RGB value of the target color. % % o x_offset,y_offset: the starting location of the operation. % % o invert: paint any pixel that does not match the target color. % */ MagickExport MagickBooleanType FloodfillPaintImage(Image *image, const ChannelType channel,const DrawInfo *draw_info, const MagickPixelPacket *target,const ssize_t x_offset,const ssize_t y_offset, const MagickBooleanType invert) { #define MaxStacksize (1UL << 15) #define PushSegmentStack(up,left,right,delta) \ { \ if (s >= (segment_stack+MaxStacksize)) \ ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \ else \ { \ if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \ { \ s->x1=(double) (left); \ s->y1=(double) (up); \ s->x2=(double) (right); \ s->y2=(double) (delta); \ s++; \ } \ } \ } CacheView *floodplane_view, *image_view; ExceptionInfo *exception; Image *floodplane_image; MagickBooleanType skip; MagickPixelPacket fill, pixel; PixelPacket fill_color; register SegmentInfo *s; SegmentInfo *segment_stack; ssize_t offset, start, x, x1, x2, y; /* Check boundary conditions. */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(draw_info != (DrawInfo *) NULL); assert(draw_info->signature == MagickSignature); if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns)) return(MagickFalse); if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows)) return(MagickFalse); if (SetImageStorageClass(image,DirectClass) == MagickFalse) return(MagickFalse); if (IsGrayColorspace(image->colorspace) != MagickFalse) (void) TransformImageColorspace(image,sRGBColorspace); if ((image->matte == MagickFalse) && (draw_info->fill.opacity != OpaqueOpacity)) (void) SetImageAlphaChannel(image,OpaqueAlphaChannel); /* Set floodfill state. */ floodplane_image=CloneImage(image,0,0,MagickTrue,&image->exception); if (floodplane_image == (Image *) NULL) return(MagickFalse); (void) SetImageAlphaChannel(floodplane_image,OpaqueAlphaChannel); segment_stack=(SegmentInfo *) AcquireQuantumMemory(MaxStacksize, sizeof(*segment_stack)); if (segment_stack == (SegmentInfo *) NULL) { floodplane_image=DestroyImage(floodplane_image); ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); } /* Push initial segment on stack. */ exception=(&image->exception); x=x_offset; y=y_offset; start=0; s=segment_stack; PushSegmentStack(y,x,x,1); PushSegmentStack(y+1,x,x,-1); GetMagickPixelPacket(image,&fill); GetMagickPixelPacket(image,&pixel); image_view=AcquireVirtualCacheView(image,exception); floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception); while (s > segment_stack) { register const IndexPacket *restrict indexes; register const PixelPacket *restrict p; register ssize_t x; register PixelPacket *restrict q; /* Pop segment off stack. */ s--; x1=(ssize_t) s->x1; x2=(ssize_t) s->x2; offset=(ssize_t) s->y2; y=(ssize_t) s->y1+offset; /* Recolor neighboring pixels. */ p=GetCacheViewVirtualPixels(image_view,0,y,(size_t) (x1+1),1,exception); q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(size_t) (x1+1),1, exception); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetCacheViewVirtualIndexQueue(image_view); p+=x1; q+=x1; for (x=x1; x >= 0; x--) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (IsMagickColorSimilar(&pixel,target) == invert) break; q->opacity=(Quantum) TransparentOpacity; p--; q--; } if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse) break; skip=x >= x1 ? MagickTrue : MagickFalse; if (skip == MagickFalse) { start=x+1; if (start < x1) PushSegmentStack(y,start,x1-1,-offset); x=x1+1; } do { if (skip == MagickFalse) { if (x < (ssize_t) image->columns) { p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1, exception); q=GetCacheViewAuthenticPixels(floodplane_view,x,y, image->columns-x,1,exception); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetCacheViewVirtualIndexQueue(image_view); for ( ; x < (ssize_t) image->columns; x++) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (IsMagickColorSimilar(&pixel,target) == invert) break; q->opacity=(Quantum) TransparentOpacity; p++; q++; } if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse) break; } PushSegmentStack(y,start,x-1,offset); if (x > (x2+1)) PushSegmentStack(y,x2+1,x-1,-offset); } skip=MagickFalse; x++; if (x <= x2) { p=GetCacheViewVirtualPixels(image_view,x,y,(size_t) (x2-x+1),1, exception); q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(size_t) (x2-x+1),1, exception); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetCacheViewVirtualIndexQueue(image_view); for ( ; x <= x2; x++) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (IsMagickColorSimilar(&pixel,target) != invert) break; p++; q++; } } start=x; } while (x <= x2); } for (y=0; y < (ssize_t) image->rows; y++) { register const PixelPacket *restrict p; register IndexPacket *restrict indexes; register ssize_t x; register PixelPacket *restrict q; /* Tile fill color onto floodplane. */ p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1, exception); q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetCacheViewAuthenticIndexQueue(image_view); for (x=0; x < (ssize_t) image->columns; x++) { if (GetPixelOpacity(p) != OpaqueOpacity) { (void) GetFillColor(draw_info,x,y,&fill_color); SetMagickPixelPacket(image,&fill_color,(IndexPacket *) NULL,&fill); if (image->colorspace == CMYKColorspace) ConvertRGBToCMYK(&fill); if ((channel & RedChannel) != 0) SetPixelRed(q,ClampToQuantum(fill.red)); if ((channel & GreenChannel) != 0) SetPixelGreen(q,ClampToQuantum(fill.green)); if ((channel & BlueChannel) != 0) SetPixelBlue(q,ClampToQuantum(fill.blue)); if ((channel & OpacityChannel) != 0) SetPixelOpacity(q,ClampToQuantum(fill.opacity)); if (((channel & IndexChannel) != 0) && (image->colorspace == CMYKColorspace)) SetPixelIndex(indexes+x,ClampToQuantum(fill.index)); } p++; q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) break; } floodplane_view=DestroyCacheView(floodplane_view); image_view=DestroyCacheView(image_view); segment_stack=(SegmentInfo *) RelinquishMagickMemory(segment_stack); floodplane_image=DestroyImage(floodplane_image); return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % S e t I m a g e D e p t h % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SetImageDepth() sets the depth of the image. % % The format of the SetImageDepth method is: % % MagickBooleanType SetImageDepth(Image *image,const size_t depth, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o channel: the channel. % % o depth: the image depth. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType SetImageDepth(Image *image, const size_t depth,ExceptionInfo *exception) { CacheView *image_view; MagickBooleanType status; QuantumAny range; ssize_t y; assert(image != (Image *) NULL); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(image->signature == MagickSignature); if (depth >= MAGICKCORE_QUANTUM_DEPTH) { image->depth=depth; return(MagickTrue); } range=GetQuantumRange(depth); if (image->storage_class == PseudoClass) { register ssize_t i; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,1,1) #endif for (i=0; i < (ssize_t) image->colors; i++) { if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny( ClampToQuantum(image->colormap[i].red),range),range); if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny( ClampToQuantum(image->colormap[i].green),range),range); if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny( ClampToQuantum(image->colormap[i].blue),range),range); if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny( ClampToQuantum(image->colormap[i].alpha),range),range); } } status=MagickTrue; image_view=AcquireAuthenticCacheView(image,exception); #if !defined(MAGICKCORE_HDRI_SUPPORT) if (QuantumRange <= MaxMap) { Quantum *depth_map; register ssize_t i; /* Scale pixels to desired (optimized with depth map). */ depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map)); if (depth_map == (Quantum *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); for (i=0; i <= (ssize_t) MaxMap; i++) depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range), range); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register ssize_t x; register Quantum *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, exception); if (q == (Quantum *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { register ssize_t i; if (GetPixelReadMask(image,q) == 0) { q+=GetPixelChannels(image); continue; } for (i=0; i < (ssize_t) GetPixelChannels(image); i++) { PixelChannel channel; PixelTrait traits; channel=GetPixelChannelChannel(image,i); traits=GetPixelChannelTraits(image,channel); if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) || (channel == ReadMaskPixelChannel)) continue; q[i]=depth_map[ScaleQuantumToMap(q[i])]; } q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) { status=MagickFalse; continue; } } image_view=DestroyCacheView(image_view); depth_map=(Quantum *) RelinquishMagickMemory(depth_map); if (status != MagickFalse) image->depth=depth; return(status); }
static Image *ReadFITSImage(const ImageInfo *image_info, ExceptionInfo *exception) { typedef struct _FITSInfo { MagickBooleanType extend, simple; int bits_per_pixel, columns, rows, number_axes, number_planes; double min_data, max_data, zero, scale; EndianType endian; } FITSInfo; char *comment, keyword[9], property[MaxTextExtent], value[73]; double pixel, scale; FITSInfo fits_info; Image *image; int c; MagickBooleanType status; MagickSizeType number_pixels; register ssize_t i, x; register PixelPacket *q; ssize_t count, scene, y; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } /* Initialize image header. */ (void) ResetMagickMemory(&fits_info,0,sizeof(fits_info)); fits_info.extend=MagickFalse; fits_info.simple=MagickFalse; fits_info.bits_per_pixel=8; fits_info.columns=1; fits_info.rows=1; fits_info.rows=1; fits_info.number_planes=1; fits_info.min_data=0.0; fits_info.max_data=0.0; fits_info.zero=0.0; fits_info.scale=1.0; fits_info.endian=MSBEndian; /* Decode image header. */ for (comment=(char *) NULL; EOFBlob(image) == MagickFalse; ) { for ( ; EOFBlob(image) == MagickFalse; ) { register char *p; count=ReadBlob(image,8,(unsigned char *) keyword); if (count != 8) break; for (i=0; i < 8; i++) { if (isspace((int) ((unsigned char) keyword[i])) != 0) break; keyword[i]=tolower((int) ((unsigned char) keyword[i])); } keyword[i]='\0'; count=ReadBlob(image,72,(unsigned char *) value); if (count != 72) break; value[72]='\0'; p=value; if (*p == '=') { p+=2; while (isspace((int) ((unsigned char) *p)) != 0) p++; } if (LocaleCompare(keyword,"end") == 0) break; if (LocaleCompare(keyword,"extend") == 0) fits_info.extend=(*p == 'T') || (*p == 't') ? MagickTrue : MagickFalse; if (LocaleCompare(keyword,"simple") == 0) fits_info.simple=(*p == 'T') || (*p == 't') ? MagickTrue : MagickFalse; if (LocaleCompare(keyword,"bitpix") == 0) fits_info.bits_per_pixel=StringToLong(p); if (LocaleCompare(keyword,"naxis") == 0) fits_info.number_axes=StringToLong(p); if (LocaleCompare(keyword,"naxis1") == 0) fits_info.columns=StringToLong(p); if (LocaleCompare(keyword,"naxis2") == 0) fits_info.rows=StringToLong(p); if (LocaleCompare(keyword,"naxis3") == 0) fits_info.number_planes=StringToLong(p); if (LocaleCompare(keyword,"datamax") == 0) fits_info.max_data=InterpretLocaleValue(p,(char **) NULL); if (LocaleCompare(keyword,"datamin") == 0) fits_info.min_data=InterpretLocaleValue(p,(char **) NULL); if (LocaleCompare(keyword,"bzero") == 0) fits_info.zero=InterpretLocaleValue(p,(char **) NULL); if (LocaleCompare(keyword,"bscale") == 0) fits_info.scale=InterpretLocaleValue(p,(char **) NULL); if (LocaleCompare(keyword,"comment") == 0) { if (comment == (char *) NULL) comment=ConstantString(p); else (void) ConcatenateString(&comment,p); } if (LocaleCompare(keyword,"xendian") == 0) { if (LocaleNCompare(p,"big",3) == 0) fits_info.endian=MSBEndian; else fits_info.endian=LSBEndian; } (void) FormatLocaleString(property,MaxTextExtent,"fits:%s",keyword); (void) SetImageProperty(image,property,p); } c=0; while (((TellBlob(image) % FITSBlocksize) != 0) && (c != EOF)) c=ReadBlobByte(image); if (fits_info.extend == MagickFalse) break; number_pixels=(MagickSizeType) fits_info.columns*fits_info.rows; if ((fits_info.simple != MagickFalse) && (fits_info.number_axes >= 1) && (fits_info.number_axes <= 4) && (number_pixels != 0)) break; } /* Verify that required image information is defined. */ if (comment != (char *) NULL) { (void) SetImageProperty(image,"comment",comment); comment=DestroyString(comment); } if (EOFBlob(image) != MagickFalse) ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); number_pixels=(MagickSizeType) fits_info.columns*fits_info.rows; if ((fits_info.simple == MagickFalse) || (fits_info.number_axes < 1) || (fits_info.number_axes > 4) || (number_pixels == 0)) ThrowReaderException(CorruptImageError,"ImageTypeNotSupported"); for (scene=0; scene < (ssize_t) fits_info.number_planes; scene++) { image->columns=(size_t) fits_info.columns; image->rows=(size_t) fits_info.rows; image->depth=(size_t) (fits_info.bits_per_pixel < 0 ? -1 : 1)* fits_info.bits_per_pixel; image->endian=fits_info.endian; image->scene=(size_t) scene; if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; /* Initialize image structure. */ if ((fits_info.min_data != 0.0) || (fits_info.max_data != 0.0)) { if ((fits_info.bits_per_pixel != 0) && (fits_info.max_data == 0.0)) fits_info.max_data=GetFITSPixelRange((size_t) fits_info.bits_per_pixel); } else GetFITSPixelExtrema(image,fits_info.bits_per_pixel,&fits_info.min_data, &fits_info.max_data); /* Convert FITS pixels to pixel packets. */ scale=(double) QuantumRange/(fits_info.scale*(fits_info.max_data- fits_info.min_data)+fits_info.zero); for (y=(ssize_t) image->rows-1; y >= 0; y--) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { pixel=GetFITSPixel(image,fits_info.bits_per_pixel); SetPixelRed(q,ClampToQuantum(scale*(fits_info.scale*(pixel- fits_info.min_data)+fits_info.zero))); SetPixelGreen(q,GetPixelRed(q)); SetPixelBlue(q,GetPixelRed(q)); q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } if (EOFBlob(image) != MagickFalse) { ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); break; } /* Proceed to next image. */ if (image_info->number_scenes != 0) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; if (scene < (ssize_t) (fits_info.number_planes-1)) { /* Allocate next image structure. */ AcquireNextImage(image_info,image); if (GetNextImageInList(image) == (Image *) NULL) { image=DestroyImageList(image); return((Image *) NULL); } image=SyncNextImageInList(image); status=SetImageProgress(image,LoadImagesTag,TellBlob(image), GetBlobSize(image)); if (status == MagickFalse) break; } } (void) CloseBlob(image); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % S e t I m a g e A l p h a C h a n n e l % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha % channel. % % The format of the SetImageAlphaChannel method is: % % MagickBooleanType SetImageAlphaChannel(Image *image, % const AlphaChannelType alpha_type) % % A description of each parameter follows: % % o image: the image. % % o alpha_type: The alpha channel type: ActivateAlphaChannel, % CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel, % OpaqueAlphaChannel, ResetAlphaChannel, SetAlphaChannel, % ShapeAlphaChannel, and TransparentAlphaChannel. % */ MagickExport MagickBooleanType SetImageAlphaChannel(Image *image, const AlphaChannelType alpha_type) { MagickBooleanType status; assert(image != (Image *) NULL); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(image->signature == MagickSignature); status=MagickTrue; switch (alpha_type) { case ActivateAlphaChannel: { image->matte=MagickTrue; break; } case BackgroundAlphaChannel: { CacheView *image_view; ExceptionInfo *exception; IndexPacket index; MagickBooleanType status; MagickPixelPacket background; PixelPacket pixel; ssize_t y; /* Set transparent pixels to background color. */ if (image->matte == MagickFalse) break; if (SetImageStorageClass(image,DirectClass) == MagickFalse) break; GetMagickPixelPacket(image,&background); SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *) NULL,&background); if (image->colorspace == CMYKColorspace) ConvertRGBToCMYK(&background); index=0; SetPixelPacket(image,&background,&pixel,&index); status=MagickTrue; exception=(&image->exception); image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register IndexPacket *restrict indexes; register PixelPacket *restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { if (q->opacity == TransparentOpacity) { SetPixelRed(q,pixel.red); SetPixelGreen(q,pixel.green); SetPixelBlue(q,pixel.blue); } q++; } if (image->colorspace == CMYKColorspace) { indexes=GetCacheViewAuthenticIndexQueue(image_view); for (x=0; x < (ssize_t) image->columns; x++) SetPixelIndex(indexes+x,index); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; } image_view=DestroyCacheView(image_view); return(status); } case CopyAlphaChannel: case ShapeAlphaChannel: { /* Special usage case for SeparateImageChannel(): copy grayscale color to the alpha channel. */ status=SeparateImageChannel(image,GrayChannels); image->matte=MagickTrue; /* make sure transparency is now on! */ if (alpha_type == ShapeAlphaChannel) { MagickPixelPacket background; /* Reset all color channels to background color. */ GetMagickPixelPacket(image,&background); SetMagickPixelPacket(image,&(image->background_color),(IndexPacket *) NULL,&background); (void) LevelColorsImage(image,&background,&background,MagickTrue); } break; } case DeactivateAlphaChannel: { image->matte=MagickFalse; break; } case ExtractAlphaChannel: { status=SeparateImageChannel(image,TrueAlphaChannel); image->matte=MagickFalse; break; } case RemoveAlphaChannel: case FlattenAlphaChannel: { CacheView *image_view; ExceptionInfo *exception; IndexPacket index; MagickBooleanType status; MagickPixelPacket background; PixelPacket pixel; ssize_t y; /* Flatten image pixels over the background pixels. */ if (image->matte == MagickFalse) break; if (SetImageStorageClass(image,DirectClass) == MagickFalse) break; GetMagickPixelPacket(image,&background); SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *) NULL,&background); if (image->colorspace == CMYKColorspace) ConvertRGBToCMYK(&background); index=0; SetPixelPacket(image,&background,&pixel,&index); status=MagickTrue; exception=(&image->exception); image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register IndexPacket *restrict indexes; register PixelPacket *restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { double gamma, opacity; gamma=1.0-QuantumScale*QuantumScale*q->opacity*pixel.opacity; opacity=(double) QuantumRange*(1.0-gamma); gamma=PerceptibleReciprocal(gamma); q->red=ClampToQuantum(gamma*MagickOver_((MagickRealType) q->red, (MagickRealType) q->opacity,(MagickRealType) pixel.red, (MagickRealType) pixel.opacity)); q->green=ClampToQuantum(gamma*MagickOver_((MagickRealType) q->green, (MagickRealType) q->opacity,(MagickRealType) pixel.green, (MagickRealType) pixel.opacity)); q->blue=ClampToQuantum(gamma*MagickOver_((MagickRealType) q->blue, (MagickRealType) q->opacity,(MagickRealType) pixel.blue, (MagickRealType) pixel.opacity)); q->opacity=ClampToQuantum(opacity); q++; } if (image->colorspace == CMYKColorspace) { indexes=GetCacheViewAuthenticIndexQueue(image_view); for (x=0; x < (ssize_t) image->columns; x++) SetPixelIndex(indexes+x,index); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; } image_view=DestroyCacheView(image_view); return(status); } case ResetAlphaChannel: /* deprecated */ case OpaqueAlphaChannel: { status=SetImageOpacity(image,OpaqueOpacity); break; } case SetAlphaChannel: { if (image->matte == MagickFalse) status=SetImageOpacity(image,OpaqueOpacity); break; } case TransparentAlphaChannel: { status=SetImageOpacity(image,TransparentOpacity); break; } case UndefinedAlphaChannel: break; } if (status == MagickFalse) return(status); return(SyncImagePixelCache(image,&image->exception)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e C I P I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure WriteCIPImage() writes an image to a file in the Cisco IP phone % image format. % % The format of the WriteCIPImage method is: % % MagickBooleanType WriteCIPImage(const ImageInfo *image_info, % Image *image,ExceptionInfo *exception) % % A description of each parameter follows. % % o image_info: the image info. % % o image: The image. % % o exception: return any errors or warnings in this structure. % */ static MagickBooleanType WriteCIPImage(const ImageInfo *image_info,Image *image, ExceptionInfo *exception) { char buffer[MagickPathExtent]; const char *value; MagickBooleanType status; register const Quantum *p; register ssize_t i, x; ssize_t y; unsigned char byte; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); assert(image != (Image *) NULL); assert(image->signature == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) return(status); (void) WriteBlobString(image,"<CiscoIPPhoneImage>\n"); value=GetImageProperty(image,"label",exception); if (value != (const char *) NULL) (void) FormatLocaleString(buffer,MagickPathExtent,"<Title>%s</Title>\n",value); else { char basename[MagickPathExtent]; GetPathComponent(image->filename,BasePath,basename); (void) FormatLocaleString(buffer,MagickPathExtent,"<Title>%s</Title>\n", basename); } (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent, "<LocationX>%.20g</LocationX>\n",(double) image->page.x); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent, "<LocationY>%.20g</LocationY>\n",(double) image->page.y); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent,"<Width>%.20g</Width>\n", (double) (image->columns+(image->columns % 2))); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent,"<Height>%.20g</Height>\n", (double) image->rows); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent,"<Depth>2</Depth>\n"); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"<Data>"); (void) TransformImageColorspace(image,sRGBColorspace,exception); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; for (x=0; x < ((ssize_t) image->columns-3); x+=4) { byte=(unsigned char) ((((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+3))/QuantumRange) & 0x03) << 6) | (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+2))/QuantumRange) & 0x03) << 4) | (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+1))/QuantumRange) & 0x03) << 2) | (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+0))/QuantumRange) & 0x03) << 0)); (void) FormatLocaleString(buffer,MagickPathExtent,"%02x",byte); (void) WriteBlobString(image,buffer); p+=4; } if ((image->columns % 4) != 0) { i=(ssize_t) image->columns % 4; byte=(unsigned char) ((((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+MagickMin(i,3)))/QuantumRange) & 0x03) << 6) | (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+MagickMin(i,2)))/QuantumRange) & 0x03) << 4) | (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+MagickMin(i,1)))/QuantumRange) & 0x03) << 2) | (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+MagickMin(i,0)))/QuantumRange) & 0x03) << 0)); (void) FormatLocaleString(buffer,MagickPathExtent,"%02x",~byte); (void) WriteBlobString(image,buffer); } status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } (void) WriteBlobString(image,"</Data>\n"); (void) WriteBlobString(image,"</CiscoIPPhoneImage>\n"); (void) CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d G R A D I E N T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadGRADIENTImage creates a gradient image and initializes it to % the color range as specified by the filename. It allocates the memory % necessary for the new Image structure and returns a pointer to the new % image. % % The format of the ReadGRADIENTImage method is: % % Image *ReadGRADIENTImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadGRADIENTImage(const ImageInfo *image_info, ExceptionInfo *exception) { char colorname[MaxTextExtent]; MagickBooleanType status; MagickPixelPacket start_pixel, stop_pixel; PixelPacket start_color, stop_color; Image *image; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); if ((image->columns == 0) || (image->rows == 0)) ThrowReaderException(OptionError,"MustSpecifyImageSize"); (void) SetImageOpacity(image,(Quantum) TransparentOpacity); (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent); (void) CopyMagickString(colorname,image_info->filename,MaxTextExtent); (void) sscanf(image_info->filename,"%[^-]",colorname); if (QueryColorDatabase(colorname,&start_color,exception) == MagickFalse) { image=DestroyImage(image); return((Image *) NULL); } (void) QueryMagickColor(colorname,&start_pixel,exception); (void) CopyMagickString(colorname,"white",MaxTextExtent); if (PixelIntensityToQuantum(image,&start_color) > (Quantum) (QuantumRange/2)) (void) CopyMagickString(colorname,"black",MaxTextExtent); (void) sscanf(image_info->filename,"%*[^-]-%s",colorname); if (QueryColorDatabase(colorname,&stop_color,exception) == MagickFalse) { image=DestroyImage(image); return((Image *) NULL); } (void) QueryMagickColor(colorname,&stop_pixel,exception); if (IssRGBColorspace(start_pixel.colorspace) != MagickFalse) { start_color.red=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* start_color.red)); start_color.green=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* start_color.green)); start_color.blue=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* start_color.blue)); } if (IssRGBColorspace(stop_pixel.colorspace) != MagickFalse) { stop_color.red=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* stop_color.red)); stop_color.green=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* stop_color.green)); stop_color.blue=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* stop_color.blue)); } status=GradientImage(image,LocaleCompare(image_info->magick,"GRADIENT") == 0 ? LinearGradient : RadialGradient,PadSpread,&start_color,&stop_color); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } (void) SetImageColorspace(image,start_pixel.colorspace); if ((start_pixel.matte == MagickFalse) && (stop_pixel.matte == MagickFalse)) (void) SetImageAlphaChannel(image,DeactivateAlphaChannel); if (IssRGBColorspace(start_pixel.colorspace) != MagickFalse) { (void) SetImageColorspace(image,RGBColorspace); (void) TransformImageColorspace(image,sRGBColorspace); } return(GetFirstImageInList(image)); }
MagickExport Image *OilPaintImage(const Image *image,const double radius, const double sigma,ExceptionInfo *exception) { #define NumberPaintBins 256 #define OilPaintImageTag "OilPaint/Image" CacheView *image_view, *paint_view; Image *linear_image, *paint_image; MagickBooleanType status; MagickOffsetType progress; size_t **histograms, width; ssize_t center, y; /* Initialize painted image attributes. */ assert(image != (const Image *) NULL); assert(image->signature == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); width=GetOptimalKernelWidth2D(radius,sigma); linear_image=CloneImage(image,0,0,MagickTrue,exception); paint_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception); if ((linear_image == (Image *) NULL) || (paint_image == (Image *) NULL)) { if (linear_image != (Image *) NULL) linear_image=DestroyImage(linear_image); if (paint_image != (Image *) NULL) linear_image=DestroyImage(paint_image); return((Image *) NULL); } if (SetImageStorageClass(paint_image,DirectClass,exception) == MagickFalse) { linear_image=DestroyImage(linear_image); paint_image=DestroyImage(paint_image); return((Image *) NULL); } histograms=AcquireHistogramThreadSet(NumberPaintBins); if (histograms == (size_t **) NULL) { linear_image=DestroyImage(linear_image); paint_image=DestroyImage(paint_image); ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); } /* Oil paint image. */ status=MagickTrue; progress=0; center=(ssize_t) GetPixelChannels(linear_image)*(linear_image->columns+width)* (width/2L)+GetPixelChannels(linear_image)*(width/2L); image_view=AcquireVirtualCacheView(linear_image,exception); paint_view=AcquireAuthenticCacheView(paint_image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(progress,status) \ magick_threads(linear_image,paint_image,linear_image->rows,1) #endif for (y=0; y < (ssize_t) linear_image->rows; y++) { register const Quantum *restrict p; register Quantum *restrict q; register size_t *histogram; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) (width/2L),linear_image->columns+width,width,exception); q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1, exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) { status=MagickFalse; continue; } histogram=histograms[GetOpenMPThreadId()]; for (x=0; x < (ssize_t) linear_image->columns; x++) { register ssize_t i, u; size_t count; ssize_t j, k, n, v; /* Assign most frequent color. */ k=0; j=0; count=0; (void) ResetMagickMemory(histogram,0,NumberPaintBins* sizeof(*histogram)); for (v=0; v < (ssize_t) width; v++) { for (u=0; u < (ssize_t) width; u++) { n=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity( linear_image,p+GetPixelChannels(linear_image)*(u+k)))); histogram[n]++; if (histogram[n] > count) { j=k+u; count=histogram[n]; } } k+=(ssize_t) (linear_image->columns+width); } for (i=0; i < (ssize_t) GetPixelChannels(linear_image); i++) { PixelChannel channel=GetPixelChannelChannel(linear_image,i); PixelTrait traits=GetPixelChannelTraits(linear_image,channel); PixelTrait paint_traits=GetPixelChannelTraits(paint_image,channel); if ((traits == UndefinedPixelTrait) || (paint_traits == UndefinedPixelTrait)) continue; if (((paint_traits & CopyPixelTrait) != 0) || (GetPixelReadMask(linear_image,p) == 0)) { SetPixelChannel(paint_image,channel,p[center+i],q); continue; } SetPixelChannel(paint_image,channel,p[j*GetPixelChannels(linear_image)+ i],q); } p+=GetPixelChannels(linear_image); q+=GetPixelChannels(paint_image); } if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse) status=MagickFalse; if (linear_image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_OilPaintImage) #endif proceed=SetImageProgress(linear_image,OilPaintImageTag,progress++, linear_image->rows); if (proceed == MagickFalse) status=MagickFalse; } } paint_view=DestroyCacheView(paint_view); image_view=DestroyCacheView(image_view); histograms=DestroyHistogramThreadSet(histograms); linear_image=DestroyImage(linear_image); if (status == MagickFalse) paint_image=DestroyImage(paint_image); return(paint_image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % C o n v e r t H S B T o R G B % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red, % green, blue) triple. % % The format of the ConvertHSBToRGBImage method is: % % void ConvertHSBToRGB(const double hue,const double saturation, % const double brightness,Quantum *red,Quantum *green,Quantum *blue) % % A description of each parameter follows: % % o hue, saturation, brightness: A double value representing a % component of the HSB color space. % % o red, green, blue: A pointer to a pixel component of type Quantum. % */ MagickExport void ConvertHSBToRGB(const double hue,const double saturation, const double brightness,Quantum *red,Quantum *green,Quantum *blue) { MagickRealType f, h, p, q, t; /* Convert HSB to RGB colorspace. */ assert(red != (Quantum *) NULL); assert(green != (Quantum *) NULL); assert(blue != (Quantum *) NULL); if (saturation == 0.0) { *red=ClampToQuantum((MagickRealType) QuantumRange*brightness); *green=(*red); *blue=(*red); return; } h=6.0*(hue-floor(hue)); f=h-floor((double) h); p=brightness*(1.0-saturation); q=brightness*(1.0-saturation*f); t=brightness*(1.0-(saturation*(1.0-f))); switch ((int) h) { case 0: default: { *red=ClampToQuantum((MagickRealType) QuantumRange*brightness); *green=ClampToQuantum((MagickRealType) QuantumRange*t); *blue=ClampToQuantum((MagickRealType) QuantumRange*p); break; } case 1: { *red=ClampToQuantum((MagickRealType) QuantumRange*q); *green=ClampToQuantum((MagickRealType) QuantumRange*brightness); *blue=ClampToQuantum((MagickRealType) QuantumRange*p); break; } case 2: { *red=ClampToQuantum((MagickRealType) QuantumRange*p); *green=ClampToQuantum((MagickRealType) QuantumRange*brightness); *blue=ClampToQuantum((MagickRealType) QuantumRange*t); break; } case 3: { *red=ClampToQuantum((MagickRealType) QuantumRange*p); *green=ClampToQuantum((MagickRealType) QuantumRange*q); *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness); break; } case 4: { *red=ClampToQuantum((MagickRealType) QuantumRange*t); *green=ClampToQuantum((MagickRealType) QuantumRange*p); *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness); break; } case 5: { *red=ClampToQuantum((MagickRealType) QuantumRange*brightness); *green=ClampToQuantum((MagickRealType) QuantumRange*p); *blue=ClampToQuantum((MagickRealType) QuantumRange*q); break; } } }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R a i s e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RaiseImage() creates a simulated three-dimensional button-like effect % by lightening and darkening the edges of the image. Members width and % height of raise_info define the width of the vertical and horizontal % edge of the effect. % % The format of the RaiseImage method is: % % MagickBooleanType RaiseImage(const Image *image, % const RectangleInfo *raise_info,const MagickBooleanType raise) % % A description of each parameter follows: % % o image: the image. % % o raise_info: Define the width and height of the raise area. % % o raise: A value other than zero creates a 3-D raise effect, % otherwise it has a lowered effect. % */ MagickExport MagickBooleanType RaiseImage(Image *image, const RectangleInfo *raise_info,const MagickBooleanType raise) { #define AccentuateFactor ScaleCharToQuantum(135) #define HighlightFactor ScaleCharToQuantum(190) #define ShadowFactor ScaleCharToQuantum(190) #define RaiseImageTag "Raise/Image" #define TroughFactor ScaleCharToQuantum(135) CacheView *image_view; ExceptionInfo *exception; MagickBooleanType status; MagickOffsetType progress; Quantum foreground, background; ssize_t y; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(raise_info != (RectangleInfo *) NULL); if ((image->columns <= (raise_info->width << 1)) || (image->rows <= (raise_info->height << 1))) ThrowBinaryException(OptionError,"ImageSizeMustExceedBevelWidth", image->filename); foreground=(Quantum) QuantumRange; background=(Quantum) 0; if (raise == MagickFalse) { foreground=(Quantum) 0; background=(Quantum) QuantumRange; } if (SetImageStorageClass(image,DirectClass) == MagickFalse) return(MagickFalse); /* Raise image. */ status=MagickTrue; progress=0; exception=(&image->exception); image_view=AcquireCacheView(image); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1) #endif for (y=0; y < (ssize_t) raise_info->height; y++) { register ssize_t x; register PixelPacket *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } for (x=0; x < y; x++) { q->red=ClampToQuantum(QuantumScale*((MagickRealType) q->red* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q->green=ClampToQuantum(QuantumScale*((MagickRealType) q->green* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q->blue=ClampToQuantum(QuantumScale*((MagickRealType) q->blue* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q++; } for ( ; x < (ssize_t) (image->columns-y); x++) { q->red=ClampToQuantum(QuantumScale*((MagickRealType) q->red* AccentuateFactor+(MagickRealType) foreground*(QuantumRange- AccentuateFactor))); q->green=ClampToQuantum(QuantumScale*((MagickRealType) q->green* AccentuateFactor+(MagickRealType) foreground*(QuantumRange- AccentuateFactor))); q->blue=ClampToQuantum(QuantumScale*((MagickRealType) q->blue* AccentuateFactor+(MagickRealType) foreground*(QuantumRange- AccentuateFactor))); q++; } for ( ; x < (ssize_t) image->columns; x++) { q->red=ClampToQuantum(QuantumScale*((MagickRealType) q->red*ShadowFactor+ (MagickRealType) background*(QuantumRange-ShadowFactor))); q->green=ClampToQuantum(QuantumScale*((MagickRealType) q->green* ShadowFactor+(MagickRealType) background*(QuantumRange-ShadowFactor))); q->blue=ClampToQuantum(QuantumScale*((MagickRealType) q->blue* ShadowFactor+(MagickRealType) background*(QuantumRange-ShadowFactor))); q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1) #endif for (y=(ssize_t) raise_info->height; y < (ssize_t) (image->rows-raise_info->height); y++) { register ssize_t x; register PixelPacket *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) raise_info->width; x++) { q->red=ClampToQuantum(QuantumScale*((MagickRealType) q->red* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q->green=ClampToQuantum(QuantumScale*((MagickRealType) q->green* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q->blue=ClampToQuantum(QuantumScale*((MagickRealType) q->blue* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q++; } for ( ; x < (ssize_t) (image->columns-raise_info->width); x++) q++; for ( ; x < (ssize_t) image->columns; x++) { q->red=ClampToQuantum(QuantumScale*((MagickRealType) q->red*ShadowFactor+ (MagickRealType) background*(QuantumRange-ShadowFactor))); q->green=ClampToQuantum(QuantumScale*((MagickRealType) q->green* ShadowFactor+(MagickRealType) background*(QuantumRange-ShadowFactor))); q->blue=ClampToQuantum(QuantumScale*((MagickRealType) q->blue* ShadowFactor+(MagickRealType) background*(QuantumRange-ShadowFactor))); q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1) #endif for (y=(ssize_t) (image->rows-raise_info->height); y < (ssize_t) image->rows; y++) { register ssize_t x; register PixelPacket *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) (image->rows-y); x++) { q->red=ClampToQuantum(QuantumScale*((MagickRealType) q->red* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q->green=ClampToQuantum(QuantumScale*((MagickRealType) q->green* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q->blue=ClampToQuantum(QuantumScale*((MagickRealType) q->blue* HighlightFactor+(MagickRealType) foreground*(QuantumRange- HighlightFactor))); q++; } for ( ; x < (ssize_t) (image->columns-(image->rows-y)); x++) { q->red=ClampToQuantum(QuantumScale*((MagickRealType) q->red*TroughFactor+ (MagickRealType) background*(QuantumRange-TroughFactor))); q->green=ClampToQuantum(QuantumScale*((MagickRealType) q->green* TroughFactor+(MagickRealType) background*(QuantumRange-TroughFactor))); q->blue=ClampToQuantum(QuantumScale*((MagickRealType) q->blue* TroughFactor+(MagickRealType) background*(QuantumRange-TroughFactor))); q++; } for ( ; x < (ssize_t) image->columns; x++) { q->red=ClampToQuantum(QuantumScale*((MagickRealType) q->red*ShadowFactor+ (MagickRealType) background*(QuantumRange-ShadowFactor))); q->green=ClampToQuantum(QuantumScale*((MagickRealType) q->green* ShadowFactor+(MagickRealType) background*(QuantumRange-ShadowFactor))); q->blue=ClampToQuantum(QuantumScale*((MagickRealType) q->blue* ShadowFactor+(MagickRealType) background*(QuantumRange-ShadowFactor))); q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_RaiseImage) #endif proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } image_view=DestroyCacheView(image_view); return(status); }