43#include "magick/studio.h"
44#include "magick/accelerate-private.h"
45#include "magick/annotate.h"
46#include "magick/artifact.h"
47#include "magick/attribute.h"
48#include "magick/cache.h"
49#include "magick/cache-view.h"
50#include "magick/channel.h"
51#include "magick/color.h"
52#include "magick/color-private.h"
53#include "magick/colorspace.h"
54#include "magick/colorspace-private.h"
55#include "magick/composite.h"
56#include "magick/decorate.h"
57#include "magick/distort.h"
58#include "magick/draw.h"
59#include "magick/effect.h"
60#include "magick/enhance.h"
61#include "magick/exception.h"
62#include "magick/exception-private.h"
64#include "magick/fx-private.h"
65#include "magick/gem.h"
66#include "magick/geometry.h"
67#include "magick/layer.h"
68#include "magick/list.h"
69#include "magick/log.h"
70#include "magick/image.h"
71#include "magick/image-private.h"
72#include "magick/magick.h"
73#include "magick/memory_.h"
74#include "magick/memory-private.h"
75#include "magick/monitor.h"
76#include "magick/monitor-private.h"
77#include "magick/opencl-private.h"
78#include "magick/option.h"
79#include "magick/pixel-accessor.h"
80#include "magick/pixel-private.h"
81#include "magick/property.h"
82#include "magick/quantum.h"
83#include "magick/quantum-private.h"
84#include "magick/random_.h"
85#include "magick/random-private.h"
86#include "magick/resample.h"
87#include "magick/resample-private.h"
88#include "magick/resize.h"
89#include "magick/resource_.h"
90#include "magick/splay-tree.h"
91#include "magick/statistic.h"
92#include "magick/statistic-private.h"
93#include "magick/string_.h"
94#include "magick/string-private.h"
95#include "magick/thread-private.h"
96#include "magick/timer-private.h"
97#include "magick/threshold.h"
98#include "magick/token.h"
99#include "magick/transform.h"
100#include "magick/utility.h"
107 BitwiseAndAssignmentOperator = 0xd9U,
108 BitwiseOrAssignmentOperator,
109 LeftShiftAssignmentOperator,
110 RightShiftAssignmentOperator,
111 PowerAssignmentOperator,
112 ModuloAssignmentOperator,
113 PlusAssignmentOperator,
114 SubtractAssignmentOperator,
115 MultiplyAssignmentOperator,
116 DivideAssignmentOperator,
117 IncrementAssignmentOperator,
118 DecrementAssignmentOperator,
121 LessThanEqualOperator,
122 GreaterThanEqualOperator,
179MagickExport FxInfo *AcquireFxInfo(
const Image *images,
const char *expression)
193 fx_info=(FxInfo *) AcquireCriticalMemory(
sizeof(*fx_info));
194 (void) memset(fx_info,0,
sizeof(*fx_info));
195 fx_info->exception=AcquireExceptionInfo();
196 fx_info->images=images;
197 fx_info->colors=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
198 RelinquishMagickMemory);
199 fx_info->symbols=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
200 RelinquishMagickMemory);
201 fx_info->view=(CacheView **) AcquireQuantumMemory(GetImageListLength(
202 fx_info->images),
sizeof(*fx_info->view));
203 if (fx_info->view == (CacheView **) NULL)
204 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
206 next=GetFirstImageInList(fx_info->images);
207 for ( ; next != (Image *) NULL; next=next->next)
209 fx_info->view[i]=AcquireVirtualCacheView(next,fx_info->exception);
212 fx_info->random_info=AcquireRandomInfo();
213 fx_info->expression=ConstantString(expression);
214 fx_info->file=stderr;
219 *fx_op=(
unsigned char) BitwiseAndAssignmentOperator;
220 (void) SubstituteString(&fx_info->expression,
"&=",(
char *) fx_op);
221 *fx_op=(
unsigned char) BitwiseOrAssignmentOperator;
222 (void) SubstituteString(&fx_info->expression,
"|=",(
char *) fx_op);
223 *fx_op=(
unsigned char) LeftShiftAssignmentOperator;
224 (void) SubstituteString(&fx_info->expression,
"<<=",(
char *) fx_op);
225 *fx_op=(
unsigned char) RightShiftAssignmentOperator;
226 (void) SubstituteString(&fx_info->expression,
">>=",(
char *) fx_op);
227 *fx_op=(
unsigned char) PowerAssignmentOperator;
228 (void) SubstituteString(&fx_info->expression,
"^=",(
char *) fx_op);
229 *fx_op=(
unsigned char) ModuloAssignmentOperator;
230 (void) SubstituteString(&fx_info->expression,
"%=",(
char *) fx_op);
231 *fx_op=(
unsigned char) PlusAssignmentOperator;
232 (void) SubstituteString(&fx_info->expression,
"+=",(
char *) fx_op);
233 *fx_op=(
unsigned char) SubtractAssignmentOperator;
234 (void) SubstituteString(&fx_info->expression,
"-=",(
char *) fx_op);
235 *fx_op=(
unsigned char) MultiplyAssignmentOperator;
236 (void) SubstituteString(&fx_info->expression,
"*=",(
char *) fx_op);
237 *fx_op=(
unsigned char) DivideAssignmentOperator;
238 (void) SubstituteString(&fx_info->expression,
"/=",(
char *) fx_op);
239 *fx_op=(
unsigned char) IncrementAssignmentOperator;
240 (void) SubstituteString(&fx_info->expression,
"++",(
char *) fx_op);
241 *fx_op=(
unsigned char) DecrementAssignmentOperator;
242 (void) SubstituteString(&fx_info->expression,
"--",(
char *) fx_op);
243 *fx_op=(
unsigned char) LeftShiftOperator;
244 (void) SubstituteString(&fx_info->expression,
"<<",(
char *) fx_op);
245 *fx_op=(
unsigned char) RightShiftOperator;
246 (void) SubstituteString(&fx_info->expression,
">>",(
char *) fx_op);
247 *fx_op=(
unsigned char) LessThanEqualOperator;
248 (void) SubstituteString(&fx_info->expression,
"<=",(
char *) fx_op);
249 *fx_op=(
unsigned char) GreaterThanEqualOperator;
250 (void) SubstituteString(&fx_info->expression,
">=",(
char *) fx_op);
251 *fx_op=(
unsigned char) EqualOperator;
252 (void) SubstituteString(&fx_info->expression,
"==",(
char *) fx_op);
253 *fx_op=(
unsigned char) NotEqualOperator;
254 (void) SubstituteString(&fx_info->expression,
"!=",(
char *) fx_op);
255 *fx_op=(
unsigned char) LogicalAndOperator;
256 (void) SubstituteString(&fx_info->expression,
"&&",(
char *) fx_op);
257 *fx_op=(
unsigned char) LogicalOrOperator;
258 (void) SubstituteString(&fx_info->expression,
"||",(
char *) fx_op);
259 *fx_op=(
unsigned char) ExponentialNotation;
260 (void) SubstituteString(&fx_info->expression,
"**",(
char *) fx_op);
264 (void) SubstituteString(&fx_info->expression,
"-",
"-1.0*");
265 (void) SubstituteString(&fx_info->expression,
"^-1.0*",
"^-");
266 (void) SubstituteString(&fx_info->expression,
"E-1.0*",
"E-");
267 (void) SubstituteString(&fx_info->expression,
"e-1.0*",
"e-");
268 (void) SubstituteString(&fx_info->expression,
" ",
"");
294MagickExport FxInfo *DestroyFxInfo(FxInfo *fx_info)
299 fx_info->exception=DestroyExceptionInfo(fx_info->exception);
300 fx_info->expression=DestroyString(fx_info->expression);
301 fx_info->symbols=DestroySplayTree(fx_info->symbols);
302 fx_info->colors=DestroySplayTree(fx_info->colors);
303 for (i=(ssize_t) GetImageListLength(fx_info->images)-1; i >= 0; i--)
304 fx_info->view[i]=DestroyCacheView(fx_info->view[i]);
305 fx_info->view=(CacheView **) RelinquishMagickMemory(fx_info->view);
306 fx_info->random_info=DestroyRandomInfo(fx_info->random_info);
307 fx_info=(FxInfo *) RelinquishMagickMemory(fx_info);
347static inline const double *GetFxSymbolValue(FxInfo *fx_info,
const char *symbol)
349 return((
const double *) GetValueFromSplayTree(fx_info->symbols,symbol));
352static inline MagickBooleanType SetFxSymbolValue(
353 FxInfo *magick_restrict fx_info,
const char *magick_restrict symbol,
359 object=(
double *) GetValueFromSplayTree(fx_info->symbols,symbol);
360 if (
object != (
double *) NULL)
365 object=(
double *) AcquireMagickMemory(
sizeof(*
object));
366 if (
object == (
double *) NULL)
368 (void) ThrowMagickException(fx_info->exception,GetMagickModule(),
369 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
370 fx_info->images->filename);
374 return(AddValueToSplayTree(fx_info->symbols,ConstantString(symbol),
object));
377static double FxChannelStatistics(FxInfo *fx_info,
const Image *image,
378 ChannelType channel,
const char *symbol,ExceptionInfo *exception)
381 channel_symbol[MaxTextExtent],
393 for (p=symbol; (*p !=
'.') && (*p !=
'\0'); p++) ;
394 *channel_symbol=
'\0';
400 (void) CopyMagickString(channel_symbol,p+1,MaxTextExtent);
401 option=ParseCommandOption(MagickChannelOptions,MagickTrue,channel_symbol);
403 channel=(ChannelType) option;
405 (void) FormatLocaleString(key,MaxTextExtent,
"%p.%.20g.%s",(
void *) image,
406 (
double) channel,symbol);
407 value=GetFxSymbolValue(fx_info,key);
408 if (value != (
const double *) NULL)
409 return(QuantumScale*(*value));
411 if (LocaleNCompare(symbol,
"depth",5) == 0)
416 depth=GetImageChannelDepth(image,channel,exception);
417 statistic=(double) depth;
419 if (LocaleNCompare(symbol,
"kurtosis",8) == 0)
425 (void) GetImageChannelKurtosis(image,channel,&kurtosis,&skewness,
427 statistic=QuantumRange*kurtosis;
429 if (LocaleNCompare(symbol,
"maxima",6) == 0)
435 (void) GetImageChannelRange(image,channel,&minima,&maxima,exception);
438 if (LocaleNCompare(symbol,
"mean",4) == 0)
444 (void) GetImageChannelMean(image,channel,&mean,&standard_deviation,
448 if (LocaleNCompare(symbol,
"minima",6) == 0)
454 (void) GetImageChannelRange(image,channel,&minima,&maxima,exception);
457 if (LocaleNCompare(symbol,
"skewness",8) == 0)
463 (void) GetImageChannelKurtosis(image,channel,&kurtosis,&skewness,
465 statistic=QuantumRange*skewness;
467 if (LocaleNCompare(symbol,
"standard_deviation",18) == 0)
473 (void) GetImageChannelMean(image,channel,&mean,&standard_deviation,
475 statistic=standard_deviation;
477 if (SetFxSymbolValue(fx_info,key,statistic) == MagickFalse)
479 return(QuantumScale*statistic);
483 FxEvaluateSubexpression(FxInfo *,
const ChannelType,
const ssize_t,
484 const ssize_t,
const char *,
const size_t,
double *,ExceptionInfo *);
486static inline MagickBooleanType IsFxFunction(
const char *expression,
487 const char *name,
const size_t length)
495 for (i=0; i <= length; i++)
496 if (expression[i] ==
'\0')
498 c=expression[length];
499 if ((LocaleNCompare(expression,name,length) == 0) &&
500 ((isspace((
int) ((
unsigned char) c)) == 0) || (c ==
'(')))
505static inline double FxGCD(
const double alpha,
const double beta,
508#define FxMaxFunctionDepth 200
511 return(FxGCD(beta,alpha,depth+1));
512 if ((fabs(beta) < 0.001) || (depth >= FxMaxFunctionDepth))
514 return(FxGCD(beta,alpha-beta*floor(alpha/beta),depth+1));
517static inline const char *FxSubexpression(
const char *expression,
518 ExceptionInfo *exception)
527 subexpression=expression;
528 while ((*subexpression !=
'\0') &&
529 ((level != 1) || (strchr(
")",(
int) *subexpression) == (
char *) NULL)))
531 if (strchr(
"(",(
int) *subexpression) != (
char *) NULL)
534 if (strchr(
")",(
int) *subexpression) != (
char *) NULL)
538 if (*subexpression ==
'\0')
539 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
540 "UnbalancedParenthesis",
"`%s'",expression);
541 return(subexpression);
544static double FxGetSymbol(FxInfo *fx_info,
const ChannelType channel,
545 const ssize_t x,
const ssize_t y,
const char *expression,
const size_t depth,
546 ExceptionInfo *exception)
550 symbol[MaxTextExtent];
582 i=GetImageIndexInList(fx_info->images);
586 if (isalpha((
int) ((
unsigned char) *(p+1))) == 0)
591 subexpression=AcquireString(expression);
592 if (strchr(
"suv",(
int) *p) != (
char *) NULL)
599 i=GetImageIndexInList(fx_info->images);
602 case 'u': i=0;
break;
603 case 'v': i=1;
break;
610 for (p++; *p !=
'\0'; )
624 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,subexpression,
625 depth,&beta,exception);
633 if ((*p ==
'p') && (isalpha((
int) ((
unsigned char) *(p+1))) == 0))
640 for (p++; *p !=
'\0'; )
654 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,subexpression,
655 depth,&beta,exception);
666 for (p++; *p !=
'\0'; )
680 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,subexpression,
681 depth,&beta,exception);
690 subexpression=DestroyString(subexpression);
692 image=GetImageFromList(fx_info->images,i);
693 if (image == (Image *) NULL)
695 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
696 "NoSuchImage",
"`%s'",expression);
699 i=GetImageIndexInList(image);
700 GetMagickPixelPacket(image,&pixel);
701 status=InterpolateMagickPixelPacket(image,fx_info->view[i],image->interpolate,
702 point.x,point.y,&pixel,exception);
704 if ((*p !=
'\0') && (*(p+1) !=
'\0') && (*(p+2) !=
'\0') &&
705 (LocaleCompare(p,
"intensity") != 0) && (LocaleCompare(p,
"luma") != 0) &&
706 (LocaleCompare(p,
"luminance") != 0) && (LocaleCompare(p,
"hue") != 0) &&
707 (LocaleCompare(p,
"saturation") != 0) &&
708 (LocaleCompare(p,
"lightness") != 0))
716 (void) CopyMagickString(name,p,MaxTextExtent);
718 for (q=name+length-1; q > name; q--)
729 if ((*q !=
'\0') && (*(q+1) !=
'\0') && (*(q+2) !=
'\0') &&
730 (GetFxSymbolValue(fx_info,name) == (
const double *) NULL))
735 color=(MagickPixelPacket *) GetValueFromSplayTree(fx_info->colors,
737 if (color != (MagickPixelPacket *) NULL)
740 p+=(ptrdiff_t) length;
743 if (QueryMagickColor(name,&pixel,fx_info->exception) != MagickFalse)
745 (void) AddValueToSplayTree(fx_info->colors,ConstantString(name),
746 CloneMagickPixelPacket(&pixel));
747 p+=(ptrdiff_t) length;
751 (void) CopyMagickString(symbol,p,MaxTextExtent);
757 case RedChannel:
return(QuantumScale*pixel.red);
758 case GreenChannel:
return(QuantumScale*pixel.green);
759 case BlueChannel:
return(QuantumScale*pixel.blue);
765 if (pixel.matte == MagickFalse)
767 alpha=(double) (QuantumScale*GetPixelAlpha(&pixel));
772 if (image->colorspace != CMYKColorspace)
774 (void) ThrowMagickException(exception,GetMagickModule(),
775 ImageError,
"ColorSeparatedImageRequired",
"`%s'",
779 return(QuantumScale*pixel.index);
781 case DefaultChannels:
782 return(QuantumScale*GetMagickPixelIntensity(image,&pixel));
786 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
787 "UnableToParseExpression",
"`%s'",p);
795 if (LocaleCompare(symbol,
"a") == 0)
796 return((
double) (QuantumScale*GetPixelAlpha(&pixel)));
802 if (LocaleCompare(symbol,
"b") == 0)
803 return(QuantumScale*pixel.blue);
809 if (IsFxFunction(symbol,
"channel",7) != MagickFalse)
817 flags=ParseGeometry(symbol+7,&channel_info);
818 if (image->colorspace == CMYKColorspace)
823 if ((flags & RhoValue) == 0)
825 return(channel_info.rho);
829 if ((flags & SigmaValue) == 0)
831 return(channel_info.sigma);
835 if ((flags & XiValue) == 0)
837 return(channel_info.xi);
841 if ((flags & PsiValue) == 0)
843 return(channel_info.psi);
847 if ((flags & ChiValue) == 0)
849 return(channel_info.chi);
858 if ((flags & RhoValue) == 0)
860 return(channel_info.rho);
864 if ((flags & SigmaValue) == 0)
866 return(channel_info.sigma);
870 if ((flags & XiValue) == 0)
872 return(channel_info.xi);
876 if ((flags & PsiValue) == 0)
878 return(channel_info.psi);
882 if ((flags & ChiValue) == 0)
884 return(channel_info.chi);
890 if (LocaleCompare(symbol,
"c") == 0)
891 return(QuantumScale*pixel.red);
897 if (LocaleNCompare(symbol,
"depth",5) == 0)
898 return(FxChannelStatistics(fx_info,image,channel,symbol,exception));
904 if (LocaleCompare(symbol,
"extent") == 0)
906 if (image->extent != 0)
907 return((
double) image->extent);
908 return((
double) GetBlobSize(image));
915 if (LocaleCompare(symbol,
"g") == 0)
916 return(QuantumScale*pixel.green);
922 if (LocaleNCompare(symbol,
"kurtosis",8) == 0)
923 return(FxChannelStatistics(fx_info,image,channel,symbol,exception));
924 if (LocaleCompare(symbol,
"k") == 0)
926 if (image->colorspace != CMYKColorspace)
928 (void) ThrowMagickException(exception,GetMagickModule(),
929 OptionError,
"ColorSeparatedImageRequired",
"`%s'",
933 return(QuantumScale*pixel.index);
940 if (LocaleCompare(symbol,
"h") == 0)
941 return((
double) image->rows);
942 if (LocaleCompare(symbol,
"hue") == 0)
949 ConvertRGBToHSL(ClampToQuantum(pixel.red),ClampToQuantum(pixel.green),
950 ClampToQuantum(pixel.blue),&hue,&saturation,&lightness);
958 if ((LocaleCompare(symbol,
"image.depth") == 0) ||
959 (LocaleCompare(symbol,
"image.minima") == 0) ||
960 (LocaleCompare(symbol,
"image.maxima") == 0) ||
961 (LocaleCompare(symbol,
"image.mean") == 0) ||
962 (LocaleCompare(symbol,
"image.kurtosis") == 0) ||
963 (LocaleCompare(symbol,
"image.skewness") == 0) ||
964 (LocaleCompare(symbol,
"image.standard_deviation") == 0))
965 return(FxChannelStatistics(fx_info,image,channel,symbol+6,exception));
966 if (LocaleCompare(symbol,
"image.resolution.x") == 0)
967 return(image->x_resolution);
968 if (LocaleCompare(symbol,
"image.resolution.y") == 0)
969 return(image->y_resolution);
970 if (LocaleCompare(symbol,
"intensity") == 0)
971 return(QuantumScale*GetMagickPixelIntensity(image,&pixel));
972 if (LocaleCompare(symbol,
"i") == 0)
979 if (LocaleCompare(symbol,
"j") == 0)
986 if (LocaleCompare(symbol,
"lightness") == 0)
993 ConvertRGBToHSL(ClampToQuantum(pixel.red),ClampToQuantum(pixel.green),
994 ClampToQuantum(pixel.blue),&hue,&saturation,&lightness);
997 if (LocaleCompare(symbol,
"luma") == 0)
1002 luma=0.212656*pixel.red+0.715158*pixel.green+0.072186*pixel.blue;
1003 return(QuantumScale*luma);
1005 if (LocaleCompare(symbol,
"luminance") == 0)
1010 luminance=0.212656*pixel.red+0.715158*pixel.green+0.072186*pixel.blue;
1011 return(QuantumScale*luminance);
1018 if (LocaleNCompare(symbol,
"maxima",6) == 0)
1019 return(FxChannelStatistics(fx_info,image,channel,symbol,exception));
1020 if (LocaleNCompare(symbol,
"mean",4) == 0)
1021 return(FxChannelStatistics(fx_info,image,channel,symbol,exception));
1022 if (LocaleNCompare(symbol,
"minima",6) == 0)
1023 return(FxChannelStatistics(fx_info,image,channel,symbol,exception));
1024 if (LocaleCompare(symbol,
"m") == 0)
1025 return(QuantumScale*pixel.green);
1031 if (LocaleCompare(symbol,
"n") == 0)
1032 return((
double) GetImageListLength(fx_info->images));
1038 if (LocaleCompare(symbol,
"o") == 0)
1039 return(QuantumScale*pixel.opacity);
1045 if (LocaleCompare(symbol,
"page.height") == 0)
1046 return((
double) image->page.height);
1047 if (LocaleCompare(symbol,
"page.width") == 0)
1048 return((
double) image->page.width);
1049 if (LocaleCompare(symbol,
"page.x") == 0)
1050 return((
double) image->page.x);
1051 if (LocaleCompare(symbol,
"page.y") == 0)
1052 return((
double) image->page.y);
1053 if (LocaleCompare(symbol,
"printsize.x") == 0)
1054 return(MagickSafeReciprocal(image->x_resolution)*image->columns);
1055 if (LocaleCompare(symbol,
"printsize.y") == 0)
1056 return(MagickSafeReciprocal(image->y_resolution)*image->rows);
1062 if (LocaleCompare(symbol,
"quality") == 0)
1063 return((
double) image->quality);
1069 if (LocaleCompare(symbol,
"resolution.x") == 0)
1070 return(image->x_resolution);
1071 if (LocaleCompare(symbol,
"resolution.y") == 0)
1072 return(image->y_resolution);
1073 if (LocaleCompare(symbol,
"r") == 0)
1074 return(QuantumScale*pixel.red);
1080 if (LocaleCompare(symbol,
"saturation") == 0)
1087 ConvertRGBToHSL(ClampToQuantum(pixel.red),ClampToQuantum(pixel.green),
1088 ClampToQuantum(pixel.blue),&hue,&saturation,&lightness);
1091 if (LocaleNCompare(symbol,
"skewness",8) == 0)
1092 return(FxChannelStatistics(fx_info,image,channel,symbol,exception));
1093 if (LocaleNCompare(symbol,
"standard_deviation",18) == 0)
1094 return(FxChannelStatistics(fx_info,image,channel,symbol,exception));
1100 if (LocaleCompare(symbol,
"t") == 0)
1101 return((
double) GetImageIndexInList(fx_info->images));
1107 if (LocaleCompare(symbol,
"w") == 0)
1108 return((
double) image->columns);
1114 if (LocaleCompare(symbol,
"y") == 0)
1115 return(QuantumScale*pixel.blue);
1121 if (LocaleCompare(symbol,
"z") == 0)
1126 depth=(double) GetImageChannelDepth(image,channel,fx_info->exception);
1134 value=GetFxSymbolValue(fx_info,symbol);
1135 if (value != (
const double *) NULL)
1137 artifact=GetImageArtifact(image,symbol);
1138 if (artifact != (
const char *) NULL)
1139 return(StringToDouble(artifact,(
char **) NULL));
1140 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1141 "UndefinedVariable",
"`%s'",symbol);
1142 (void) SetFxSymbolValue(fx_info,symbol,0.0);
1146static const char *FxOperatorPrecedence(
const char *expression,
1147 ExceptionInfo *exception)
1151 UndefinedPrecedence,
1153 BitwiseComplementPrecedence,
1155 ExponentialNotationPrecedence,
1159 RelationalPrecedence,
1160 EquivalencyPrecedence,
1161 BitwiseAndPrecedence,
1162 BitwiseOrPrecedence,
1163 LogicalAndPrecedence,
1164 LogicalOrPrecedence,
1166 AssignmentPrecedence,
1186 subexpression=(
const char *) NULL;
1187 target=NullPrecedence;
1188 while ((c !=
'\0') && (*expression !=
'\0'))
1190 precedence=UndefinedPrecedence;
1191 if ((isspace((
int) ((
unsigned char) *expression)) != 0) || (c == (
int)
'@'))
1196 switch (*expression)
1201#if defined(MAGICKCORE_HAVE_ACOSH)
1202 if (IsFxFunction(expression,
"acosh",5) != MagickFalse)
1208#if defined(MAGICKCORE_HAVE_ASINH)
1209 if (IsFxFunction(expression,
"asinh",5) != MagickFalse)
1215#if defined(MAGICKCORE_HAVE_ATANH)
1216 if (IsFxFunction(expression,
"atanh",5) != MagickFalse)
1222 if (IsFxFunction(expression,
"atan2",5) != MagickFalse)
1232 if ((isdigit((
int) ((
unsigned char) c)) != 0) &&
1233 ((LocaleNCompare(expression,
"E+",2) == 0) ||
1234 (LocaleNCompare(expression,
"E-",2) == 0)))
1244 if ((IsFxFunction(expression,
"j0",2) != MagickFalse) ||
1245 (IsFxFunction(expression,
"j1",2) != MagickFalse))
1254 while (isxdigit((
int) ((
unsigned char) *(expression+1))) != 0)
1261 if ((c == (
int)
'{') || (c == (
int)
'['))
1264 if ((c == (
int)
'}') || (c == (
int)
']'))
1267 switch ((
unsigned char) *expression)
1272 precedence=BitwiseComplementPrecedence;
1278 precedence=ExponentPrecedence;
1283 if (((c != 0) && ((isdigit((
int) ((
unsigned char) c)) != 0) ||
1284 (strchr(
")",c) != (
char *) NULL))) &&
1285 (((islower((
int) ((
unsigned char) *expression)) != 0) ||
1286 (strchr(
"(",(
int) ((
unsigned char) *expression)) != (
char *) NULL)) ||
1287 ((isdigit((
int) ((
unsigned char) c)) == 0) &&
1288 (isdigit((
int) ((
unsigned char) *expression)) != 0))) &&
1289 (strchr(
"xy",(
int) ((
unsigned char) *expression)) == (
char *) NULL))
1290 precedence=MultiplyPrecedence;
1297 precedence=MultiplyPrecedence;
1303 if ((strchr(
"(+-/*%:&^|<>~,",c) == (
char *) NULL) ||
1304 (isalpha((
int) ((
unsigned char) c)) != 0))
1305 precedence=AdditionPrecedence;
1308 case BitwiseAndAssignmentOperator:
1309 case BitwiseOrAssignmentOperator:
1310 case LeftShiftAssignmentOperator:
1311 case RightShiftAssignmentOperator:
1312 case PowerAssignmentOperator:
1313 case ModuloAssignmentOperator:
1314 case PlusAssignmentOperator:
1315 case SubtractAssignmentOperator:
1316 case MultiplyAssignmentOperator:
1317 case DivideAssignmentOperator:
1318 case IncrementAssignmentOperator:
1319 case DecrementAssignmentOperator:
1321 precedence=AssignmentPrecedence;
1324 case LeftShiftOperator:
1325 case RightShiftOperator:
1327 precedence=ShiftPrecedence;
1331 case LessThanEqualOperator:
1332 case GreaterThanEqualOperator:
1335 precedence=RelationalPrecedence;
1339 case NotEqualOperator:
1341 precedence=EquivalencyPrecedence;
1346 precedence=BitwiseAndPrecedence;
1351 precedence=BitwiseOrPrecedence;
1354 case LogicalAndOperator:
1356 precedence=LogicalAndPrecedence;
1359 case LogicalOrOperator:
1361 precedence=LogicalOrPrecedence;
1364 case ExponentialNotation:
1366 precedence=ExponentialNotationPrecedence;
1372 precedence=TernaryPrecedence;
1377 precedence=AssignmentPrecedence;
1382 precedence=CommaPrecedence;
1387 precedence=SeparatorPrecedence;
1391 if ((precedence == BitwiseComplementPrecedence) ||
1392 (precedence == TernaryPrecedence) ||
1393 (precedence == AssignmentPrecedence))
1395 if (precedence > target)
1401 subexpression=expression;
1405 if (precedence >= target)
1411 subexpression=expression;
1413 if (strchr(
"(",(
int) *expression) != (
char *) NULL)
1414 expression=FxSubexpression(expression,exception);
1415 c=(int) (*expression++);
1417 return(subexpression);
1420static double FxEvaluateSubexpression(FxInfo *fx_info,
const ChannelType channel,
1421 const ssize_t x,
const ssize_t y,
const char *expression,
const size_t depth,
1422 double *beta,ExceptionInfo *exception)
1424#define FxMaxParenthesisDepth 58
1425#define FxMaxSubexpressionDepth 200
1426#define FxReturn(value) \
1428 subexpression=DestroyString(subexpression); \
1431#define FxParseConditional(subexpression,sentinal,p,q) \
1434 for (q=(char *) p; (*q != (sentinal)) && (*q != '\0'); q++) \
1437 for (q++; (*q != ')') && (*q != '\0'); q++); \
1443 (void) ThrowMagickException(exception,GetMagickModule(), \
1444 OptionError,"UnableToParseExpression","`%s'",subexpression); \
1447 if (strlen(q) == 1) \
1467 subexpression=AcquireString(expression);
1468 *subexpression=
'\0';
1469 if (depth > FxMaxSubexpressionDepth)
1471 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1472 "UnableToParseExpression",
"`%s'",expression);
1475 if (exception->severity >= ErrorException)
1477 while (isspace((
int) ((
unsigned char) *expression)) != 0)
1479 if (*expression ==
'\0')
1481 p=FxOperatorPrecedence(expression,exception);
1482 if (p != (
const char *) NULL)
1484 (void) CopyMagickString(subexpression,expression,(
size_t)
1486 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,subexpression,depth+1,
1488 switch ((
unsigned char) *p)
1492 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1494 *beta=(double) (~CastDoubleToSizeT(*beta));
1499 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1501 FxReturn(*beta == 0.0 ? 1.0 : 0.0);
1505 *beta=pow(alpha,FxEvaluateSubexpression(fx_info,channel,x,y,++p,
1506 depth+1,beta,exception));
1510 case ExponentialNotation:
1512 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1514 FxReturn(alpha*(*beta));
1518 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1520 FxReturn(alpha/(*beta));
1524 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1526 FxReturn(fmod(alpha,*beta));
1530 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1532 FxReturn(alpha+(*beta));
1536 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1538 FxReturn(alpha-(*beta));
1540 case BitwiseAndAssignmentOperator:
1543 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1547 (void) ThrowMagickException(exception,GetMagickModule(),
1548 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1551 ClearMagickException(exception);
1552 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1554 value=(double) (CastDoubleToSizeT(alpha+0.5) & CastDoubleToSizeT(*beta+0.5));
1555 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1559 case BitwiseOrAssignmentOperator:
1562 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1566 (void) ThrowMagickException(exception,GetMagickModule(),
1567 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1570 ClearMagickException(exception);
1571 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1573 value=(double) (CastDoubleToSizeT(alpha+0.5) |
1574 CastDoubleToSizeT(*beta+0.5));
1575 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1579 case LeftShiftAssignmentOperator:
1582 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1586 (void) ThrowMagickException(exception,GetMagickModule(),
1587 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1590 ClearMagickException(exception);
1591 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1593 if (CastDoubleToSizeT(*beta+0.5) >= (8*
sizeof(
size_t)))
1595 (void) ThrowMagickException(exception,GetMagickModule(),
1596 OptionError,
"ShiftCountOverflow",
"`%s'",subexpression);
1599 value=(double) (CastDoubleToSizeT(alpha+0.5) <<
1600 CastDoubleToSizeT(*beta+0.5));
1601 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1605 case RightShiftAssignmentOperator:
1608 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1612 (void) ThrowMagickException(exception,GetMagickModule(),
1613 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1616 ClearMagickException(exception);
1617 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1619 if (CastDoubleToSizeT(*beta+0.5) >= (8*
sizeof(
size_t)))
1621 (void) ThrowMagickException(exception,GetMagickModule(),
1622 OptionError,
"ShiftCountOverflow",
"`%s'",subexpression);
1625 value=(double) (CastDoubleToSizeT(alpha+0.5) >>
1626 CastDoubleToSizeT(*beta+0.5));
1627 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1631 case PowerAssignmentOperator:
1634 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1638 (void) ThrowMagickException(exception,GetMagickModule(),
1639 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1642 ClearMagickException(exception);
1643 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1645 value=pow(alpha,*beta);
1646 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1650 case ModuloAssignmentOperator:
1653 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1657 (void) ThrowMagickException(exception,GetMagickModule(),
1658 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1661 ClearMagickException(exception);
1662 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1664 value=fmod(alpha,*beta);
1665 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1669 case PlusAssignmentOperator:
1672 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1676 (void) ThrowMagickException(exception,GetMagickModule(),
1677 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1680 ClearMagickException(exception);
1681 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1683 value=alpha+(*beta);
1684 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1688 case SubtractAssignmentOperator:
1691 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1695 (void) ThrowMagickException(exception,GetMagickModule(),
1696 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1699 ClearMagickException(exception);
1700 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1702 value=alpha-(*beta);
1703 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1707 case MultiplyAssignmentOperator:
1710 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1714 (void) ThrowMagickException(exception,GetMagickModule(),
1715 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1718 ClearMagickException(exception);
1719 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1721 value=alpha*(*beta);
1722 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1726 case DivideAssignmentOperator:
1729 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1733 (void) ThrowMagickException(exception,GetMagickModule(),
1734 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1737 ClearMagickException(exception);
1738 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1740 value=alpha/(*beta);
1741 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1745 case IncrementAssignmentOperator:
1747 if (*subexpression ==
'\0')
1748 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1751 if (*subexpression ==
'\0')
1753 if (SetFxSymbolValue(fx_info,p,value) == MagickFalse)
1757 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1761 case DecrementAssignmentOperator:
1763 if (*subexpression ==
'\0')
1764 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1767 if (*subexpression ==
'\0')
1769 if (SetFxSymbolValue(fx_info,p,value) == MagickFalse)
1773 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1777 case LeftShiftOperator:
1779 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1781 if (CastDoubleToSizeT(gamma+0.5) >= (8*
sizeof(
size_t)))
1783 (void) ThrowMagickException(exception,GetMagickModule(),
1784 OptionError,
"ShiftCountOverflow",
"`%s'",subexpression);
1787 *beta=(double) (CastDoubleToSizeT(alpha+0.5) <<
1788 CastDoubleToSizeT(gamma+0.5));
1791 case RightShiftOperator:
1793 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1795 if (CastDoubleToSizeT(gamma+0.5) >= (8*
sizeof(
size_t)))
1797 (void) ThrowMagickException(exception,GetMagickModule(),
1798 OptionError,
"ShiftCountOverflow",
"`%s'",subexpression);
1801 *beta=(double) (CastDoubleToSizeT(alpha+0.5) >> CastDoubleToSizeT(gamma+0.5));
1806 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1808 FxReturn(alpha < *beta ? 1.0 : 0.0);
1810 case LessThanEqualOperator:
1812 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1814 FxReturn(alpha <= *beta ? 1.0 : 0.0);
1818 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1820 FxReturn(alpha > *beta ? 1.0 : 0.0);
1822 case GreaterThanEqualOperator:
1824 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1826 FxReturn(alpha >= *beta ? 1.0 : 0.0);
1830 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1832 FxReturn(fabs(alpha-(*beta)) < MagickEpsilon ? 1.0 : 0.0);
1834 case NotEqualOperator:
1836 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1838 FxReturn(fabs(alpha-(*beta)) >= MagickEpsilon ? 1.0 : 0.0);
1842 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1844 *beta=(double) (CastDoubleToSizeT(alpha+0.5) & CastDoubleToSizeT(gamma+0.5));
1849 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1851 *beta=(double) (CastDoubleToSizeT(alpha+0.5) | CastDoubleToSizeT(gamma+0.5));
1854 case LogicalAndOperator:
1862 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,beta,
1864 *beta=(gamma > 0.0) ? 1.0 : 0.0;
1867 case LogicalOrOperator:
1875 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,beta,
1877 *beta=(gamma > 0.0) ? 1.0 : 0.0;
1885 (void) CopyMagickString(subexpression,++p,MaxTextExtent-1);
1886 FxParseConditional(subexpression,
':',p,q);
1887 if (fabs(alpha) >= MagickEpsilon)
1888 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,beta,
1891 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,q+1,depth+1,beta,
1898 while (isalpha((
int) ((
unsigned char) *q)) != 0)
1902 (void) ThrowMagickException(exception,GetMagickModule(),
1903 OptionError,
"UnableToParseExpression",
"`%s'",subexpression);
1906 ClearMagickException(exception);
1907 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1910 if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse)
1916 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1922 *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta,
1930 gamma=alpha*FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,
1936 if (strchr(
"(",(
int) *expression) != (
char *) NULL)
1941 if (depth >= FxMaxParenthesisDepth)
1942 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1943 "ParenthesisNestedTooDeeply",
"`%s'",expression);
1944 length=CopyMagickString(subexpression,expression+1,MaxTextExtent);
1946 subexpression[length-1]=
'\0';
1947 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,subexpression,depth+1,
1951 switch (*expression)
1955 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,expression+1,depth+1,
1957 FxReturn(1.0*gamma);
1961 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,expression+1,depth+1,
1963 FxReturn(-1.0*gamma);
1967 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,expression+1,depth+1,
1969 FxReturn((
double) (~CastDoubleToSizeT(gamma+0.5)));
1974 if (IsFxFunction(expression,
"abs",3) != MagickFalse)
1976 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
1977 depth+1,beta,exception);
1978 FxReturn(fabs(alpha));
1980#if defined(MAGICKCORE_HAVE_ACOSH)
1981 if (IsFxFunction(expression,
"acosh",5) != MagickFalse)
1983 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
1984 depth+1,beta,exception);
1985 FxReturn(acosh(alpha));
1988 if (IsFxFunction(expression,
"acos",4) != MagickFalse)
1990 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
1991 depth+1,beta,exception);
1992 FxReturn(acos(alpha));
1994#if defined(MAGICKCORE_HAVE_J1)
1995 if (IsFxFunction(expression,
"airy",4) != MagickFalse)
1997 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
1998 depth+1,beta,exception);
2001 gamma=2.0*j1((MagickPI*alpha))/(MagickPI*alpha);
2002 FxReturn(gamma*gamma);
2005#if defined(MAGICKCORE_HAVE_ASINH)
2006 if (IsFxFunction(expression,
"asinh",5) != MagickFalse)
2008 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2009 depth+1,beta,exception);
2010 FxReturn(asinh(alpha));
2013 if (IsFxFunction(expression,
"asin",4) != MagickFalse)
2015 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2016 depth+1,beta,exception);
2017 FxReturn(asin(alpha));
2019 if (IsFxFunction(expression,
"alt",3) != MagickFalse)
2021 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2022 depth+1,beta,exception);
2023 FxReturn(((ssize_t) alpha) & 0x01 ? -1.0 : 1.0);
2025 if (IsFxFunction(expression,
"atan2",5) != MagickFalse)
2027 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2028 depth+1,beta,exception);
2029 FxReturn(atan2(alpha,*beta));
2031#if defined(MAGICKCORE_HAVE_ATANH)
2032 if (IsFxFunction(expression,
"atanh",5) != MagickFalse)
2034 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2035 depth+1,beta,exception);
2036 FxReturn(atanh(alpha));
2039 if (IsFxFunction(expression,
"atan",4) != MagickFalse)
2041 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2042 depth+1,beta,exception);
2043 FxReturn(atan(alpha));
2045 if (LocaleCompare(expression,
"a") == 0)
2046 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2052 if (LocaleCompare(expression,
"b") == 0)
2053 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2059 if (IsFxFunction(expression,
"ceil",4) != MagickFalse)
2061 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2062 depth+1,beta,exception);
2063 FxReturn(ceil(alpha));
2065 if (IsFxFunction(expression,
"clamp",5) != MagickFalse)
2067 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2068 depth+1,beta,exception);
2075 if (IsFxFunction(expression,
"cosh",4) != MagickFalse)
2077 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2078 depth+1,beta,exception);
2079 FxReturn(cosh(alpha));
2081 if (IsFxFunction(expression,
"cos",3) != MagickFalse)
2083 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2084 depth+1,beta,exception);
2085 FxReturn(cos(alpha));
2087 if (LocaleCompare(expression,
"c") == 0)
2088 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2094 if (IsFxFunction(expression,
"debug",5) != MagickFalse)
2102 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2103 depth+1,beta,exception);
2104 switch (fx_info->images->colorspace)
2106 case CMYKColorspace:
2110 case CyanChannel: type=
"cyan";
break;
2111 case MagentaChannel: type=
"magenta";
break;
2112 case YellowChannel: type=
"yellow";
break;
2113 case AlphaChannel: type=
"alpha";
break;
2114 case BlackChannel: type=
"black";
break;
2115 default: type=
"unknown";
break;
2119 case GRAYColorspace:
2123 case RedChannel: type=
"gray";
break;
2124 case AlphaChannel: type=
"alpha";
break;
2125 default: type=
"unknown";
break;
2133 case RedChannel: type=
"red";
break;
2134 case GreenChannel: type=
"green";
break;
2135 case BlueChannel: type=
"blue";
break;
2136 case AlphaChannel: type=
"alpha";
break;
2137 default: type=
"unknown";
break;
2142 *subexpression=
'\0';
2144 if (strlen(expression) > 6)
2145 length=CopyMagickString(subexpression,expression+6,MaxTextExtent);
2147 subexpression[length-1]=
'\0';
2148 if (fx_info->file != (FILE *) NULL)
2149 (void) FormatLocaleFile(fx_info->file,
2150 "%s[%.20g,%.20g].%s: %s=%.*g\n",fx_info->images->filename,
2151 (
double) x,(
double) y,type,subexpression,GetMagickPrecision(),
2155 if (IsFxFunction(expression,
"do",2) != MagickFalse)
2163 length=CopyMagickString(subexpression,expression+6,
2164 MagickPathExtent-1);
2166 subexpression[length-1]=
'\0';
2167 FxParseConditional(subexpression,
',',p,q);
2170 if (IsImageTTLExpired(fx_info->images) != MagickFalse)
2171 (void) ThrowMagickException(exception,GetMagickModule(),
2172 ResourceLimitFatalError,
"TimeLimitExceeded",
"`%s'",
2173 fx_info->images->filename);
2174 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,q+1,depth+1,beta,
2176 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,&sans,
2178 if (fabs(gamma) < MagickEpsilon)
2183 if (IsFxFunction(expression,
"drc",3) != MagickFalse)
2185 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2186 depth+1,beta,exception);
2187 FxReturn(alpha/(*beta*(alpha-1.0)+1.0));
2194 if (LocaleCompare(expression,
"epsilon") == 0)
2195 FxReturn(MagickEpsilon);
2196#if defined(MAGICKCORE_HAVE_ERF)
2197 if (IsFxFunction(expression,
"erf",3) != MagickFalse)
2199 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2200 depth+1,beta,exception);
2201 FxReturn(erf(alpha));
2204 if (IsFxFunction(expression,
"exp",3) != MagickFalse)
2206 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2207 depth+1,beta,exception);
2208 FxReturn(exp(alpha));
2210 if (LocaleCompare(expression,
"e") == 0)
2211 FxReturn(2.7182818284590452354);
2217 if (IsFxFunction(expression,
"floor",5) != MagickFalse)
2219 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2220 depth+1,beta,exception);
2221 FxReturn(floor(alpha));
2223 if (IsFxFunction(expression,
"for",3) != MagickFalse)
2234 length=CopyMagickString(subexpression,expression+4,
2235 MagickPathExtent-1);
2237 subexpression[length-1]=
'\0';
2238 FxParseConditional(subexpression,
',',p,q);
2239 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,&sans,
2241 (void) CopyMagickString(subexpression,q+1,MagickPathExtent-1);
2242 FxParseConditional(subexpression,
',',p,q);
2245 if (IsImageTTLExpired(fx_info->images) != MagickFalse)
2246 (void) ThrowMagickException(exception,GetMagickModule(),
2247 ResourceLimitFatalError,
"TimeLimitExceeded",
"`%s'",
2248 fx_info->images->filename);
2249 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,&sans,
2251 if (fabs(gamma) < MagickEpsilon)
2253 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,q+1,depth+1,beta,
2263 if (IsFxFunction(expression,
"gauss",5) != MagickFalse)
2265 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2266 depth+1,beta,exception);
2267 FxReturn(exp((-alpha*alpha/2.0))/sqrt(2.0*MagickPI));
2269 if (IsFxFunction(expression,
"gcd",3) != MagickFalse)
2274 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2275 depth+1,beta,exception);
2278 gcd=FxGCD(alpha,*beta,0);
2281 if (LocaleCompare(expression,
"g") == 0)
2282 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2288 if (LocaleCompare(expression,
"h") == 0)
2289 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2290 if (LocaleCompare(expression,
"hue") == 0)
2291 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2292 if (IsFxFunction(expression,
"hypot",5) != MagickFalse)
2294 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2295 depth+1,beta,exception);
2296 FxReturn(hypot(alpha,*beta));
2303 if (LocaleCompare(expression,
"k") == 0)
2304 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2310 if (IsFxFunction(expression,
"if",2) != MagickFalse)
2321 length=CopyMagickString(subexpression,expression+3,
2322 MagickPathExtent-1);
2324 subexpression[length-1]=
'\0';
2325 FxParseConditional(subexpression,
',',p,q);
2326 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,&sans,
2328 (void) CopyMagickString(subexpression,q+1,MagickPathExtent-1);
2329 FxParseConditional(subexpression,
',',p,q);
2330 if (fabs(alpha) >= MagickEpsilon)
2331 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,beta,
2334 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,q+1,depth+1,beta,
2338 if (LocaleCompare(expression,
"intensity") == 0)
2339 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2340 if (IsFxFunction(expression,
"int",3) != MagickFalse)
2342 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2343 depth+1,beta,exception);
2344 FxReturn(floor(alpha));
2346 if (IsFxFunction(expression,
"isnan",5) != MagickFalse)
2348 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2349 depth+1,beta,exception);
2350 FxReturn((
double) !!IsNaN(alpha));
2352 if (LocaleCompare(expression,
"i") == 0)
2353 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2359 if (LocaleCompare(expression,
"j") == 0)
2360 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2361#if defined(MAGICKCORE_HAVE_J0)
2362 if (IsFxFunction(expression,
"j0",2) != MagickFalse)
2364 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+2,
2365 depth+1,beta,exception);
2366 FxReturn(j0(alpha));
2369#if defined(MAGICKCORE_HAVE_J1)
2370 if (IsFxFunction(expression,
"j1",2) != MagickFalse)
2372 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+2,
2373 depth+1,beta,exception);
2374 FxReturn(j1(alpha));
2377#if defined(MAGICKCORE_HAVE_J1)
2378 if (IsFxFunction(expression,
"jinc",4) != MagickFalse)
2380 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2381 depth+1,beta,exception);
2384 FxReturn((2.0*j1((MagickPI*alpha))/(MagickPI*alpha)));
2392 if (IsFxFunction(expression,
"ln",2) != MagickFalse)
2394 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+2,
2395 depth+1,beta,exception);
2396 FxReturn(log(alpha));
2398 if (IsFxFunction(expression,
"logtwo",6) != MagickFalse)
2400 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+6,
2401 depth+1,beta,exception);
2402 FxReturn(log10(alpha)/log10(2.0));
2404 if (IsFxFunction(expression,
"log",3) != MagickFalse)
2406 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2407 depth+1,beta,exception);
2408 FxReturn(log10(alpha));
2410 if (LocaleCompare(expression,
"lightness") == 0)
2411 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2417 if (LocaleCompare(expression,
"MaxRGB") == 0)
2418 FxReturn((
double) QuantumRange);
2419 if (LocaleNCompare(expression,
"maxima",6) == 0)
2421 if (IsFxFunction(expression,
"max",3) != MagickFalse)
2423 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2424 depth+1,beta,exception);
2425 FxReturn(alpha > *beta ? alpha : *beta);
2427 if (LocaleNCompare(expression,
"minima",6) == 0)
2429 if (IsFxFunction(expression,
"min",3) != MagickFalse)
2431 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2432 depth+1,beta,exception);
2433 FxReturn(alpha < *beta ? alpha : *beta);
2435 if (IsFxFunction(expression,
"mod",3) != MagickFalse)
2437 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2438 depth+1,beta,exception);
2441 FxReturn(alpha-floor((
double) (alpha/(*beta))*(*beta)));
2443 if (LocaleCompare(expression,
"m") == 0)
2444 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2450 if (IsFxFunction(expression,
"not",3) != MagickFalse)
2452 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2453 depth+1,beta,exception);
2454 FxReturn((
double) (alpha < MagickEpsilon));
2456 if (LocaleCompare(expression,
"n") == 0)
2457 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2463 if (LocaleCompare(expression,
"Opaque") == 0)
2465 if (LocaleCompare(expression,
"o") == 0)
2466 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2472 if (LocaleCompare(expression,
"phi") == 0)
2473 FxReturn(MagickPHI);
2474 if (LocaleCompare(expression,
"pi") == 0)
2476 if (IsFxFunction(expression,
"pow",3) != MagickFalse)
2478 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2479 depth+1,beta,exception);
2480 FxReturn(pow(alpha,*beta));
2482 if (LocaleCompare(expression,
"p") == 0)
2483 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2489 if (LocaleCompare(expression,
"QuantumRange") == 0)
2490 FxReturn((
double) QuantumRange);
2491 if (LocaleCompare(expression,
"QuantumScale") == 0)
2492 FxReturn(QuantumScale);
2498 if (IsFxFunction(expression,
"rand",4) != MagickFalse)
2503#if defined(MAGICKCORE_OPENMP_SUPPORT)
2504 #pragma omp critical (MagickCore_FxEvaluateSubexpression)
2506 alpha=GetPseudoRandomValue(fx_info->random_info);
2509 if (IsFxFunction(expression,
"round",5) != MagickFalse)
2511 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2512 depth+1,beta,exception);
2513 if ((alpha-floor(alpha)) < (ceil(alpha)-alpha))
2514 FxReturn(floor(alpha));
2515 FxReturn(ceil(alpha));
2517 if (LocaleCompare(expression,
"r") == 0)
2518 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2524 if (LocaleCompare(expression,
"saturation") == 0)
2525 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2526 if (IsFxFunction(expression,
"sign",4) != MagickFalse)
2528 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2529 depth+1,beta,exception);
2530 FxReturn(alpha < 0.0 ? -1.0 : 1.0);
2532 if (IsFxFunction(expression,
"sinc",4) != MagickFalse)
2534 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2535 depth+1,beta,exception);
2538 FxReturn(sin((MagickPI*alpha))/(MagickPI*alpha));
2540 if (IsFxFunction(expression,
"sinh",4) != MagickFalse)
2542 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2543 depth+1,beta,exception);
2544 FxReturn(sinh(alpha));
2546 if (IsFxFunction(expression,
"sin",3) != MagickFalse)
2548 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2549 depth+1,beta,exception);
2550 FxReturn(sin(alpha));
2552 if (IsFxFunction(expression,
"sqrt",4) != MagickFalse)
2554 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2555 depth+1,beta,exception);
2556 FxReturn(sqrt(alpha));
2558 if (IsFxFunction(expression,
"squish",6) != MagickFalse)
2560 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+6,
2561 depth+1,beta,exception);
2562 FxReturn((1.0/(1.0+exp(-alpha))));
2564 if (LocaleCompare(expression,
"s") == 0)
2565 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2571 if (IsFxFunction(expression,
"tanh",4) != MagickFalse)
2573 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,
2574 depth+1,beta,exception);
2575 FxReturn(tanh(alpha));
2577 if (IsFxFunction(expression,
"tan",3) != MagickFalse)
2579 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+3,
2580 depth+1,beta,exception);
2581 FxReturn(tan(alpha));
2583 if (LocaleCompare(expression,
"Transparent") == 0)
2585 if (IsFxFunction(expression,
"trunc",5) != MagickFalse)
2587 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+5,
2588 depth+1,beta,exception);
2590 FxReturn(floor(alpha));
2591 FxReturn(ceil(alpha));
2593 if (LocaleCompare(expression,
"t") == 0)
2594 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2600 if (LocaleCompare(expression,
"u") == 0)
2601 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2607 if (LocaleCompare(expression,
"v") == 0)
2608 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2614 if (IsFxFunction(expression,
"while",5) != MagickFalse)
2622 length=CopyMagickString(subexpression,expression+6,
2623 MagickPathExtent-1);
2625 subexpression[length-1]=
'\0';
2626 FxParseConditional(subexpression,
',',p,q);
2629 if (IsImageTTLExpired(fx_info->images) != MagickFalse)
2630 (void) ThrowMagickException(exception,GetMagickModule(),
2631 ResourceLimitFatalError,
"TimeLimitExceeded",
"`%s'",
2632 fx_info->images->filename);
2633 gamma=FxEvaluateSubexpression(fx_info,channel,x,y,p,depth+1,beta,
2635 if (fabs(gamma) < MagickEpsilon)
2637 alpha=FxEvaluateSubexpression(fx_info,channel,x,y,q+1,depth+1,beta,
2642 if (LocaleCompare(expression,
"w") == 0)
2643 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2649 if (LocaleCompare(expression,
"y") == 0)
2650 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2656 if (LocaleCompare(expression,
"z") == 0)
2657 FxReturn(FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception));
2663 q=(
char *) expression;
2664 alpha=InterpretSiPrefixValue(expression,&q);
2665 if (q == expression)
2666 alpha=FxGetSymbol(fx_info,channel,x,y,expression,depth+1,exception);
2668 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2669 "UnbalancedParenthesis",
"`%s'",expression);
2673MagickExport MagickBooleanType FxEvaluateExpression(FxInfo *fx_info,
2674 double *alpha,ExceptionInfo *exception)
2679 status=FxEvaluateChannelExpression(fx_info,GrayChannel,0,0,alpha,exception);
2683MagickExport MagickBooleanType FxPreprocessExpression(FxInfo *fx_info,
2684 double *alpha,ExceptionInfo *exception)
2693 fx_info->file=(FILE *) NULL;
2694 status=FxEvaluateChannelExpression(fx_info,GrayChannel,0,0,alpha,exception);
2699MagickExport MagickBooleanType FxEvaluateChannelExpression(FxInfo *fx_info,
2700 const ChannelType channel,
const ssize_t x,
const ssize_t y,
double *alpha,
2701 ExceptionInfo *exception)
2707 *alpha=FxEvaluateSubexpression(fx_info,channel,x,y,fx_info->expression,0,
2709 return(exception->severity == OptionError ? MagickFalse : MagickTrue);
2744static FxInfo **DestroyFxTLS(FxInfo **fx_info)
2749 assert(fx_info != (FxInfo **) NULL);
2750 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
2751 if (fx_info[i] != (FxInfo *) NULL)
2752 fx_info[i]=DestroyFxInfo(fx_info[i]);
2753 fx_info=(FxInfo **) RelinquishMagickMemory(fx_info);
2757static FxInfo **AcquireFxTLS(
const Image *image,
const char *expression,
2758 ExceptionInfo *exception)
2775 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
2776 fx_info=(FxInfo **) AcquireQuantumMemory(number_threads,
sizeof(*fx_info));
2777 if (fx_info == (FxInfo **) NULL)
2779 (void) ThrowMagickException(exception,GetMagickModule(),
2780 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",image->filename);
2781 return((FxInfo **) NULL);
2783 (void) memset(fx_info,0,number_threads*
sizeof(*fx_info));
2784 if (*expression !=
'@')
2785 fx_expression=ConstantString(expression);
2787 fx_expression=FileToString(expression,~0UL,exception);
2788 for (i=0; i < (ssize_t) number_threads; i++)
2793 fx_info[i]=AcquireFxInfo(image,fx_expression);
2794 if (fx_info[i] == (FxInfo *) NULL)
2796 status=FxPreprocessExpression(fx_info[i],&alpha,exception);
2797 if (status == MagickFalse)
2800 fx_expression=DestroyString(fx_expression);
2801 if (i < (ssize_t) number_threads)
2802 fx_info=DestroyFxTLS(fx_info);
2806MagickExport Image *FxImage(
const Image *image,
const char *expression,
2807 ExceptionInfo *exception)
2812 fx_image=FxImageChannel(image,GrayChannel,expression,exception);
2816MagickExport Image *FxImageChannel(
const Image *image,
const ChannelType channel,
2817 const char *expression,ExceptionInfo *exception)
2819#define FxImageTag "Fx/Image"
2825 **magick_restrict fx_info;
2839 assert(image != (Image *) NULL);
2840 assert(image->signature == MagickCoreSignature);
2841 if (IsEventLogging() != MagickFalse)
2842 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2843 if (expression == (
const char *) NULL)
2844 return(CloneImage(image,0,0,MagickTrue,exception));
2845 fx_info=AcquireFxTLS(image,expression,exception);
2846 if (fx_info == (FxInfo **) NULL)
2847 return((Image *) NULL);
2848 fx_image=CloneImage(image,0,0,MagickTrue,exception);
2849 if (fx_image == (Image *) NULL)
2851 fx_info=DestroyFxTLS(fx_info);
2852 return((Image *) NULL);
2854 if (SetImageStorageClass(fx_image,DirectClass) == MagickFalse)
2856 InheritException(exception,&fx_image->exception);
2857 fx_info=DestroyFxTLS(fx_info);
2858 fx_image=DestroyImage(fx_image);
2859 return((Image *) NULL);
2866 fx_view=AcquireAuthenticCacheView(fx_image,exception);
2867#if defined(MAGICKCORE_OPENMP_SUPPORT)
2868 #pragma omp parallel for schedule(dynamic) shared(progress,status) \
2869 magick_number_threads(image,fx_image,fx_image->rows, \
2870 GlobExpression(fx_info[0]->expression,"*debug(*",MagickTrue) == 0 ? 1 : 0)
2872 for (y=0; y < (ssize_t) fx_image->rows; y++)
2875 id = GetOpenMPThreadId();
2881 *magick_restrict fx_indexes;
2889 if (status == MagickFalse)
2891 q=GetCacheViewAuthenticPixels(fx_view,0,y,fx_image->columns,1,exception);
2892 if (q == (PixelPacket *) NULL)
2897 fx_indexes=GetCacheViewAuthenticIndexQueue(fx_view);
2899 for (x=0; x < (ssize_t) fx_image->columns; x++)
2901 if ((channel & RedChannel) != 0)
2903 (void) FxEvaluateChannelExpression(fx_info[
id],RedChannel,x,y,
2905 SetPixelRed(q,ClampToQuantum((MagickRealType) QuantumRange*alpha));
2907 if ((channel & GreenChannel) != 0)
2909 (void) FxEvaluateChannelExpression(fx_info[
id],GreenChannel,x,y,
2911 SetPixelGreen(q,ClampToQuantum((MagickRealType) QuantumRange*alpha));
2913 if ((channel & BlueChannel) != 0)
2915 (void) FxEvaluateChannelExpression(fx_info[
id],BlueChannel,x,y,
2917 SetPixelBlue(q,ClampToQuantum((MagickRealType) QuantumRange*alpha));
2919 if ((channel & OpacityChannel) != 0)
2921 (void) FxEvaluateChannelExpression(fx_info[
id],OpacityChannel,x,y,
2923 if (image->matte == MagickFalse)
2924 SetPixelOpacity(q,ClampToQuantum((MagickRealType) QuantumRange*
2927 SetPixelOpacity(q,ClampToQuantum((MagickRealType) QuantumRange-
2928 (MagickRealType) QuantumRange*alpha));
2930 if (((channel & IndexChannel) != 0) &&
2931 (fx_image->colorspace == CMYKColorspace))
2933 (void) FxEvaluateChannelExpression(fx_info[
id],IndexChannel,x,y,
2935 SetPixelIndex(fx_indexes+x,ClampToQuantum((MagickRealType)
2936 QuantumRange*alpha));
2940 if (SyncCacheViewAuthenticPixels(fx_view,exception) == MagickFalse)
2942 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2947#if defined(MAGICKCORE_OPENMP_SUPPORT)
2951 proceed=SetImageProgress(image,FxImageTag,progress,image->rows);
2952 if (proceed == MagickFalse)
2956 fx_view=DestroyCacheView(fx_view);
2957 fx_info=DestroyFxTLS(fx_info);
2958 if (status == MagickFalse)
2959 fx_image=DestroyImage(fx_image);