/MagickCore/fx.c
C | 6107 lines | 4762 code | 359 blank | 986 comment | 1327 complexity | b20d1e013a3c94837285ae4f9eddfac3 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
Large files files are truncated, but you can click here to view the full file
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- % FFFFF X X %
- % F X X %
- % FFF X %
- % F X X %
- % F X X %
- % %
- % %
- % MagickCore Image Special Effects Methods %
- % %
- % Software Design %
- % Cristy %
- % October 1996 %
- % %
- % %
- % %
- % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
- % dedicated to making software imaging solutions freely available. %
- % %
- % You may not use this file except in compliance with the License. You may %
- % obtain a copy of the License at %
- % %
- % https://imagemagick.org/script/license.php %
- % %
- % Unless required by applicable law or agreed to in writing, software %
- % distributed under the License is distributed on an "AS IS" BASIS, %
- % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
- % See the License for the specific language governing permissions and %
- % limitations under the License. %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- %
- %
- */
- /*
- Include declarations.
- */
- #include "MagickCore/studio.h"
- #include "MagickCore/accelerate-private.h"
- #include "MagickCore/annotate.h"
- #include "MagickCore/artifact.h"
- #include "MagickCore/attribute.h"
- #include "MagickCore/cache.h"
- #include "MagickCore/cache-view.h"
- #include "MagickCore/channel.h"
- #include "MagickCore/color.h"
- #include "MagickCore/color-private.h"
- #include "MagickCore/colorspace-private.h"
- #include "MagickCore/composite.h"
- #include "MagickCore/decorate.h"
- #include "MagickCore/distort.h"
- #include "MagickCore/draw.h"
- #include "MagickCore/effect.h"
- #include "MagickCore/enhance.h"
- #include "MagickCore/exception.h"
- #include "MagickCore/exception-private.h"
- #include "MagickCore/fx.h"
- #include "MagickCore/fx-private.h"
- #include "MagickCore/gem.h"
- #include "MagickCore/gem-private.h"
- #include "MagickCore/geometry.h"
- #include "MagickCore/layer.h"
- #include "MagickCore/list.h"
- #include "MagickCore/log.h"
- #include "MagickCore/image.h"
- #include "MagickCore/image-private.h"
- #include "MagickCore/magick.h"
- #include "MagickCore/memory_.h"
- #include "MagickCore/memory-private.h"
- #include "MagickCore/monitor.h"
- #include "MagickCore/monitor-private.h"
- #include "MagickCore/option.h"
- #include "MagickCore/pixel.h"
- #include "MagickCore/pixel-accessor.h"
- #include "MagickCore/property.h"
- #include "MagickCore/quantum.h"
- #include "MagickCore/quantum-private.h"
- #include "MagickCore/random_.h"
- #include "MagickCore/random-private.h"
- #include "MagickCore/resample.h"
- #include "MagickCore/resample-private.h"
- #include "MagickCore/resize.h"
- #include "MagickCore/resource_.h"
- #include "MagickCore/splay-tree.h"
- #include "MagickCore/statistic.h"
- #include "MagickCore/string_.h"
- #include "MagickCore/string-private.h"
- #include "MagickCore/thread-private.h"
- #include "MagickCore/threshold.h"
- #include "MagickCore/transform.h"
- #include "MagickCore/transform-private.h"
- #include "MagickCore/utility.h"
- /*
- Define declarations.
- */
- #define LeftShiftOperator 0xf5U
- #define RightShiftOperator 0xf6U
- #define LessThanEqualOperator 0xf7U
- #define GreaterThanEqualOperator 0xf8U
- #define EqualOperator 0xf9U
- #define NotEqualOperator 0xfaU
- #define LogicalAndOperator 0xfbU
- #define LogicalOrOperator 0xfcU
- #define ExponentialNotation 0xfdU
- struct _FxInfo
- {
- const Image
- *images;
- char
- *expression;
- FILE
- *file;
- SplayTreeInfo
- *colors,
- *symbols;
- CacheView
- **view;
- RandomInfo
- *random_info;
- ExceptionInfo
- *exception;
- };
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- + A c q u i r e F x I n f o %
- % %
- % %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % AcquireFxInfo() allocates the FxInfo structure.
- %
- % The format of the AcquireFxInfo method is:
- %
- % FxInfo *AcquireFxInfo(Image *images,const char *expression,
- % ExceptionInfo *exception)
- %
- % A description of each parameter follows:
- %
- % o images: the image sequence.
- %
- % o expression: the expression.
- %
- % o exception: return any errors or warnings in this structure.
- %
- */
- MagickPrivate FxInfo *AcquireFxInfo(const Image *images,const char *expression,
- ExceptionInfo *exception)
- {
- char
- fx_op[2];
- const Image
- *next;
- FxInfo
- *fx_info;
- register ssize_t
- i;
- fx_info=(FxInfo *) AcquireCriticalMemory(sizeof(*fx_info));
- (void) memset(fx_info,0,sizeof(*fx_info));
- fx_info->exception=AcquireExceptionInfo();
- fx_info->images=images;
- fx_info->colors=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
- RelinquishMagickMemory);
- fx_info->symbols=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
- RelinquishMagickMemory);
- fx_info->view=(CacheView **) AcquireQuantumMemory(GetImageListLength(
- fx_info->images),sizeof(*fx_info->view));
- if (fx_info->view == (CacheView **) NULL)
- ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
- i=0;
- next=GetFirstImageInList(fx_info->images);
- for ( ; next != (Image *) NULL; next=next->next)
- {
- fx_info->view[i]=AcquireVirtualCacheView(next,exception);
- i++;
- }
- fx_info->random_info=AcquireRandomInfo();
- fx_info->expression=ConstantString(expression);
- fx_info->file=stderr;
- (void) SubstituteString(&fx_info->expression," ",""); /* compact string */
- /*
- Force right-to-left associativity for unary negation.
- */
- (void) SubstituteString(&fx_info->expression,"-","-1.0*");
- (void) SubstituteString(&fx_info->expression,"^-1.0*","^-");
- (void) SubstituteString(&fx_info->expression,"E-1.0*","E-");
- (void) SubstituteString(&fx_info->expression,"e-1.0*","e-");
- /*
- Convert compound to simple operators.
- */
- fx_op[1]='\0';
- *fx_op=(char) LeftShiftOperator;
- (void) SubstituteString(&fx_info->expression,"<<",fx_op);
- *fx_op=(char) RightShiftOperator;
- (void) SubstituteString(&fx_info->expression,">>",fx_op);
- *fx_op=(char) LessThanEqualOperator;
- (void) SubstituteString(&fx_info->expression,"<=",fx_op);
- *fx_op=(char) GreaterThanEqualOperator;
- (void) SubstituteString(&fx_info->expression,">=",fx_op);
- *fx_op=(char) EqualOperator;
- (void) SubstituteString(&fx_info->expression,"==",fx_op);
- *fx_op=(char) NotEqualOperator;
- (void) SubstituteString(&fx_info->expression,"!=",fx_op);
- *fx_op=(char) LogicalAndOperator;
- (void) SubstituteString(&fx_info->expression,"&&",fx_op);
- *fx_op=(char) LogicalOrOperator;
- (void) SubstituteString(&fx_info->expression,"||",fx_op);
- *fx_op=(char) ExponentialNotation;
- (void) SubstituteString(&fx_info->expression,"**",fx_op);
- return(fx_info);
- }
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- % A d d N o i s e I m a g e %
- % %
- % %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % AddNoiseImage() adds random noise to the image.
- %
- % The format of the AddNoiseImage method is:
- %
- % Image *AddNoiseImage(const Image *image,const NoiseType noise_type,
- % const double attenuate,ExceptionInfo *exception)
- %
- % A description of each parameter follows:
- %
- % o image: the image.
- %
- % o channel: the channel type.
- %
- % o noise_type: The type of noise: Uniform, Gaussian, Multiplicative,
- % Impulse, Laplacian, or Poisson.
- %
- % o attenuate: attenuate the random distribution.
- %
- % o exception: return any errors or warnings in this structure.
- %
- */
- MagickExport Image *AddNoiseImage(const Image *image,const NoiseType noise_type,
- const double attenuate,ExceptionInfo *exception)
- {
- #define AddNoiseImageTag "AddNoise/Image"
- CacheView
- *image_view,
- *noise_view;
- Image
- *noise_image;
- MagickBooleanType
- status;
- MagickOffsetType
- progress;
- RandomInfo
- **magick_restrict random_info;
- ssize_t
- y;
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- unsigned long
- key;
- #endif
- /*
- Initialize noise 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);
- #if defined(MAGICKCORE_OPENCL_SUPPORT)
- noise_image=AccelerateAddNoiseImage(image,noise_type,attenuate,exception);
- if (noise_image != (Image *) NULL)
- return(noise_image);
- #endif
- noise_image=CloneImage(image,0,0,MagickTrue,exception);
- if (noise_image == (Image *) NULL)
- return((Image *) NULL);
- if (SetImageStorageClass(noise_image,DirectClass,exception) == MagickFalse)
- {
- noise_image=DestroyImage(noise_image);
- return((Image *) NULL);
- }
- /*
- Add noise in each row.
- */
- status=MagickTrue;
- progress=0;
- random_info=AcquireRandomInfoThreadSet();
- image_view=AcquireVirtualCacheView(image,exception);
- noise_view=AcquireAuthenticCacheView(noise_image,exception);
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- key=GetRandomSecretKey(random_info[0]);
- #pragma omp parallel for schedule(static) shared(progress,status) \
- magick_number_threads(image,noise_image,image->rows,key == ~0UL)
- #endif
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- const int
- id = GetOpenMPThreadId();
- MagickBooleanType
- sync;
- register const Quantum
- *magick_restrict p;
- register ssize_t
- x;
- register Quantum
- *magick_restrict q;
- if (status == MagickFalse)
- continue;
- p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
- q=QueueCacheViewAuthenticPixels(noise_view,0,y,noise_image->columns,1,
- exception);
- if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
- {
- status=MagickFalse;
- continue;
- }
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- register ssize_t
- i;
- for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
- {
- PixelChannel channel = GetPixelChannelChannel(image,i);
- PixelTrait traits = GetPixelChannelTraits(image,channel);
- PixelTrait noise_traits=GetPixelChannelTraits(noise_image,channel);
- if ((traits == UndefinedPixelTrait) ||
- (noise_traits == UndefinedPixelTrait))
- continue;
- if ((noise_traits & CopyPixelTrait) != 0)
- {
- SetPixelChannel(noise_image,channel,p[i],q);
- continue;
- }
- SetPixelChannel(noise_image,channel,ClampToQuantum(
- GenerateDifferentialNoise(random_info[id],p[i],noise_type,attenuate)),
- q);
- }
- p+=GetPixelChannels(image);
- q+=GetPixelChannels(noise_image);
- }
- sync=SyncCacheViewAuthenticPixels(noise_view,exception);
- if (sync == MagickFalse)
- status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
- {
- MagickBooleanType
- proceed;
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp atomic
- #endif
- progress++;
- proceed=SetImageProgress(image,AddNoiseImageTag,progress,image->rows);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- noise_view=DestroyCacheView(noise_view);
- image_view=DestroyCacheView(image_view);
- random_info=DestroyRandomInfoThreadSet(random_info);
- if (status == MagickFalse)
- noise_image=DestroyImage(noise_image);
- return(noise_image);
- }
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- % B l u e S h i f t I m a g e %
- % %
- % %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % BlueShiftImage() mutes the colors of the image to simulate a scene at
- % nighttime in the moonlight.
- %
- % The format of the BlueShiftImage method is:
- %
- % Image *BlueShiftImage(const Image *image,const double factor,
- % ExceptionInfo *exception)
- %
- % A description of each parameter follows:
- %
- % o image: the image.
- %
- % o factor: the shift factor.
- %
- % o exception: return any errors or warnings in this structure.
- %
- */
- MagickExport Image *BlueShiftImage(const Image *image,const double factor,
- ExceptionInfo *exception)
- {
- #define BlueShiftImageTag "BlueShift/Image"
- CacheView
- *image_view,
- *shift_view;
- Image
- *shift_image;
- MagickBooleanType
- status;
- MagickOffsetType
- progress;
- ssize_t
- y;
- /*
- Allocate blue shift image.
- */
- 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);
- shift_image=CloneImage(image,0,0,MagickTrue,exception);
- if (shift_image == (Image *) NULL)
- return((Image *) NULL);
- if (SetImageStorageClass(shift_image,DirectClass,exception) == MagickFalse)
- {
- shift_image=DestroyImage(shift_image);
- return((Image *) NULL);
- }
- /*
- Blue-shift DirectClass image.
- */
- status=MagickTrue;
- progress=0;
- image_view=AcquireVirtualCacheView(image,exception);
- shift_view=AcquireAuthenticCacheView(shift_image,exception);
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static) shared(progress,status) \
- magick_number_threads(image,shift_image,image->rows,1)
- #endif
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- MagickBooleanType
- sync;
- PixelInfo
- pixel;
- Quantum
- quantum;
- register const Quantum
- *magick_restrict p;
- register ssize_t
- x;
- register Quantum
- *magick_restrict q;
- if (status == MagickFalse)
- continue;
- p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
- q=QueueCacheViewAuthenticPixels(shift_view,0,y,shift_image->columns,1,
- exception);
- if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
- {
- status=MagickFalse;
- continue;
- }
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- quantum=GetPixelRed(image,p);
- if (GetPixelGreen(image,p) < quantum)
- quantum=GetPixelGreen(image,p);
- if (GetPixelBlue(image,p) < quantum)
- quantum=GetPixelBlue(image,p);
- pixel.red=0.5*(GetPixelRed(image,p)+factor*quantum);
- pixel.green=0.5*(GetPixelGreen(image,p)+factor*quantum);
- pixel.blue=0.5*(GetPixelBlue(image,p)+factor*quantum);
- quantum=GetPixelRed(image,p);
- if (GetPixelGreen(image,p) > quantum)
- quantum=GetPixelGreen(image,p);
- if (GetPixelBlue(image,p) > quantum)
- quantum=GetPixelBlue(image,p);
- pixel.red=0.5*(pixel.red+factor*quantum);
- pixel.green=0.5*(pixel.green+factor*quantum);
- pixel.blue=0.5*(pixel.blue+factor*quantum);
- SetPixelRed(shift_image,ClampToQuantum(pixel.red),q);
- SetPixelGreen(shift_image,ClampToQuantum(pixel.green),q);
- SetPixelBlue(shift_image,ClampToQuantum(pixel.blue),q);
- p+=GetPixelChannels(image);
- q+=GetPixelChannels(shift_image);
- }
- sync=SyncCacheViewAuthenticPixels(shift_view,exception);
- if (sync == MagickFalse)
- status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
- {
- MagickBooleanType
- proceed;
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp atomic
- #endif
- progress++;
- proceed=SetImageProgress(image,BlueShiftImageTag,progress,image->rows);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- image_view=DestroyCacheView(image_view);
- shift_view=DestroyCacheView(shift_view);
- if (status == MagickFalse)
- shift_image=DestroyImage(shift_image);
- return(shift_image);
- }
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- % C h a r c o a l I m a g e %
- % %
- % %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % CharcoalImage() creates a new image that is a copy of an existing one with
- % the edge highlighted. It allocates the memory necessary for the new Image
- % structure and returns a pointer to the new image.
- %
- % The format of the CharcoalImage method is:
- %
- % Image *CharcoalImage(const Image *image,const double radius,
- % const double sigma,ExceptionInfo *exception)
- %
- % A description of each parameter follows:
- %
- % o image: the image.
- %
- % o radius: the radius of the pixel neighborhood.
- %
- % o sigma: the standard deviation of the Gaussian, in pixels.
- %
- % o exception: return any errors or warnings in this structure.
- %
- */
- MagickExport Image *CharcoalImage(const Image *image,const double radius,
- const double sigma,ExceptionInfo *exception)
- {
- Image
- *charcoal_image,
- *edge_image;
- MagickBooleanType
- status;
- 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);
- edge_image=EdgeImage(image,radius,exception);
- if (edge_image == (Image *) NULL)
- return((Image *) NULL);
- charcoal_image=(Image *) NULL;
- status=ClampImage(edge_image,exception);
- if (status != MagickFalse)
- charcoal_image=BlurImage(edge_image,radius,sigma,exception);
- edge_image=DestroyImage(edge_image);
- if (charcoal_image == (Image *) NULL)
- return((Image *) NULL);
- status=NormalizeImage(charcoal_image,exception);
- if (status != MagickFalse)
- status=NegateImage(charcoal_image,MagickFalse,exception);
- if (status != MagickFalse)
- status=GrayscaleImage(charcoal_image,image->intensity,exception);
- if (status == MagickFalse)
- charcoal_image=DestroyImage(charcoal_image);
- return(charcoal_image);
- }
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- % C o l o r i z e I m a g e %
- % %
- % %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % ColorizeImage() blends the fill color with each pixel in the image.
- % A percentage blend is specified with opacity. Control the application
- % of different color components by specifying a different percentage for
- % each component (e.g. 90/100/10 is 90% red, 100% green, and 10% blue).
- %
- % The format of the ColorizeImage method is:
- %
- % Image *ColorizeImage(const Image *image,const char *blend,
- % const PixelInfo *colorize,ExceptionInfo *exception)
- %
- % A description of each parameter follows:
- %
- % o image: the image.
- %
- % o blend: A character string indicating the level of blending as a
- % percentage.
- %
- % o colorize: A color value.
- %
- % o exception: return any errors or warnings in this structure.
- %
- */
- MagickExport Image *ColorizeImage(const Image *image,const char *blend,
- const PixelInfo *colorize,ExceptionInfo *exception)
- {
- #define ColorizeImageTag "Colorize/Image"
- #define Colorize(pixel,blend_percentage,colorize) \
- (((pixel)*(100.0-(blend_percentage))+(colorize)*(blend_percentage))/100.0)
- CacheView
- *image_view;
- GeometryInfo
- geometry_info;
- Image
- *colorize_image;
- MagickBooleanType
- status;
- MagickOffsetType
- progress;
- MagickStatusType
- flags;
- PixelInfo
- blend_percentage;
- ssize_t
- y;
- /*
- Allocate colorized image.
- */
- 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);
- colorize_image=CloneImage(image,0,0,MagickTrue,exception);
- if (colorize_image == (Image *) NULL)
- return((Image *) NULL);
- if (SetImageStorageClass(colorize_image,DirectClass,exception) == MagickFalse)
- {
- colorize_image=DestroyImage(colorize_image);
- return((Image *) NULL);
- }
- if ((IsGrayColorspace(colorize_image->colorspace) != MagickFalse) ||
- (IsPixelInfoGray(colorize) != MagickFalse))
- (void) SetImageColorspace(colorize_image,sRGBColorspace,exception);
- if ((colorize_image->alpha_trait == UndefinedPixelTrait) &&
- (colorize->alpha_trait != UndefinedPixelTrait))
- (void) SetImageAlpha(colorize_image,OpaqueAlpha,exception);
- if (blend == (const char *) NULL)
- return(colorize_image);
- GetPixelInfo(colorize_image,&blend_percentage);
- flags=ParseGeometry(blend,&geometry_info);
- blend_percentage.red=geometry_info.rho;
- blend_percentage.green=geometry_info.rho;
- blend_percentage.blue=geometry_info.rho;
- blend_percentage.black=geometry_info.rho;
- blend_percentage.alpha=(MagickRealType) TransparentAlpha;
- if ((flags & SigmaValue) != 0)
- blend_percentage.green=geometry_info.sigma;
- if ((flags & XiValue) != 0)
- blend_percentage.blue=geometry_info.xi;
- if ((flags & PsiValue) != 0)
- blend_percentage.alpha=geometry_info.psi;
- if (blend_percentage.colorspace == CMYKColorspace)
- {
- if ((flags & PsiValue) != 0)
- blend_percentage.black=geometry_info.psi;
- if ((flags & ChiValue) != 0)
- blend_percentage.alpha=geometry_info.chi;
- }
- /*
- Colorize DirectClass image.
- */
- status=MagickTrue;
- progress=0;
- image_view=AcquireVirtualCacheView(colorize_image,exception);
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static) shared(progress,status) \
- magick_number_threads(colorize_image,colorize_image,colorize_image->rows,1)
- #endif
- for (y=0; y < (ssize_t) colorize_image->rows; y++)
- {
- MagickBooleanType
- sync;
- register Quantum
- *magick_restrict q;
- register ssize_t
- x;
- if (status == MagickFalse)
- continue;
- q=GetCacheViewAuthenticPixels(image_view,0,y,colorize_image->columns,1,
- exception);
- if (q == (Quantum *) NULL)
- {
- status=MagickFalse;
- continue;
- }
- for (x=0; x < (ssize_t) colorize_image->columns; x++)
- {
- register ssize_t
- i;
- for (i=0; i < (ssize_t) GetPixelChannels(colorize_image); i++)
- {
- PixelTrait traits = GetPixelChannelTraits(colorize_image,
- (PixelChannel) i);
- if (traits == UndefinedPixelTrait)
- continue;
- if ((traits & CopyPixelTrait) != 0)
- continue;
- SetPixelChannel(colorize_image,(PixelChannel) i,ClampToQuantum(
- Colorize(q[i],GetPixelInfoChannel(&blend_percentage,(PixelChannel) i),
- GetPixelInfoChannel(colorize,(PixelChannel) i))),q);
- }
- q+=GetPixelChannels(colorize_image);
- }
- sync=SyncCacheViewAuthenticPixels(image_view,exception);
- if (sync == MagickFalse)
- status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
- {
- MagickBooleanType
- proceed;
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp atomic
- #endif
- progress++;
- proceed=SetImageProgress(image,ColorizeImageTag,progress,
- colorize_image->rows);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- image_view=DestroyCacheView(image_view);
- if (status == MagickFalse)
- colorize_image=DestroyImage(colorize_image);
- return(colorize_image);
- }
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- % C o l o r M a t r i x I m a g e %
- % %
- % %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % ColorMatrixImage() applies color transformation to an image. This method
- % permits saturation changes, hue rotation, luminance to alpha, and various
- % other effects. Although variable-sized transformation matrices can be used,
- % typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
- % (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
- % except offsets are in column 6 rather than 5 (in support of CMYKA images)
- % and offsets are normalized (divide Flash offset by 255).
- %
- % The format of the ColorMatrixImage method is:
- %
- % Image *ColorMatrixImage(const Image *image,
- % const KernelInfo *color_matrix,ExceptionInfo *exception)
- %
- % A description of each parameter follows:
- %
- % o image: the image.
- %
- % o color_matrix: the color matrix.
- %
- % o exception: return any errors or warnings in this structure.
- %
- */
- /* FUTURE: modify to make use of a MagickMatrix Mutliply function
- That should be provided in "matrix.c"
- (ASIDE: actually distorts should do this too but currently doesn't)
- */
- MagickExport Image *ColorMatrixImage(const Image *image,
- const KernelInfo *color_matrix,ExceptionInfo *exception)
- {
- #define ColorMatrixImageTag "ColorMatrix/Image"
- CacheView
- *color_view,
- *image_view;
- double
- ColorMatrix[6][6] =
- {
- { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
- { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 },
- { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 },
- { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
- { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 },
- { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }
- };
- Image
- *color_image;
- MagickBooleanType
- status;
- MagickOffsetType
- progress;
- register ssize_t
- i;
- ssize_t
- u,
- v,
- y;
- /*
- Map given color_matrix, into a 6x6 matrix RGBKA and a constant
- */
- 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);
- i=0;
- for (v=0; v < (ssize_t) color_matrix->height; v++)
- for (u=0; u < (ssize_t) color_matrix->width; u++)
- {
- if ((v < 6) && (u < 6))
- ColorMatrix[v][u]=color_matrix->values[i];
- i++;
- }
- /*
- Initialize color image.
- */
- color_image=CloneImage(image,0,0,MagickTrue,exception);
- if (color_image == (Image *) NULL)
- return((Image *) NULL);
- if (SetImageStorageClass(color_image,DirectClass,exception) == MagickFalse)
- {
- color_image=DestroyImage(color_image);
- return((Image *) NULL);
- }
- if (image->debug != MagickFalse)
- {
- char
- format[MagickPathExtent],
- *message;
- (void) LogMagickEvent(TransformEvent,GetMagickModule(),
- " ColorMatrix image with color matrix:");
- message=AcquireString("");
- for (v=0; v < 6; v++)
- {
- *message='\0';
- (void) FormatLocaleString(format,MagickPathExtent,"%.20g: ",(double) v);
- (void) ConcatenateString(&message,format);
- for (u=0; u < 6; u++)
- {
- (void) FormatLocaleString(format,MagickPathExtent,"%+f ",
- ColorMatrix[v][u]);
- (void) ConcatenateString(&message,format);
- }
- (void) LogMagickEvent(TransformEvent,GetMagickModule(),"%s",message);
- }
- message=DestroyString(message);
- }
- /*
- Apply the ColorMatrix to image.
- */
- status=MagickTrue;
- progress=0;
- image_view=AcquireVirtualCacheView(image,exception);
- color_view=AcquireAuthenticCacheView(color_image,exception);
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static) shared(progress,status) \
- magick_number_threads(image,color_image,image->rows,1)
- #endif
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- PixelInfo
- pixel;
- register const Quantum
- *magick_restrict p;
- register Quantum
- *magick_restrict q;
- register ssize_t
- x;
- if (status == MagickFalse)
- continue;
- p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
- q=GetCacheViewAuthenticPixels(color_view,0,y,color_image->columns,1,
- exception);
- if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
- {
- status=MagickFalse;
- continue;
- }
- GetPixelInfo(image,&pixel);
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- register ssize_t
- v;
- size_t
- height;
- GetPixelInfoPixel(image,p,&pixel);
- height=color_matrix->height > 6 ? 6UL : color_matrix->height;
- for (v=0; v < (ssize_t) height; v++)
- {
- double
- sum;
- sum=ColorMatrix[v][0]*GetPixelRed(image,p)+ColorMatrix[v][1]*
- GetPixelGreen(image,p)+ColorMatrix[v][2]*GetPixelBlue(image,p);
- if (image->colorspace == CMYKColorspace)
- sum+=ColorMatrix[v][3]*GetPixelBlack(image,p);
- if (image->alpha_trait != UndefinedPixelTrait)
- sum+=ColorMatrix[v][4]*GetPixelAlpha(image,p);
- sum+=QuantumRange*ColorMatrix[v][5];
- switch (v)
- {
- case 0: pixel.red=sum; break;
- case 1: pixel.green=sum; break;
- case 2: pixel.blue=sum; break;
- case 3: pixel.black=sum; break;
- case 4: pixel.alpha=sum; break;
- default: break;
- }
- }
- SetPixelViaPixelInfo(color_image,&pixel,q);
- p+=GetPixelChannels(image);
- q+=GetPixelChannels(color_image);
- }
- if (SyncCacheViewAuthenticPixels(color_view,exception) == MagickFalse)
- status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
- {
- MagickBooleanType
- proceed;
- #if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp atomic
- #endif
- progress++;
- proceed=SetImageProgress(image,ColorMatrixImageTag,progress,
- image->rows);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- color_view=DestroyCacheView(color_view);
- image_view=DestroyCacheView(image_view);
- if (status == MagickFalse)
- color_image=DestroyImage(color_image);
- return(color_image);
- }
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- + D e s t r o y F x I n f o %
- % %
- % %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % DestroyFxInfo() deallocates memory associated with an FxInfo structure.
- %
- % The format of the DestroyFxInfo method is:
- %
- % ImageInfo *DestroyFxInfo(ImageInfo *fx_info)
- %
- % A description of each parameter follows:
- %
- % o fx_info: the fx info.
- %
- */
- MagickPrivate FxInfo *DestroyFxInfo(FxInfo *fx_info)
- {
- register ssize_t
- i;
- fx_info->exception=DestroyExceptionInfo(fx_info->exception);
- fx_info->expression=DestroyString(fx_info->expression);
- fx_info->symbols=DestroySplayTree(fx_info->symbols);
- fx_info->colors=DestroySplayTree(fx_info->colors);
- for (i=(ssize_t) GetImageListLength(fx_info->images)-1; i >= 0; i--)
- fx_info->view[i]=DestroyCacheView(fx_info->view[i]);
- fx_info->view=(CacheView **) RelinquishMagickMemory(fx_info->view);
- fx_info->random_info=DestroyRandomInfo(fx_info->random_info);
- fx_info=(FxInfo *) RelinquishMagickMemory(fx_info);
- return(fx_info);
- }
- /*
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % %
- % %
- + F x E v a l u a t e C h a n n e l E x p r e s s i o n %
- % %
- % %
- % %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % FxEvaluateChannelExpression() evaluates an expression and returns the
- % results.
- %
- % The format of the FxEvaluateExpression method is:
- %
- % double FxEvaluateChannelExpression(FxInfo *fx_info,
- % const PixelChannel channel,const ssize_t x,const ssize_t y,
- % double *alpha,Exceptioninfo *exception)
- % double FxEvaluateExpression(FxInfo *fx_info,
- % double *alpha,Exceptioninfo *exception)
- %
- % A description of each parameter follows:
- %
- % o fx_info: the fx info.
- %
- % o channel: the channel.
- %
- % o x,y: the pixel position.
- %
- % o alpha: the result.
- %
- % o exception: return any errors or warnings in this structure.
- %
- */
- static double FxChannelStatistics(FxInfo *fx_info,Image *image,
- PixelChannel channel,const char *symbol,ExceptionInfo *exception)
- {
- ChannelType
- channel_mask;
- char
- key[MagickPathExtent],
- statistic[MagickPathExtent];
- const char
- *value;
- register const char
- *p;
- channel_mask=UndefinedChannel;
- for (p=symbol; (*p != '.') && (*p != '\0'); p++) ;
- if (*p == '.')
- {
- ssize_t
- option;
- option=ParseCommandOption(MagickPixelChannelOptions,MagickTrue,p+1);
- if (option >= 0)
- {
- channel=(PixelChannel) option;
- channel_mask=SetPixelChannelMask(image,(ChannelType)
- (1UL << channel));
- }
- }
- (void) FormatLocaleString(key,MagickPathExtent,"%p.%.20g.%s",(void *) image,
- (double) channel,symbol);
- value=(const char *) GetValueFromSplayTree(fx_info->symbols,key);
- if (value != (const char *) NULL)
- {
- if (channel_mask != UndefinedChannel)
- (void) SetPixelChannelMask(image,channel_mask);
- return(QuantumScale*StringToDouble(value,(char **) NULL));
- }
- (void) DeleteNodeFromSplayTree(fx_info->symbols,key);
- if (LocaleNCompare(symbol,"depth",5) == 0)
- {
- size_t
- depth;
- depth=GetImageDepth(image,exception);
- (void) FormatLocaleString(statistic,MagickPathExtent,"%.20g",(double)
- depth);
- }
- if (LocaleNCompare(symbol,"kurtosis",8) == 0)
- {
- double
- kurtosis,
- skewness;
- (void) GetImageKurtosis(image,&kurtosis,&skewness,exception);
- (void) FormatLocaleString(statistic,MagickPathExtent,"%.20g",kurtosis);
- }
- if (LocaleNCompare(symbol,"maxima",6) == 0)
- {
- double
- maxima,
- minima;
- (void) GetImageRange(image,&minima,&maxima,exception);
- (void) FormatLocaleString(statistic,MagickPathExtent,"%.20g",maxima);
- }
- if (LocaleNCompare(symbol,"mean",4) == 0)
- {
- double
- mean,
- standard_deviation;
- (void) GetImageMean(image,&mean,&standard_deviation,exception);
- (void) FormatLocaleString(statistic,MagickPathExtent,"%.20g",mean);
- }
- if (LocaleNCompare(symbol,"minima",6) == 0)
- {
- double
- maxima,
- minima;
- (void) GetImageRange(image,&minima,&maxima,exception);
- (void) FormatLocaleString(statistic,MagickPathExtent,"%.20g",minima);
- }
- if (LocaleNCompare(symbol,"skewness",8) == 0)
- {
- double
- kurtosis,
- skewness;
- (void) GetImageKurtosis(image,&kurtosis,&skewness,exception);
- (void) FormatLocaleString(statistic,MagickPathExtent,"%.20g",skewness);
- }
- if (LocaleNCompare(symbol,"standard_deviation",18) == 0)
- {
- double
- mean,
- standard_deviation;
- (void) GetImageMean(image,&mean,&standard_deviation,exception);
- (void) FormatLocaleString(statistic,MagickPathExtent,"%.20g",
- standard_deviation);
- }
- if (channel_mask != UndefinedChannel)
- (void) SetPixelChannelMask(image,channel_mask);
- (void) AddValueToSplayTree(fx_info->symbols,ConstantString(key),
- ConstantString(statistic));
- return(QuantumScale*StringToDouble(statistic,(char **) NULL));
- }
- static double
- FxEvaluateSubexpression(FxInfo *,const PixelChannel,const ssize_t,
- const ssize_t,const char *,const size_t,double *,ExceptionInfo *);
- static MagickOffsetType FxGCD(MagickOffsetType alpha,MagickOffsetType beta)
- {
- if (beta != 0)
- return(FxGCD(beta,alpha % beta));
- return(alpha);
- }
- static inline const char *FxSubexpression(const char *expression,
- ExceptionInfo *exception)
- {
- const char
- *subexpression;
- register ssize_t
- level;
- level=0;
- subexpression=expression;
- while ((*subexpression != '\0') &&
- ((level != 1) || (strchr(")",(int) *subexpression) == (char *) NULL)))
- {
- if (strchr("(",(int) *subexpression) != (char *) NULL)
- level++;
- else
- if (strchr(")",(int) *subexpression) != (char *) NULL)
- level--;
- subexpression++;
- }
- if (*subexpression == '\0')
- (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
- "UnbalancedParenthesis","`%s'",expression);
- return(subexpression);
- }
- static double FxGetSymbol(FxInfo *fx_info,const PixelChannel channel,
- const ssize_t x,const ssize_t y,const char *expression,const size_t depth,
- ExceptionInfo *exception)
- {
- char
- *q,
- symbol[MagickPathExtent];
- const char
- *p,
- *value;
- Image
- *image;
- MagickBooleanType
- status;
- PixelInfo
- pixel;
- double
- alpha,
- beta;
- PointInfo
- point;
- register ssize_t
- i;
- size_t
- level;
- p=expression;
- i=GetImageIndexInList(fx_info->images);
- level=0;
- point.x=(double) x;
- point.y=(double) y;
- if (isalpha((int) ((unsigned char) *(p+1))) == 0)
- {
- char
- *subexpression;
- subexpression=AcquireString(expression);
- if (strchr("suv",(int) *p) != (char *) NULL)
- {
- switch (*p)
- {
- case 's':
- default:
- {
- i=GetImageIndexInList(fx_info->images);
- break;
- }
- case 'u': i=0; break;
- case 'v': i=1; break;
- }
- p++;
- if (*p == '[')
- {
- level++;
- q=subexpression;
- for (p++; *p != '\0'; )
- {
- if (*p == '[')
- level++;
- else
- if (*p == ']')
- {
- level--;
- if (level == 0)
- break;
- }
- *q++=(*p++);
- }
- *q='\0';
- alpha=FxEvaluateSubexpression(fx_info,channel,x,y,subexpression,
- depth,&beta,exception);
- i=(ssize_t) alpha;
- if (*p != '\0')
- p++;
- }
- if (*p == '.')
- p++;
- }
- if ((*p == 'p') && (isalpha((int) ((unsigned char) *(p+1))) == 0))
- {
- p++;
- if (*p == '{')
- {
- level++;
- q=subexpression;
- for (p++; *p != '\0'; )
- {
- if (*p == '{')
- level++;
- else
- if (*p == '}')
- {
- level--;
- if (level == 0)
- break;
- }
- *q++=(*p++);
- }
- *q='\0';
- alpha=FxEvaluateSubexpression(fx_info,channel,x,y,subexpression,
- depth,&beta,exception);
- point.x=alpha;
- point.y=beta;
- if (*p != '\0')
- p++;
- }
- else
- if (*p == '[')
- {
- level++;
- q=subexpression;
- for (p++; *p != '\0'; )
- {
- if (*p == '[')
- level++;
- else
- if (*p == ']')
- {
- level--;
- if (level == 0)
- break;
- }
- *q++=(*p++);
- }
- *q='\0';
- alpha=FxEvaluateSubexpression(fx_info,channel,x,y,subexpression,
- depth,&beta,exception);
- point.x+=alpha;
- point.y+=beta;
- if (*p != '\0')
- p++;
- }
- if (*p == '.')
- p++;
- }
- subexpression=DestroyString(subexpression);
- }
- image=GetImageFromList(fx_info->images,i);
- if (image == (Image *) NULL)
- {
- (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
- "NoSuchImage","`%s'",expression);
- return(0.0);
- }
- i=GetImageIndexInList(image);
- GetPixelInfo(image,&pixel);
- status=InterpolatePixelInfo(image,fx_info->view[i],image->interpolate,
- point.x,point.y,&pixel,exception);
- (void) status;
- if ((strlen(p) > 2) && (LocaleCompare(p,"intensity") != 0) &&
- (LocaleCompare(p,"luma") != 0) && (LocaleCompare(p,"luminance") != 0) &&
- (LocaleCompare(p,"hue") != 0) && (LocaleCompare(p,"saturation") != 0) &&
- (LocaleCompare(p,"lightness") != 0))
- {
- char
- name[MagickPathExtent];
- (void) CopyMagickString(name,p,MagickPathExtent);
- for (q=name+(strlen(name)-1); q > name; q--)
- {
- if (*q == ')')
- break;
- if (*q == '.')
- {
- *q='\0';
- break;
- }
- }
- if ((strlen(name) > 2) &&
- (GetValueFromSplayTree(fx_info->symbols,name) == (const char *) NULL))
- {
- PixelInfo
- *color;
- color=(PixelInfo *) GetValueFromSplayTree(fx_info->colors,name);
- if (color != (PixelInfo *) NULL)
- {
- pixel=(*color);
- p+=strlen(name);
- }
- else
- {
- MagickBooleanType
- status;
- status=QueryColorCompliance(name,AllCompliance,&pixel,
- fx_info->exception);
- if (status != MagickFalse)
- {
- (void) AddValueToSplayTree(fx_info->colors,ConstantString(
- name),ClonePixelInfo(&pixel));
- p+=strlen(name);
- }
- }
- }
- }
- (void) CopyMagickString(symbol,p,MagickPathExtent);
- StripString(symbol);
- if (*symbol == '\0')
- {
- switch (channel)
- {
- case RedPixelChannel: return(QuantumScale*pixel.red);
- case GreenPixelChannel: return(QuantumScale*pixel.green);
- case BluePixelChannel: return(QuantumScale*pixel.blue);
- case BlackPixelChannel:
- {
- if (image->colorspace != CMYKColorspace)
- {
- (void) ThrowMagickException(exception,GetMagickModule(),
- ImageError,"ColorSeparatedImageRequired","`%s'",
- image->filename);
- return(0.0);
- }
- return(QuantumScale*pixel.black);
- }
- case AlphaPixelChannel:
- {
- if (pixel.alpha_trait == UndefinedPixelTrait)
- return(1.0);
- alpha=(double) (QuantumScale*pixel.alpha);
- return(alpha);
- }
- case CompositePixelChannel:
- {
- Quantum
- quantum_pixel[MaxPixelChannels];
- SetPixelViaPixelInfo(image,&pixel,quantum_pixel);
- return(QuantumScale*GetPixelIntensity(image,quantum_pixel));
- }
- case IndexPixelChannel:
- return(0.0);
- default:
- break;
- }
- (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
- "UnableToParseExpression","`%s'",p);
- return(0.0);
- }
- switch (*symbol)
- {
- case 'A':
- case 'a':
- {
- if (LocaleCompare(symbol,"a") == 0)
- return((QuantumScale*pixel.alpha));
- break;
- }
- case 'B':
- case 'b':
- {
- if (LocaleCompare(symbol,"b") == 0)
- return(QuantumScale*pixel.blue);
- break;
- }
- case 'C':
- case 'c':
- {
- if (LocaleNCompare(symbol,"channel",7) == 0)
- {
- GeometryInfo
- channel_info;
- MagickStatusType
- flags;
- flags=ParseGeometry(symbol+7,&channel_info);
- if (image->colorspace == CMYKColorspace)
- switch (channel)
- {
- case CyanPixelChannel:
- {
- if ((flags & RhoValue) == 0)
- return(0.0);
- return(channel_info.rho);
- }
- case MagentaPixelChannel:
- {
- if ((flags & SigmaValue) == 0)
- return(0.0);
- return(channel_info.sigma);
- }
- case YellowPixelChannel:
- {
- if ((flags & XiValue) == 0)
- return(0.0);
- return(channel_info.xi);
- }
- case BlackPixelChannel:
- {
- if ((flags & PsiValue) == 0)
- return(0.0);
- return(channel_info.psi);
- }
- case AlphaPixelChannel:
- {
- if ((flags & ChiValue) == 0)
- return(0.0);
- return(channel_info.chi);
- }
- default:
- return(0.0);
- }
- switch (channel)
- {
- case RedPixelChannel:
- {
- …
Large files files are truncated, but you can click here to view the full file