blob: 25dff3501da886f3ce99a372e3428f8d93ccd8e3 [file] [log] [blame]
anthony805a2d42011-09-25 08:25:12 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
anthony8b10b462012-02-08 12:32:44 +00006% OOO PPPP EEEE RRRR AA TTTTT III OOO N N %
7% O O P P E R R A A T I O O NN N %
8% O O PPPP EEE RRRR AAAA T I O O N N N %
9% O O P E R R A A T I O O N NN %
10% OOO P EEEE R RR A A T III OOO N N %
anthony805a2d42011-09-25 08:25:12 +000011% %
12% %
anthony8b10b462012-02-08 12:32:44 +000013% CLI Magick Option Methods %
anthony805a2d42011-09-25 08:25:12 +000014% %
anthony8b10b462012-02-08 12:32:44 +000015% Dragon Computing %
cristy9e58efd2012-01-30 14:27:34 +000016% Anthony Thyssen %
cristy0a0ca4f2011-09-28 01:15:28 +000017% September 2011 %
anthony805a2d42011-09-25 08:25:12 +000018% %
19% %
cristyfe676ee2013-11-18 13:03:38 +000020% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
anthony805a2d42011-09-25 08:25:12 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% Apply the given options (settings, and simple, or sequence operations) to
anthony8b10b462012-02-08 12:32:44 +000037% the given image(s) according to the current "image_info", "draw_info", and
38% "quantize_info" settings, stored in a special CLI Image Wand.
anthony805a2d42011-09-25 08:25:12 +000039%
40% The final goal is to allow the execution in a strict one option at a time
41% manner that is needed for 'pipelining and file scripting' of options in
42% IMv7.
43%
anthony8b10b462012-02-08 12:32:44 +000044% Anthony Thyssen, September 2011
anthony805a2d42011-09-25 08:25:12 +000045*/
46
47/*
48 Include declarations.
49*/
50#include "MagickWand/studio.h"
51#include "MagickWand/MagickWand.h"
anthony72feaa62012-01-17 06:46:23 +000052#include "MagickWand/magick-wand-private.h"
cristyd7df81d2014-01-18 18:42:05 +000053#include "MagickWand/mogrify.h"
anthony43f425d2012-02-26 12:58:58 +000054#include "MagickWand/wand.h"
anthony756cd0d2012-04-08 12:41:44 +000055#include "MagickWand/wandcli.h"
56#include "MagickWand/wandcli-private.h"
cristye66172d2014-01-15 20:23:01 +000057#include "MagickCore/image-private.h"
anthony805a2d42011-09-25 08:25:12 +000058#include "MagickCore/monitor-private.h"
cristye66172d2014-01-15 20:23:01 +000059#include "MagickWand/operation.h"
anthony805a2d42011-09-25 08:25:12 +000060#include "MagickCore/thread-private.h"
61#include "MagickCore/string-private.h"
anthony7a4d6102012-07-01 09:48:25 +000062#include "MagickCore/pixel-private.h"
anthony805a2d42011-09-25 08:25:12 +000063
64/*
cristyd7df81d2014-01-18 18:42:05 +000065 Constant declaration.
66*/
67static const char
68 MogrifyBackgroundColor[] = "#fff", /* white */
69 MogrifyBorderColor[] = "#dfdfdf", /* sRGB gray */
70 MogrifyMatteColor[] = "#bdbdbd"; /* slightly darker gray */
71
72/*
anthony805a2d42011-09-25 08:25:12 +000073 Define declarations.
74*/
anthonyc7994672012-11-17 05:33:27 +000075#define USE_WAND_METHODS 1
anthonyafa3dfc2012-03-03 11:31:30 +000076#define MAX_STACK_DEPTH 32
77#define UNDEFINED_COMPRESSION_QUALITY 0UL
78
anthonyb1d483a2012-04-14 12:53:56 +000079/* FUTURE: why is this default so specific? */
80#define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
81
anthony22de2722012-04-19 14:43:00 +000082/* For Debugging Geometry Input */
83#define ReportGeometry(flags,info) \
84 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
85 flags, info.rho, info.sigma, info.xi, info.psi )
anthony805a2d42011-09-25 08:25:12 +000086
87/*
88** Function to report on the progress of image operations
89*/
90static MagickBooleanType MonitorProgress(const char *text,
91 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000092 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000093{
94 char
95 message[MaxTextExtent],
96 tag[MaxTextExtent];
97
98 const char
99 *locale_message;
100
101 register char
102 *p;
103
104 if (extent < 2)
105 return(MagickTrue);
106 (void) CopyMagickMemory(tag,text,MaxTextExtent);
107 p=strrchr(tag,'/');
108 if (p != (char *) NULL)
109 *p='\0';
110 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
111 locale_message=GetLocaleMessage(message);
112 if (locale_message == message)
113 locale_message=tag;
114 if (p == (char *) NULL)
115 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
116 locale_message,(long) offset,(unsigned long) extent,(long)
117 (100L*offset/(extent-1)));
118 else
119 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
120 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
121 (100L*offset/(extent-1)));
122 if (offset == (MagickOffsetType) (extent-1))
123 (void) FormatLocaleFile(stderr,"\n");
124 (void) fflush(stderr);
125 return(MagickTrue);
126}
127
128/*
129** GetImageCache() will read an image into a image cache if not already
130** present then return the image that is in the cache under that filename.
131*/
132static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
133 ExceptionInfo *exception)
134{
135 char
136 key[MaxTextExtent];
137
138 ExceptionInfo
139 *sans_exception;
140
141 Image
142 *image;
143
144 ImageInfo
145 *read_info;
146
147 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
148 sans_exception=AcquireExceptionInfo();
149 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
150 sans_exception=DestroyExceptionInfo(sans_exception);
151 if (image != (Image *) NULL)
152 return(image);
153 read_info=CloneImageInfo(image_info);
cristy4d246fc2014-01-15 22:33:44 +0000154 if (path != (const char *) NULL)
155 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
anthony805a2d42011-09-25 08:25:12 +0000156 image=ReadImage(read_info,exception);
157 read_info=DestroyImageInfo(read_info);
158 if (image != (Image *) NULL)
159 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
160 return(image);
161}
162
anthony756cd0d2012-04-08 12:41:44 +0000163/*
anthonya89dd172011-10-04 13:29:35 +0000164 SparseColorOption() parse the complex -sparse-color argument into an
165 an array of floating point values than call SparseColorImage().
166 Argument is a complex mix of floating-point pixel coodinates, and color
167 specifications (or direct floating point numbers). The number of floats
anthony4023b262013-06-03 07:43:50 +0000168 needed to represent a color varies depending on the current channel
anthonya89dd172011-10-04 13:29:35 +0000169 setting.
anthony43f425d2012-02-26 12:58:58 +0000170
171 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000172*/
173static Image *SparseColorOption(const Image *image,
cristyab943592013-03-29 16:47:23 +0000174 const SparseColorMethod method,const char *arguments,ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000175{
176 char
177 token[MaxTextExtent];
178
179 const char
180 *p;
181
182 double
183 *sparse_arguments;
184
185 Image
186 *sparse_image;
187
188 PixelInfo
189 color;
190
191 MagickBooleanType
192 error;
193
194 register size_t
195 x;
196
197 size_t
198 number_arguments,
199 number_colors;
200
201 assert(image != (Image *) NULL);
202 assert(image->signature == MagickSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000203 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000204 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
205 assert(exception != (ExceptionInfo *) NULL);
206 assert(exception->signature == MagickSignature);
207 /*
anthonyb1d483a2012-04-14 12:53:56 +0000208 Limit channels according to image
209 add up number of values needed per color.
anthony805a2d42011-09-25 08:25:12 +0000210 */
211 number_colors=0;
212 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
213 number_colors++;
214 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
215 number_colors++;
216 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
217 number_colors++;
218 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
219 (image->colorspace == CMYKColorspace))
220 number_colors++;
221 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000222 image->alpha_trait == BlendPixelTrait)
anthony805a2d42011-09-25 08:25:12 +0000223 number_colors++;
224
225 /*
226 Read string, to determine number of arguments needed,
227 */
228 p=arguments;
229 x=0;
230 while( *p != '\0' )
231 {
232 GetMagickToken(p,&p,token);
233 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000234 if ( isalpha((int) token[0]) || token[0] == '#' )
235 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000236 else
anthony805a2d42011-09-25 08:25:12 +0000237 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000238 }
anthony31f1bf72012-01-30 12:37:22 +0000239 /* control points and color values */
anthony7bcfe7f2012-03-30 14:01:22 +0000240 error = IsMagickTrue( x % (2+number_colors) );
anthony31f1bf72012-01-30 12:37:22 +0000241 number_arguments=x;
anthony7bcfe7f2012-03-30 14:01:22 +0000242 if ( IfMagickTrue(error) ) {
anthony805a2d42011-09-25 08:25:12 +0000243 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000244 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000245 "Invalid number of Arguments");
246 return( (Image *)NULL);
247 }
248
249 /* Allocate and fill in the floating point arguments */
250 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
251 sizeof(*sparse_arguments));
252 if (sparse_arguments == (double *) NULL) {
253 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
254 "MemoryAllocationFailed","%s","SparseColorOption");
255 return( (Image *)NULL);
256 }
257 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
258 sizeof(*sparse_arguments));
259 p=arguments;
260 x=0;
261 while( *p != '\0' && x < number_arguments ) {
262 /* X coordinate */
263 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
264 if ( token[0] == '\0' ) break;
265 if ( isalpha((int) token[0]) || token[0] == '#' ) {
266 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000267 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000268 "Color found, instead of X-coord");
269 error = MagickTrue;
270 break;
271 }
cristydbdd0e32011-11-04 23:29:40 +0000272 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000273 /* Y coordinate */
274 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
275 if ( token[0] == '\0' ) break;
276 if ( isalpha((int) token[0]) || token[0] == '#' ) {
277 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000278 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000279 "Color found, instead of Y-coord");
280 error = MagickTrue;
281 break;
282 }
cristydbdd0e32011-11-04 23:29:40 +0000283 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000284 /* color name or function given in string argument */
285 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
286 if ( token[0] == '\0' ) break;
287 if ( isalpha((int) token[0]) || token[0] == '#' ) {
288 /* Color string given */
289 (void) QueryColorCompliance(token,AllCompliance,&color,
290 exception);
291 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
292 sparse_arguments[x++] = QuantumScale*color.red;
293 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
294 sparse_arguments[x++] = QuantumScale*color.green;
295 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
296 sparse_arguments[x++] = QuantumScale*color.blue;
297 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
298 (image->colorspace == CMYKColorspace))
299 sparse_arguments[x++] = QuantumScale*color.black;
300 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000301 image->alpha_trait == BlendPixelTrait)
anthony31f1bf72012-01-30 12:37:22 +0000302 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000303 }
anthony31f1bf72012-01-30 12:37:22 +0000304 else {
305 /* Colors given as a set of floating point values - experimental */
306 /* NB: token contains the first floating point value to use! */
307 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
308 {
309 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
310 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
311 break;
312 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
313 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000314 }
anthony31f1bf72012-01-30 12:37:22 +0000315 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
316 {
317 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
318 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
319 break;
320 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
321 token[0] = ','; /* used this token - get another */
322 }
323 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
324 {
325 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
326 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
327 break;
328 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
329 token[0] = ','; /* used this token - get another */
330 }
331 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
332 (image->colorspace == CMYKColorspace))
333 {
334 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
335 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
336 break;
337 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
338 token[0] = ','; /* used this token - get another */
339 }
340 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000341 image->alpha_trait == BlendPixelTrait)
anthony31f1bf72012-01-30 12:37:22 +0000342 {
343 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
344 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
345 break;
346 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
347 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000348 }
349 }
350 }
351 if ( number_arguments != x && !error ) {
352 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000353 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000354 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
355 return( (Image *)NULL);
356 }
357 if ( error )
358 return( (Image *)NULL);
359
anthony31f1bf72012-01-30 12:37:22 +0000360 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000361 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
362 exception);
363 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
364 return( sparse_image );
365}
366
367/*
368%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369% %
370% %
371% %
anthony464f1c42012-04-22 08:51:01 +0000372% C L I S e t t i n g O p t i o n I n f o %
anthony43f425d2012-02-26 12:58:58 +0000373% %
374% %
375% %
376%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
377%
378% CLISettingOptionInfo() applies a single settings option into a CLI wand
379% holding the image_info, draw_info, quantize_info structures that will be
380% used when processing the images.
381%
382% These options do no require images to be present in the CLI wand for them
383% to be able to be set, in which case they will generally be applied to image
384% that are read in later
anthony80c37752012-01-16 01:03:11 +0000385%
386% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000387% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000388%
anthony2052d272012-02-28 12:48:29 +0000389% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000390%
anthonyafa3dfc2012-03-03 11:31:30 +0000391% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000392% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000393%
394% A description of each parameter follows:
395%
anthony43f425d2012-02-26 12:58:58 +0000396% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000397%
anthonydcf510d2011-10-30 13:51:40 +0000398% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000399%
anthonye5fcd362012-04-09 04:02:09 +0000400% o arg1, arg2: optional argument strings to the operation
401% arg2 is currently only used by "-limit"
anthonydcf510d2011-10-30 13:51:40 +0000402%
anthony805a2d42011-09-25 08:25:12 +0000403*/
cristyfe831852013-02-12 14:56:07 +0000404WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonya322a832013-04-27 06:28:03 +0000405 const char *option,const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +0000406{
anthony30b912a2012-03-22 01:20:28 +0000407 ssize_t
408 parse; /* option argument parsing (string to value table lookup) */
409
anthonya322a832013-04-27 06:28:03 +0000410 const char /* percent escaped versions of the args */
411 *arg1,
412 *arg2;
anthony1afdc7a2011-10-05 11:54:28 +0000413
anthony2e4501b2012-03-30 04:41:54 +0000414#define _image_info (cli_wand->wand.image_info)
anthonya322a832013-04-27 06:28:03 +0000415#define _image (cli_wand->wand.images)
anthony2e4501b2012-03-30 04:41:54 +0000416#define _exception (cli_wand->wand.exception)
417#define _draw_info (cli_wand->draw_info)
418#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000419#define IfSetOption (*option=='-')
anthony7bcfe7f2012-03-30 14:01:22 +0000420#define ArgBoolean IsMagickTrue(IfSetOption)
421#define ArgBooleanNot IsMagickFalse(IfSetOption)
anthony24aa8822012-03-11 00:56:06 +0000422#define ArgBooleanString (IfSetOption?"true":"false")
423#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000424
anthonya322a832013-04-27 06:28:03 +0000425 assert(cli_wand != (MagickCLI *) NULL);
426 assert(cli_wand->signature == WandSignature);
427 assert(cli_wand->wand.signature == WandSignature);
anthony4837ac22012-05-18 23:39:48 +0000428
anthonya322a832013-04-27 06:28:03 +0000429 if (IfMagickTrue(cli_wand->wand.debug))
430 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
431 "- Setting Option: %s \"%s\" \"%s\"", option,arg1n,arg2n);
432
433 arg1 = arg1n,
434 arg2 = arg2n;
435
436#if 1
anthony4837ac22012-05-18 23:39:48 +0000437#define _process_flags (cli_wand->process_flags)
438#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
439 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +0000440 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
441 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
442 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
443 /* Interpret Percent escapes in argument 1 */
444 if (arg1n != (char *) NULL) {
445 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
446 if (arg1 == (char *) NULL) {
447 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
448 arg1=arg1n; /* use the given argument as is */
449 }
450 }
451 if (arg2n != (char *) NULL) {
452 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
453 if (arg2 == (char *) NULL) {
454 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
455 arg2=arg2n; /* use the given argument as is */
456 }
457 }
458 }
459#undef _process_flags
460#undef _option_type
461#endif
462
anthonyafa3dfc2012-03-03 11:31:30 +0000463 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000464 {
465 case 'a':
466 {
anthonyafa3dfc2012-03-03 11:31:30 +0000467 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000468 {
anthony92c93bd2012-03-19 14:02:47 +0000469 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000470 break;
471 }
anthonyafa3dfc2012-03-03 11:31:30 +0000472 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000473 {
anthony464f1c42012-04-22 08:51:01 +0000474 CLIWandWarnReplaced("-draw 'affine ...'");
anthony74b1cfc2011-10-06 12:44:16 +0000475 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000476 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000477 else
anthony92c93bd2012-03-19 14:02:47 +0000478 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000479 break;
480 }
anthonyafa3dfc2012-03-03 11:31:30 +0000481 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000482 {
anthony92c93bd2012-03-19 14:02:47 +0000483 _image_info->antialias =
484 _draw_info->stroke_antialias =
485 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000486 break;
487 }
anthony31f1bf72012-01-30 12:37:22 +0000488 if (LocaleCompare("attenuate",option+1) == 0)
489 {
anthony7bcfe7f2012-03-30 14:01:22 +0000490 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000491 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
492 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000493 break;
494 }
anthonyafa3dfc2012-03-03 11:31:30 +0000495 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000496 {
anthony92c93bd2012-03-19 14:02:47 +0000497 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000498 break;
499 }
anthonyebb73a22012-03-22 14:25:52 +0000500 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000501 }
502 case 'b':
503 {
anthonyafa3dfc2012-03-03 11:31:30 +0000504 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000505 {
anthony92c93bd2012-03-19 14:02:47 +0000506 /* FUTURE: both _image_info attribute & ImageOption in use!
507 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000508 SyncImageSettings() used to set per-image attribute.
509
anthony92c93bd2012-03-19 14:02:47 +0000510 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000511 we should fall back to per-image background_color
512
513 At this time -background will 'wipe out' the per-image
514 background color!
515
516 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000517 */
anthony92c93bd2012-03-19 14:02:47 +0000518 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
cristyd7df81d2014-01-18 18:42:05 +0000519 (void) QueryColorCompliance(ArgOption(MogrifyBackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000520 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000521 break;
522 }
anthonyafa3dfc2012-03-03 11:31:30 +0000523 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000524 {
anthony52bef752012-03-27 13:54:47 +0000525 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000526 as it is actually rarely used except in direct convolve operations
527 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000528
529 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000530 */
anthony7bcfe7f2012-03-30 14:01:22 +0000531 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000532 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000533 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000534 break;
535 }
anthonyafa3dfc2012-03-03 11:31:30 +0000536 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000537 {
anthony72feaa62012-01-17 06:46:23 +0000538 /* Used as a image chromaticity setting
539 SyncImageSettings() used to set per-image attribute.
540 */
anthony92c93bd2012-03-19 14:02:47 +0000541 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000542 break;
543 }
anthonyafa3dfc2012-03-03 11:31:30 +0000544 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000545 {
anthonyafbaed72011-10-26 12:05:04 +0000546 /* Image chromaticity X,Y NB: Y=X if Y not defined
547 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000548 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000549 */
anthonyf42014d2012-03-25 09:53:06 +0000550 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000551 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000552 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000553 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000554 break;
555 }
anthonyafa3dfc2012-03-03 11:31:30 +0000556 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000557 {
anthony92c93bd2012-03-19 14:02:47 +0000558 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000559 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000560 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000561 */
anthony74b1cfc2011-10-06 12:44:16 +0000562 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000563 {
anthony92c93bd2012-03-19 14:02:47 +0000564 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000565 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000566 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000567 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000568 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000569 break;
570 }
anthony92c93bd2012-03-19 14:02:47 +0000571 (void) DeleteImageOption(_image_info,option+1);
cristyd7df81d2014-01-18 18:42:05 +0000572 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000573 &_image_info->border_color,_exception);
cristyd7df81d2014-01-18 18:42:05 +0000574 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000575 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000576 break;
577 }
anthonyafa3dfc2012-03-03 11:31:30 +0000578 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000579 {
anthony464f1c42012-04-22 08:51:01 +0000580 CLIWandWarnReplaced("-undercolor");
anthony975a8d72012-04-12 13:54:36 +0000581 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
anthonyfd706f92012-01-19 04:22:02 +0000582 break;
anthony805a2d42011-09-25 08:25:12 +0000583 }
anthonyebb73a22012-03-22 14:25:52 +0000584 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000585 }
586 case 'c':
587 {
anthonyafa3dfc2012-03-03 11:31:30 +0000588 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000589 {
590 MagickSizeType
591 limit;
592
anthony7bcfe7f2012-03-30 14:01:22 +0000593 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000594 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000595 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000596 if (LocaleCompare("unlimited",arg1) != 0)
597 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000598 (void) SetMagickResourceLimit(MemoryResource,limit);
599 (void) SetMagickResourceLimit(MapResource,2*limit);
600 break;
601 }
anthonyafa3dfc2012-03-03 11:31:30 +0000602 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000603 {
anthony92c93bd2012-03-19 14:02:47 +0000604 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000605 break;
606 }
anthonyafa3dfc2012-03-03 11:31:30 +0000607 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000608 {
anthony4023b262013-06-03 07:43:50 +0000609 parse=ParseChannelOption(ArgOption("Default"));
anthony30b912a2012-03-22 01:20:28 +0000610 if (parse < 0)
611 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
612 option,arg1);
613 _image_info->channel=(ChannelType) parse;
614 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000615 break;
616 }
anthonyafa3dfc2012-03-03 11:31:30 +0000617 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000618 {
anthonyafbaed72011-10-26 12:05:04 +0000619 /* Setting used for new images via AquireImage()
620 But also used as a SimpleImageOperator
621 Undefined colorspace means don't modify images on
622 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000623 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
624 ArgOption("undefined"));
625 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000626 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
627 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000628 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000629 break;
630 }
anthonyafa3dfc2012-03-03 11:31:30 +0000631 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000632 {
anthony92c93bd2012-03-19 14:02:47 +0000633 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000634 break;
635 }
anthonyafa3dfc2012-03-03 11:31:30 +0000636 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000637 {
anthony92c93bd2012-03-19 14:02:47 +0000638 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000639 SyncImageSettings() used to set per-image attribute. - REMOVE
640
anthonyafbaed72011-10-26 12:05:04 +0000641 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000642 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000643 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000644 */
anthonyebb73a22012-03-22 14:25:52 +0000645 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
646 ArgOption("undefined"));
647 if (parse < 0)
648 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
649 option,arg1);
650 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000651 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000652 break;
653 }
anthonyafa3dfc2012-03-03 11:31:30 +0000654 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000655 {
anthony92c93bd2012-03-19 14:02:47 +0000656 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000657 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000658 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000659
anthony92c93bd2012-03-19 14:02:47 +0000660 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000661 however the image attribute (for save) is set from the
662 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000663
664 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000665 */
anthonyebb73a22012-03-22 14:25:52 +0000666 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
667 ArgOption("undefined"));
668 if (parse < 0)
669 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
670 option,arg1);
671 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000672 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000673 break;
674 }
anthonyebb73a22012-03-22 14:25:52 +0000675 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000676 }
677 case 'd':
678 {
anthonyafa3dfc2012-03-03 11:31:30 +0000679 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000680 {
anthony72feaa62012-01-17 06:46:23 +0000681 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000682 arg1=ArgOption("none");
683 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
684 if (parse < 0)
685 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
686 option,arg1);
687 (void) SetLogEventMask(arg1);
688 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000689 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000690 break;
691 }
anthonyafa3dfc2012-03-03 11:31:30 +0000692 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000693 {
anthony24aa8822012-03-11 00:56:06 +0000694 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000695 {
anthony5f867ae2011-10-09 10:28:34 +0000696 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000697 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000698 else
anthony24aa8822012-03-11 00:56:06 +0000699 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000700 break;
701 }
anthony24aa8822012-03-11 00:56:06 +0000702 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000703 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000704 (void) DefineImageOption(_image_info,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +0000705 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000706 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000707 break;
708 }
anthonyafa3dfc2012-03-03 11:31:30 +0000709 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000710 {
anthonyafbaed72011-10-26 12:05:04 +0000711 /* Only used for new images via AcquireImage()
712 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000713 */
anthonyebb73a22012-03-22 14:25:52 +0000714 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000715 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000716 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
717 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000718 break;
719 }
anthonyafa3dfc2012-03-03 11:31:30 +0000720 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000721 {
anthony92c93bd2012-03-19 14:02:47 +0000722 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000723 Basically as density can be in a XxY form!
724
725 SyncImageSettings() used to set per-image attribute.
726 */
anthony7bcfe7f2012-03-30 14:01:22 +0000727 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000728 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000729 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
730 (void) CloneString(&_image_info->density,ArgOption(NULL));
731 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000732 break;
733 }
anthonyafa3dfc2012-03-03 11:31:30 +0000734 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000735 {
anthony72feaa62012-01-17 06:46:23 +0000736 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
737 SyncImageSettings() used to set per-image attribute.
738 */
anthony7bcfe7f2012-03-30 14:01:22 +0000739 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000740 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000741 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000742 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000743 break;
744 }
anthonyafa3dfc2012-03-03 11:31:30 +0000745 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000746 {
anthony92c93bd2012-03-19 14:02:47 +0000747 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000748 arg1=ArgOption("undefined");
749 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
750 if (parse < 0)
751 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
752 option,arg1);
753 _draw_info->direction=(DirectionType) parse;
754 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000755 break;
756 }
anthonyafa3dfc2012-03-03 11:31:30 +0000757 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000758 {
anthony92c93bd2012-03-19 14:02:47 +0000759 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
760 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000761 break;
762 }
anthonyafa3dfc2012-03-03 11:31:30 +0000763 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000764 {
anthony72feaa62012-01-17 06:46:23 +0000765 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000766 arg1=ArgOption("undefined");
767 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
768 if (parse < 0)
769 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
770 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000771 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000772 break;
773 }
anthonyb1d483a2012-04-14 12:53:56 +0000774 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
775 {
776 /* FUTURE: this is only used by CompareImages() which is used
777 only by the "compare" CLI program at this time. */
778 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
779 if (IfMagickFalse(IsGeometry(arg1)))
780 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
781 (void) SetImageOption(_image_info,option+1,arg1);
782 break;
783 }
anthonyafa3dfc2012-03-03 11:31:30 +0000784 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000785 {
anthony92c93bd2012-03-19 14:02:47 +0000786 /* _image_info attr (on/off), _quantize_info attr (on/off)
787 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000788 FUTURE: merge the duality of the dithering options
789 */
cristycbda6112012-05-27 20:57:16 +0000790 _image_info->dither = ArgBoolean;
anthony92c93bd2012-03-19 14:02:47 +0000791 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
792 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
cristycbda6112012-05-27 20:57:16 +0000793 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000794 if (_quantize_info->dither_method == NoDitherMethod)
cristycbda6112012-05-27 20:57:16 +0000795 _image_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000796 break;
797 }
anthonyebb73a22012-03-22 14:25:52 +0000798 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000799 }
800 case 'e':
801 {
anthonyafa3dfc2012-03-03 11:31:30 +0000802 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000803 {
anthony92c93bd2012-03-19 14:02:47 +0000804 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
805 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000806 break;
807 }
anthonyafa3dfc2012-03-03 11:31:30 +0000808 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000809 {
anthony92c93bd2012-03-19 14:02:47 +0000810 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000811 arg1 = ArgOption("undefined");
812 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
813 if (parse < 0)
814 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
815 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000816 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000817 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000818 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000819 break;
820 }
anthonyafa3dfc2012-03-03 11:31:30 +0000821 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000822 {
anthony92c93bd2012-03-19 14:02:47 +0000823 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000824 break;
825 }
anthonyebb73a22012-03-22 14:25:52 +0000826 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000827 }
828 case 'f':
829 {
anthonyafa3dfc2012-03-03 11:31:30 +0000830 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000831 {
anthony92c93bd2012-03-19 14:02:47 +0000832 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000833 break;
834 }
anthonya322a832013-04-27 06:28:03 +0000835 if (LocaleCompare("features",option+1) == 0)
836 {
837 (void) SetImageOption(_image_info,"identify:features",
cristyf9b9b662013-05-25 12:50:16 +0000838 ArgBooleanString);
anthonya322a832013-04-27 06:28:03 +0000839 if (IfSetOption)
840 (void) SetImageArtifact(_image,"verbose","true");
841 break;
842 }
anthonyafa3dfc2012-03-03 11:31:30 +0000843 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000844 {
anthony92c93bd2012-03-19 14:02:47 +0000845 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000846 The original fill color is preserved if a fill-pattern is given.
847 That way it does not effect other operations that directly using
848 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000849 */
anthony72feaa62012-01-17 06:46:23 +0000850 MagickBooleanType
851 status;
anthony6dc09cd2011-10-12 08:56:49 +0000852
853 ExceptionInfo
854 *sans;
855
anthonyfd706f92012-01-19 04:22:02 +0000856 PixelInfo
857 color;
858
anthony2a0ec8c2012-03-24 04:35:56 +0000859 arg1 = ArgOption("none"); /* +fill turns it off! */
860 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000861 if (_draw_info->fill_pattern != (Image *) NULL)
862 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000863
864 /* is it a color or a image? -- ignore exceptions */
865 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +0000866 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000867 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000868
anthony7bcfe7f2012-03-30 14:01:22 +0000869 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +0000870 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000871 else
anthony92c93bd2012-03-19 14:02:47 +0000872 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000873 break;
874 }
anthonyafa3dfc2012-03-03 11:31:30 +0000875 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000876 {
anthony72feaa62012-01-17 06:46:23 +0000877 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +0000878 arg1 = ArgOption("undefined");
879 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
880 if (parse < 0)
881 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
882 option,arg1);
883 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000884 break;
885 }
anthonyafa3dfc2012-03-03 11:31:30 +0000886 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000887 {
anthony92c93bd2012-03-19 14:02:47 +0000888 (void) CloneString(&_draw_info->font,ArgOption(NULL));
889 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000890 break;
891 }
anthonyafa3dfc2012-03-03 11:31:30 +0000892 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000893 {
anthonydcf510d2011-10-30 13:51:40 +0000894 /* FUTURE: why the ping test, you could set ping after this! */
895 /*
anthony805a2d42011-09-25 08:25:12 +0000896 register const char
897 *q;
898
anthony24aa8822012-03-11 00:56:06 +0000899 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000900 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000901 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000902 */
anthony92c93bd2012-03-19 14:02:47 +0000903 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000904 break;
905 }
anthonyafa3dfc2012-03-03 11:31:30 +0000906 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000907 {
anthony72feaa62012-01-17 06:46:23 +0000908 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000909 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000910 SyncImageSettings() used to set per-image attribute.
911
anthony2a0ec8c2012-03-24 04:35:56 +0000912 FUTURE: Can't find anything else using _image_info->fuzz directly!
anthonya322a832013-04-27 06:28:03 +0000913 convert structure attribute to 'option' string
anthony6613bf32011-10-15 07:24:44 +0000914 */
anthony2a0ec8c2012-03-24 04:35:56 +0000915 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000916 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +0000917 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
918 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +0000919 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +0000920 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000921 break;
922 }
anthonyebb73a22012-03-22 14:25:52 +0000923 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000924 }
925 case 'g':
926 {
anthonyafa3dfc2012-03-03 11:31:30 +0000927 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000928 {
anthony72feaa62012-01-17 06:46:23 +0000929 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000930 arg1 = ArgOption("none");
931 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
932 if (parse < 0)
933 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
934 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +0000935 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +0000936 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000937 break;
938 }
anthonyafa3dfc2012-03-03 11:31:30 +0000939 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000940 {
anthonydcf510d2011-10-30 13:51:40 +0000941 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000942 SyncImageSettings() used to set per-image attribute.
943 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000944 */
anthonyf42014d2012-03-25 09:53:06 +0000945 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000946 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000947 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000948 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000949 break;
950 }
anthonyebb73a22012-03-22 14:25:52 +0000951 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000952 }
anthonyb1d483a2012-04-14 12:53:56 +0000953 case 'h':
954 {
955 if (LocaleCompare("highlight-color",option+1) == 0)
956 {
957 /* FUTURE: this is only used by CompareImages() which is used
958 only by the "compare" CLI program at this time. */
959 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
960 break;
961 }
962 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
963 }
anthony805a2d42011-09-25 08:25:12 +0000964 case 'i':
965 {
cristy70e9f682013-03-12 22:31:22 +0000966 if (LocaleCompare("intensity",option+1) == 0)
967 {
968 arg1 = ArgOption("undefined");
cristy8f84fdd2013-03-28 17:52:55 +0000969 parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
970 arg1);
cristy70e9f682013-03-12 22:31:22 +0000971 if (parse < 0)
cristy8f84fdd2013-03-28 17:52:55 +0000972 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityType",
973 option,arg1);
cristy70e9f682013-03-12 22:31:22 +0000974 (void) SetImageOption(_image_info,option+1,arg1);
975 break;
976 }
anthonyafa3dfc2012-03-03 11:31:30 +0000977 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000978 {
anthony72feaa62012-01-17 06:46:23 +0000979 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000980 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000981 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000982 */
cristy70e9f682013-03-12 22:31:22 +0000983 arg1 = ArgOption("undefined");
anthonyfe1aa782012-03-24 13:43:04 +0000984 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
985 if (parse < 0)
986 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
987 option,arg1);
988 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000989 break;
990 }
anthonyafa3dfc2012-03-03 11:31:30 +0000991 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000992 {
anthony92c93bd2012-03-19 14:02:47 +0000993 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000994 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000995 */
anthonyfe1aa782012-03-24 13:43:04 +0000996 arg1 = ArgOption("undefined");
997 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
998 if (parse < 0)
999 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
1000 option,arg1);
1001 _image_info->interlace=(InterlaceType) parse;
1002 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001003 break;
1004 }
anthonyafa3dfc2012-03-03 11:31:30 +00001005 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001006 {
anthony7bcfe7f2012-03-30 14:01:22 +00001007 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001008 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001009 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1010 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001011 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001012 break;
1013 }
anthonyafa3dfc2012-03-03 11:31:30 +00001014 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001015 {
anthonyfd706f92012-01-19 04:22:02 +00001016 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001017 arg1 = ArgOption("undefined");
1018 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1019 if (parse < 0)
1020 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1021 option,arg1);
1022 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001023 break;
1024 }
anthonyafa3dfc2012-03-03 11:31:30 +00001025 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001026 {
anthony7bcfe7f2012-03-30 14:01:22 +00001027 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001028 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001029 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1030 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001031 break;
1032 }
anthonyebb73a22012-03-22 14:25:52 +00001033 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001034 }
1035 case 'k':
1036 {
anthonyafa3dfc2012-03-03 11:31:30 +00001037 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001038 {
anthony7bcfe7f2012-03-30 14:01:22 +00001039 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001040 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001041 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1042 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001043 break;
1044 }
anthonyebb73a22012-03-22 14:25:52 +00001045 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001046 }
1047 case 'l':
1048 {
anthonyafa3dfc2012-03-03 11:31:30 +00001049 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001050 {
anthony72feaa62012-01-17 06:46:23 +00001051 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001052 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001053 break;
1054 }
anthony756cd0d2012-04-08 12:41:44 +00001055 if (LocaleCompare("limit",option+1) == 0)
1056 {
1057 MagickSizeType
1058 limit;
1059
1060 limit=MagickResourceInfinity;
1061 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1062 if ( parse < 0 )
1063 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1064 option,arg1);
1065 if (LocaleCompare("unlimited",arg2) != 0)
1066 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1067 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1068 break;
1069 }
anthonyafa3dfc2012-03-03 11:31:30 +00001070 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001071 {
anthonyfe1aa782012-03-24 13:43:04 +00001072 if (IfSetOption) {
1073 if ((strchr(arg1,'%') == (char *) NULL))
1074 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001075 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001076 }
anthony805a2d42011-09-25 08:25:12 +00001077 break;
1078 }
anthony975a8d72012-04-12 13:54:36 +00001079 if (LocaleCompare("lowlight-color",option+1) == 0)
1080 {
anthonyb1d483a2012-04-14 12:53:56 +00001081 /* FUTURE: this is only used by CompareImages() which is used
1082 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001083 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1084 break;
1085 }
anthonyafa3dfc2012-03-03 11:31:30 +00001086 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001087 {
anthony72feaa62012-01-17 06:46:23 +00001088 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001089 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001090 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001091 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1092 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001093 break;
1094 }
anthonyebb73a22012-03-22 14:25:52 +00001095 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001096 }
1097 case 'm':
1098 {
anthonyafa3dfc2012-03-03 11:31:30 +00001099 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001100 {
anthony72feaa62012-01-17 06:46:23 +00001101 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001102 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
cristyd7df81d2014-01-18 18:42:05 +00001103 (void) QueryColorCompliance(ArgOption(MogrifyMatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001104 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001105 break;
anthonycd358fc2012-04-16 13:59:03 +00001106 }
anthonyb1d483a2012-04-14 12:53:56 +00001107 if (LocaleCompare("metric",option+1) == 0)
1108 {
1109 /* FUTURE: this is only used by CompareImages() which is used
1110 only by the "compare" CLI program at this time. */
1111 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1112 if ( parse < 0 )
1113 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1114 option,arg1);
1115 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001116 break;
anthony805a2d42011-09-25 08:25:12 +00001117 }
cristybd4a3c22014-01-07 15:09:37 +00001118 if (LocaleCompare("moments",option+1) == 0)
1119 {
1120 (void) SetImageOption(_image_info,"identify:moments",
1121 ArgBooleanString);
1122 if (IfSetOption)
1123 (void) SetImageArtifact(_image,"verbose","true");
1124 break;
1125 }
anthonyafa3dfc2012-03-03 11:31:30 +00001126 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001127 {
anthony92c93bd2012-03-19 14:02:47 +00001128 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001129 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001130 break;
1131 }
anthonyafa3dfc2012-03-03 11:31:30 +00001132 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001133 {
anthony24aa8822012-03-11 00:56:06 +00001134 /* Setting (used by some input coders!) -- why?
1135 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001136 */
anthony92c93bd2012-03-19 14:02:47 +00001137 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001138 break;
1139 }
anthonyebb73a22012-03-22 14:25:52 +00001140 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001141 }
1142 case 'o':
1143 {
anthonyafa3dfc2012-03-03 11:31:30 +00001144 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001145 {
anthony72feaa62012-01-17 06:46:23 +00001146 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001147 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001148 FUTURE: make set meta-data operator instead.
1149 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001150 */
anthony7bc87992012-03-25 02:32:51 +00001151 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1152 ArgOption("undefined"));
1153 if (parse < 0)
1154 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1155 option,arg1);
1156 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001157 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001158 break;
1159 }
anthonyebb73a22012-03-22 14:25:52 +00001160 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001161 }
1162 case 'p':
1163 {
anthonyafa3dfc2012-03-03 11:31:30 +00001164 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001165 {
anthony7bc87992012-03-25 02:32:51 +00001166 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001167 SyncImageSettings() used to set per-image attribute. ?????
1168 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001169 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001170 */
anthony805a2d42011-09-25 08:25:12 +00001171 char
1172 *canonical_page,
1173 page[MaxTextExtent];
1174
1175 const char
1176 *image_option;
1177
1178 MagickStatusType
1179 flags;
1180
1181 RectangleInfo
1182 geometry;
1183
anthonydcf510d2011-10-30 13:51:40 +00001184 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001185 {
anthony92c93bd2012-03-19 14:02:47 +00001186 (void) DeleteImageOption(_image_info,option+1);
1187 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001188 break;
1189 }
1190 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001191 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001192 if (image_option != (const char *) NULL)
1193 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001194 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001195 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1196 canonical_page=DestroyString(canonical_page);
1197 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1198 (unsigned long) geometry.width,(unsigned long) geometry.height);
1199 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1200 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1201 (unsigned long) geometry.width,(unsigned long) geometry.height,
1202 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001203 (void) SetImageOption(_image_info,option+1,page);
1204 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001205 break;
1206 }
anthonyafa3dfc2012-03-03 11:31:30 +00001207 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001208 {
anthony92c93bd2012-03-19 14:02:47 +00001209 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001210 break;
1211 }
anthonyafa3dfc2012-03-03 11:31:30 +00001212 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001213 {
anthonyf42014d2012-03-25 09:53:06 +00001214 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001215 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001216 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1217 _image_info->pointsize =
1218 _draw_info->pointsize =
1219 StringToDouble(arg1,(char **) NULL);
1220 }
1221 else {
1222 _image_info->pointsize=0.0; /* unset pointsize */
1223 _draw_info->pointsize=12.0;
1224 }
anthony805a2d42011-09-25 08:25:12 +00001225 break;
1226 }
anthonyafa3dfc2012-03-03 11:31:30 +00001227 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001228 {
anthonyf42014d2012-03-25 09:53:06 +00001229 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001230 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001231 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1232 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001233 break;
1234 }
anthonydcf510d2011-10-30 13:51:40 +00001235 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001236 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001237 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001238 {
anthony92c93bd2012-03-19 14:02:47 +00001239 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001240 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001241 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001242 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001243 break;
1244 }
anthonydcf510d2011-10-30 13:51:40 +00001245 */
anthonyebb73a22012-03-22 14:25:52 +00001246 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001247 }
1248 case 'q':
1249 {
anthonyafa3dfc2012-03-03 11:31:30 +00001250 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001251 {
anthony7bcfe7f2012-03-30 14:01:22 +00001252 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001253 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001254 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1255 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001256 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001257 break;
1258 }
anthonyafa3dfc2012-03-03 11:31:30 +00001259 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001260 {
anthony92c93bd2012-03-19 14:02:47 +00001261 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001262 arg1=ArgOption("undefined");
1263 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1264 if (parse < 0)
1265 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1266 option,arg1);
1267 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001268 break;
1269 }
anthonyafa3dfc2012-03-03 11:31:30 +00001270 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001271 {
anthonyf42014d2012-03-25 09:53:06 +00001272 /* FUTURE: if two -quiet is performed you can not do +quiet!
1273 This needs to be checked over thoughly.
1274 */
anthony805a2d42011-09-25 08:25:12 +00001275 static WarningHandler
1276 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001277
anthonyafbaed72011-10-26 12:05:04 +00001278 WarningHandler
1279 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001280
anthonyafbaed72011-10-26 12:05:04 +00001281 if ( tmp != (WarningHandler) NULL)
1282 warning_handler = tmp; /* remember the old handler */
1283 if (!IfSetOption) /* set the old handler */
1284 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001285 break;
1286 }
anthonyebb73a22012-03-22 14:25:52 +00001287 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001288 }
1289 case 'r':
1290 {
anthonyafa3dfc2012-03-03 11:31:30 +00001291 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001292 {
anthonydcf510d2011-10-30 13:51:40 +00001293 /* Image chromaticity X,Y NB: Y=X if Y not defined
1294 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001295 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001296 */
anthonyf42014d2012-03-25 09:53:06 +00001297 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001298 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001299 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001300 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001301 break;
1302 }
cristyb0f7a182012-04-06 23:33:11 +00001303 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001304 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001305 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001306 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001307 {
anthony92c93bd2012-03-19 14:02:47 +00001308 /* _draw_info only setting */
1309 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001310 break;
1311 }
anthony756cd0d2012-04-08 12:41:44 +00001312 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1313 {
1314 /* link image and setting stacks - option is itself saved on stack! */
1315 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1316 break;
1317 }
anthonyebb73a22012-03-22 14:25:52 +00001318 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001319 }
1320 case 's':
1321 {
anthonyafa3dfc2012-03-03 11:31:30 +00001322 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001323 {
anthonyafbaed72011-10-26 12:05:04 +00001324 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001325 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001326 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001327 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001328 break;
1329 }
anthonyafa3dfc2012-03-03 11:31:30 +00001330 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001331 {
anthonyf42014d2012-03-25 09:53:06 +00001332 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001333 What ??? Why ????
1334 */
anthony7bcfe7f2012-03-30 14:01:22 +00001335 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001336 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001337 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1338 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001339 break;
1340 }
anthonyafa3dfc2012-03-03 11:31:30 +00001341 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001342 {
anthony7bcfe7f2012-03-30 14:01:22 +00001343 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001344 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001345 SetRandomSecretKey(
cristya30f8e62013-02-19 15:03:45 +00001346 IfSetOption ? (unsigned long) StringToUnsignedLong(arg1)
1347 : (unsigned long) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001348 break;
1349 }
anthonyafa3dfc2012-03-03 11:31:30 +00001350 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001351 {
anthony92c93bd2012-03-19 14:02:47 +00001352 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001353 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001354 */
anthony92c93bd2012-03-19 14:02:47 +00001355 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001356 break;
1357 }
anthonyafa3dfc2012-03-03 11:31:30 +00001358 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001359 {
anthonyf42014d2012-03-25 09:53:06 +00001360 arg1=ArgOption("undefined");
1361 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1362 if (parse < 0)
1363 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1364 option,arg1);
1365 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001366 break;
1367 }
anthonyafa3dfc2012-03-03 11:31:30 +00001368 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001369 {
anthonyafbaed72011-10-26 12:05:04 +00001370 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001371 UPDATE: ensure stroke color is not destroyed is a pattern
1372 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001373 */
anthony72feaa62012-01-17 06:46:23 +00001374 MagickBooleanType
1375 status;
anthonyafbaed72011-10-26 12:05:04 +00001376
1377 ExceptionInfo
1378 *sans;
1379
anthonyfd706f92012-01-19 04:22:02 +00001380 PixelInfo
1381 color;
1382
anthony2a0ec8c2012-03-24 04:35:56 +00001383 arg1 = ArgOption("none"); /* +fill turns it off! */
1384 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001385 if (_draw_info->stroke_pattern != (Image *) NULL)
1386 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001387
1388 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001389 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001390 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001391 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001392
anthony7bcfe7f2012-03-30 14:01:22 +00001393 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001394 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001395 else
anthony92c93bd2012-03-19 14:02:47 +00001396 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001397 break;
1398 }
anthonyafa3dfc2012-03-03 11:31:30 +00001399 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001400 {
anthony7bcfe7f2012-03-30 14:01:22 +00001401 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001402 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001403 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1404 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001405 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001406 break;
1407 }
anthonyafa3dfc2012-03-03 11:31:30 +00001408 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001409 {
anthonyf42014d2012-03-25 09:53:06 +00001410 arg1=ArgOption("undefined");
1411 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1412 if (parse < 0)
1413 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1414 option,arg1);
1415 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001416 break;
1417 }
anthonycd358fc2012-04-16 13:59:03 +00001418#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001419 if (LocaleCompare("subimage-search",option+1) == 0)
1420 {
1421 /* FUTURE: this is only used by CompareImages() which is used
1422 only by the "compare" CLI program at this time. */
1423 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1424 break;
1425 }
anthonycd358fc2012-04-16 13:59:03 +00001426#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001428 {
anthonyf42014d2012-03-25 09:53:06 +00001429 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001430 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001431 break;
1432 }
anthonyebb73a22012-03-22 14:25:52 +00001433 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001434 }
1435 case 't':
1436 {
anthonyafa3dfc2012-03-03 11:31:30 +00001437 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001438 {
anthony72feaa62012-01-17 06:46:23 +00001439 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001440 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001441 break;
1442 }
anthonyafa3dfc2012-03-03 11:31:30 +00001443 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001444 {
anthony4837ac22012-05-18 23:39:48 +00001445 /* Note: arguments do not have percent escapes expanded */
anthony52bef752012-03-27 13:54:47 +00001446 /* FUTURE: move _image_info string to option splay-tree
1447 Other than "montage" what uses "texture" ????
1448 */
anthony92c93bd2012-03-19 14:02:47 +00001449 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001450 break;
1451 }
anthonyafa3dfc2012-03-03 11:31:30 +00001452 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001453 {
anthony4837ac22012-05-18 23:39:48 +00001454 /* Note: arguments do not have percent escapes expanded */
anthony92c93bd2012-03-19 14:02:47 +00001455 _draw_info->fill_pattern=IfSetOption
1456 ?GetImageCache(_image_info,arg1,_exception)
1457 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001458 break;
1459 }
anthonyafa3dfc2012-03-03 11:31:30 +00001460 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001461 {
anthony72feaa62012-01-17 06:46:23 +00001462 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001463 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001464 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001465 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1466 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001467 break;
1468 }
anthonyafa3dfc2012-03-03 11:31:30 +00001469 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001470 {
anthony92c93bd2012-03-19 14:02:47 +00001471 /* FUTURE: both _image_info attribute & ImageOption in use!
1472 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001473 SyncImageSettings() used to set per-image attribute.
1474
anthonyafbaed72011-10-26 12:05:04 +00001475 Note that +transparent-color, means fall-back to image
1476 attribute so ImageOption is deleted, not set to a default.
1477 */
anthony7bcfe7f2012-03-30 14:01:22 +00001478 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001479 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001480 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001481 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001482 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001483 break;
1484 }
anthonyafa3dfc2012-03-03 11:31:30 +00001485 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001486 {
anthony92c93bd2012-03-19 14:02:47 +00001487 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1488 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001489 break;
1490 }
anthonyafa3dfc2012-03-03 11:31:30 +00001491 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001492 {
anthony72feaa62012-01-17 06:46:23 +00001493 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001494 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1495 ArgOption("undefined"));
1496 if (parse < 0)
1497 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1498 option,arg1);
1499 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001500 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001501 break;
1502 }
anthonyebb73a22012-03-22 14:25:52 +00001503 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001504 }
1505 case 'u':
1506 {
anthonyafa3dfc2012-03-03 11:31:30 +00001507 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001508 {
anthony92c93bd2012-03-19 14:02:47 +00001509 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001510 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001511 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001512 break;
1513 }
anthonyafa3dfc2012-03-03 11:31:30 +00001514 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001515 {
anthony72feaa62012-01-17 06:46:23 +00001516 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001517 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001518 FUTURE: this probably should be part of the density setting
1519 */
anthony52bef752012-03-27 13:54:47 +00001520 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1521 ArgOption("undefined"));
1522 if (parse < 0)
1523 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1524 option,arg1);
1525 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001526 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001527 break;
1528 }
anthonyebb73a22012-03-22 14:25:52 +00001529 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001530 }
1531 case 'v':
1532 {
anthonyafa3dfc2012-03-03 11:31:30 +00001533 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001534 {
anthony24aa8822012-03-11 00:56:06 +00001535 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001536 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001537 */
anthony92c93bd2012-03-19 14:02:47 +00001538 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1539 _image_info->verbose= ArgBoolean;
1540 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001541 break;
1542 }
anthonyafa3dfc2012-03-03 11:31:30 +00001543 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001544 {
anthony92c93bd2012-03-19 14:02:47 +00001545 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001546 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001547 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001548 */
anthony92c93bd2012-03-19 14:02:47 +00001549 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001550 break;
1551 }
anthonyafa3dfc2012-03-03 11:31:30 +00001552 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001553 {
anthonyfd706f92012-01-19 04:22:02 +00001554 /* SyncImageSettings() used to set per-image attribute.
1555 This is VERY deep in the image caching structure.
1556 */
anthony52bef752012-03-27 13:54:47 +00001557 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1558 ArgOption("undefined"));
1559 if (parse < 0)
1560 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1561 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001562 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001563 break;
1564 }
anthonyebb73a22012-03-22 14:25:52 +00001565 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001566 }
1567 case 'w':
1568 {
anthonyafa3dfc2012-03-03 11:31:30 +00001569 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001570 {
anthony72feaa62012-01-17 06:46:23 +00001571 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001572 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001573 */
anthony52bef752012-03-27 13:54:47 +00001574 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001575 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001576 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001577 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001578 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001579 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001580 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001581 if (_draw_info->weight <= 800)
1582 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001583 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001584 if (_draw_info->weight >= 100)
1585 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001586 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001587 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001588 break;
1589 }
anthonyafa3dfc2012-03-03 11:31:30 +00001590 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001591 {
anthony72feaa62012-01-17 06:46:23 +00001592 /* Used as a image chromaticity setting
1593 SyncImageSettings() used to set per-image attribute.
1594 */
anthony52bef752012-03-27 13:54:47 +00001595 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001596 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001597 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1598 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001599 break;
1600 }
anthonyebb73a22012-03-22 14:25:52 +00001601 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001602 }
1603 default:
anthonyebb73a22012-03-22 14:25:52 +00001604 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001605 }
anthony24aa8822012-03-11 00:56:06 +00001606
anthony4837ac22012-05-18 23:39:48 +00001607 /* clean up percent escape interpreted strings */
1608 if (arg1 != arg1n )
1609 arg1=DestroyString((char *)arg1);
1610 if (arg2 != arg2n )
1611 arg2=DestroyString((char *)arg2);
anthony4837ac22012-05-18 23:39:48 +00001612
anthony92c93bd2012-03-19 14:02:47 +00001613#undef _image_info
1614#undef _exception
1615#undef _draw_info
1616#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001617#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001618#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001619#undef ArgBooleanNot
1620#undef ArgBooleanString
1621#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001622
anthony31f1bf72012-01-30 12:37:22 +00001623 return;
anthony805a2d42011-09-25 08:25:12 +00001624}
1625
1626/*
1627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628% %
1629% %
1630% %
anthony43f425d2012-02-26 12:58:58 +00001631+ C L I S i m p l e O p e r a t o r I m a g e s %
anthony805a2d42011-09-25 08:25:12 +00001632% %
1633% %
1634% %
1635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1636%
anthonyc7994672012-11-17 05:33:27 +00001637% CLISimpleOperatorImages() applys one simple image operation given to all
1638% the images in the CLI wand, using any per-image or global settings that was
1639% previously saved in the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001640%
anthonyc7994672012-11-17 05:33:27 +00001641% It is assumed that any such settings are up-to-date.
anthony805a2d42011-09-25 08:25:12 +00001642%
anthony7a4d6102012-07-01 09:48:25 +00001643% The format of the WandSimpleOperatorImages method is:
anthony805a2d42011-09-25 08:25:12 +00001644%
anthony43f425d2012-02-26 12:58:58 +00001645% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001646% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001647%
1648% A description of each parameter follows:
1649%
anthony43f425d2012-02-26 12:58:58 +00001650% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001651%
anthonyfd706f92012-01-19 04:22:02 +00001652% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001653%
anthonyfd706f92012-01-19 04:22:02 +00001654% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001655%
anthony805a2d42011-09-25 08:25:12 +00001656*/
anthony31f1bf72012-01-30 12:37:22 +00001657
1658/*
anthonyc7994672012-11-17 05:33:27 +00001659 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1660 image operation to the current image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001661
1662 The image in the list may be modified in three different ways...
1663 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1664 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1665 * one image replace by a list of images (-separate and -crop only!)
1666
anthonyafa3dfc2012-03-03 11:31:30 +00001667 In each case the result replaces the single original image in the list, as
1668 well as the pointer to the modified image (last image added if replaced by a
1669 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001670
1671 As the image pointed to may be replaced, the first image in the list may
1672 also change. GetFirstImageInList() should be used by caller if they wish
1673 return the Image pointer to the first image in list.
1674*/
cristyfe831852013-02-12 14:56:07 +00001675static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00001676 const char *option, const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00001677{
1678 Image *
1679 new_image;
1680
anthony805a2d42011-09-25 08:25:12 +00001681 GeometryInfo
1682 geometry_info;
1683
1684 RectangleInfo
1685 geometry;
1686
1687 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001688 flags;
1689
anthony92c93bd2012-03-19 14:02:47 +00001690 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001691 parse;
anthony92c93bd2012-03-19 14:02:47 +00001692
anthonya322a832013-04-27 06:28:03 +00001693 const char /* percent escaped versions of the args */
anthony964d28e2012-05-17 23:39:46 +00001694 *arg1,
1695 *arg2;
1696
anthonya322a832013-04-27 06:28:03 +00001697#define _image_info (cli_wand->wand.image_info)
1698#define _image (cli_wand->wand.images)
1699#define _exception (cli_wand->wand.exception)
1700#define _draw_info (cli_wand->draw_info)
1701#define _quantize_info (cli_wand->quantize_info)
1702#define _process_flags (cli_wand->process_flags)
1703#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
1704#define IfNormalOp (*option=='-')
1705#define IfPlusOp (*option!='-')
1706#define IsNormalOp IsMagickTrue(IfNormalOp)
1707#define IsPlusOp IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001708
anthony43f425d2012-02-26 12:58:58 +00001709 assert(cli_wand != (MagickCLI *) NULL);
1710 assert(cli_wand->signature == WandSignature);
1711 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001712 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001713 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001714 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001715
anthony964d28e2012-05-17 23:39:46 +00001716 arg1 = arg1n,
1717 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00001718
1719 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00001720 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1721 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1722 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1723 /* Interpret Percent escapes in argument 1 */
1724 if (arg1n != (char *) NULL) {
1725 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1726 if (arg1 == (char *) NULL) {
1727 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1728 arg1=arg1n; /* use the given argument as is */
1729 }
1730 }
1731 if (arg2n != (char *) NULL) {
1732 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1733 if (arg2 == (char *) NULL) {
1734 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1735 arg2=arg2n; /* use the given argument as is */
1736 }
1737 }
1738 }
anthony4837ac22012-05-18 23:39:48 +00001739#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00001740#undef _option_type
1741
1742#if 0
1743 (void) FormatLocaleFile(stderr,
1744 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1745#endif
anthony805a2d42011-09-25 08:25:12 +00001746
anthony5330ae02012-03-20 14:17:01 +00001747 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony964d28e2012-05-17 23:39:46 +00001748 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001749
anthonyafa3dfc2012-03-03 11:31:30 +00001750 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001751 {
1752 case 'a':
1753 {
anthonyafa3dfc2012-03-03 11:31:30 +00001754 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001755 {
anthonyfd706f92012-01-19 04:22:02 +00001756 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001757 if ((flags & (RhoValue|SigmaValue)) == 0)
1758 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001759 if ((flags & SigmaValue) == 0)
1760 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001761 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001762 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001763 break;
1764 }
anthonyafa3dfc2012-03-03 11:31:30 +00001765 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001766 {
anthonyfe1aa782012-03-24 13:43:04 +00001767 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001768 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001769 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1770 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1771 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001772 _exception);
anthony805a2d42011-09-25 08:25:12 +00001773 break;
1774 }
anthonyafa3dfc2012-03-03 11:31:30 +00001775 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001776 {
anthonyfd706f92012-01-19 04:22:02 +00001777 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001778 if ((flags & (RhoValue|SigmaValue)) == 0)
1779 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001780 if ((flags & SigmaValue) == 0)
1781 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001782 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001783 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001784 break;
1785 }
anthonyafa3dfc2012-03-03 11:31:30 +00001786 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001787 {
cristy288a3532012-08-28 00:19:44 +00001788 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001789 if (parse < 0)
cristyb15b06c2012-08-28 11:36:48 +00001790 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
anthony92c93bd2012-03-19 14:02:47 +00001791 option,arg1);
cristyb15b06c2012-08-28 11:36:48 +00001792 (void) SetImageAlphaChannel(_image,(AlphaChannelOption)parse,
anthony2a0ec8c2012-03-24 04:35:56 +00001793 _exception);
anthony805a2d42011-09-25 08:25:12 +00001794 break;
1795 }
anthonyafa3dfc2012-03-03 11:31:30 +00001796 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001797 {
1798 char
anthony805a2d42011-09-25 08:25:12 +00001799 geometry[MaxTextExtent];
1800
anthony805a2d42011-09-25 08:25:12 +00001801 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001802 flags=ParseGeometry(arg1,&geometry_info);
cristy8592b052013-02-07 01:24:54 +00001803 if (flags == 0)
anthony22de2722012-04-19 14:43:00 +00001804 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001805 if ((flags & SigmaValue) == 0)
1806 geometry_info.sigma=geometry_info.rho;
anthony964d28e2012-05-17 23:39:46 +00001807 (void) CloneString(&_draw_info->text,arg2);
anthony805a2d42011-09-25 08:25:12 +00001808 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1809 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001810 (void) CloneString(&_draw_info->geometry,geometry);
1811 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001812 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001813 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001814 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001815 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001816 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001817 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001818 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001819 (void) AnnotateImage(_image,_draw_info,_exception);
1820 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001821 break;
1822 }
anthonyafa3dfc2012-03-03 11:31:30 +00001823 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001824 {
anthony92c93bd2012-03-19 14:02:47 +00001825 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001826 break;
1827 }
anthonyafa3dfc2012-03-03 11:31:30 +00001828 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001829 {
anthony92c93bd2012-03-19 14:02:47 +00001830 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001831 break;
1832 }
anthonyafa3dfc2012-03-03 11:31:30 +00001833 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001834 {
cristyfa5f6c72013-01-01 14:37:35 +00001835 new_image=AutoOrientImage(_image,_image->orientation,_exception);
anthony805a2d42011-09-25 08:25:12 +00001836 break;
1837 }
anthonyebb73a22012-03-22 14:25:52 +00001838 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001839 }
1840 case 'b':
1841 {
anthonyafa3dfc2012-03-03 11:31:30 +00001842 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001843 {
anthony7bcfe7f2012-03-30 14:01:22 +00001844 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001845 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001846 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001847 break;
1848 }
anthonyafa3dfc2012-03-03 11:31:30 +00001849 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001850 {
anthony805a2d42011-09-25 08:25:12 +00001851 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001852 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001853 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001854 if ((flags & RhoValue) == 0)
1855 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001856 }
anthony92c93bd2012-03-19 14:02:47 +00001857 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001858 break;
1859 }
anthonyafa3dfc2012-03-03 11:31:30 +00001860 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001861 {
anthonyfd706f92012-01-19 04:22:02 +00001862 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001863 if ((flags & (RhoValue|SigmaValue)) == 0)
1864 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001865 if ((flags & SigmaValue) == 0)
1866 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001867 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1868 _exception);
anthony805a2d42011-09-25 08:25:12 +00001869 break;
1870 }
anthonyafa3dfc2012-03-03 11:31:30 +00001871 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001872 {
anthony31f1bf72012-01-30 12:37:22 +00001873 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001874 compose;
1875
1876 const char*
anthony5f867ae2011-10-09 10:28:34 +00001877 value;
1878
anthony22de2722012-04-19 14:43:00 +00001879 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
cristy64ad8f92012-08-03 00:58:24 +00001880 if ((flags & (WidthValue | HeightValue)) == 0)
anthony5330ae02012-03-20 14:17:01 +00001881 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy64ad8f92012-08-03 00:58:24 +00001882 compose=OverCompositeOp;
anthony92c93bd2012-03-19 14:02:47 +00001883 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001884 if (value != (const char *) NULL)
cristy64ad8f92012-08-03 00:58:24 +00001885 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1886 MagickFalse,value);
anthony92c93bd2012-03-19 14:02:47 +00001887 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001888 break;
1889 }
anthonyafa3dfc2012-03-03 11:31:30 +00001890 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001891 {
1892 double
1893 brightness,
1894 contrast;
1895
1896 GeometryInfo
1897 geometry_info;
1898
1899 MagickStatusType
1900 flags;
1901
anthonyfd706f92012-01-19 04:22:02 +00001902 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001903 if ((flags & RhoValue) == 0)
1904 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001905 brightness=geometry_info.rho;
1906 contrast=0.0;
1907 if ((flags & SigmaValue) != 0)
1908 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001909 (void) BrightnessContrastImage(_image,brightness,contrast,
1910 _exception);
anthony805a2d42011-09-25 08:25:12 +00001911 break;
1912 }
anthonyebb73a22012-03-22 14:25:52 +00001913 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001914 }
1915 case 'c':
1916 {
anthonyafa3dfc2012-03-03 11:31:30 +00001917 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001918 {
anthony4837ac22012-05-18 23:39:48 +00001919 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001920 char
1921 *color_correction_collection;
1922
1923 /*
1924 Color correct with a color decision list.
1925 */
cristy3a5987c2013-11-07 14:18:46 +00001926 color_correction_collection=FileToString(arg1,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001927 if (color_correction_collection == (char *) NULL)
1928 break;
anthony92c93bd2012-03-19 14:02:47 +00001929 (void) ColorDecisionListImage(_image,color_correction_collection,
1930 _exception);
anthony805a2d42011-09-25 08:25:12 +00001931 break;
1932 }
anthonyafa3dfc2012-03-03 11:31:30 +00001933 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001934 {
anthonyfd706f92012-01-19 04:22:02 +00001935 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001936 if ((flags & (RhoValue|SigmaValue)) == 0)
1937 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001938 if ((flags & SigmaValue) == 0)
1939 geometry_info.sigma=1.0;
1940 if ((flags & XiValue) == 0)
1941 geometry_info.xi=1.0;
cristyee3f7522012-12-21 19:27:44 +00001942 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1943 _exception);
anthony805a2d42011-09-25 08:25:12 +00001944 break;
1945 }
anthonyafa3dfc2012-03-03 11:31:30 +00001946 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001947 {
anthony7bcfe7f2012-03-30 14:01:22 +00001948 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001949 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001950 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1951 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001952 break;
1953 }
anthonyafa3dfc2012-03-03 11:31:30 +00001954 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001955 {
anthony92c93bd2012-03-19 14:02:47 +00001956 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001957 break;
1958 }
anthonyafa3dfc2012-03-03 11:31:30 +00001959 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001960 {
anthonyafa3dfc2012-03-03 11:31:30 +00001961 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001962 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001963 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001964 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001965 break;
1966 }
anthonyafa3dfc2012-03-03 11:31:30 +00001967 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001968 {
anthony4837ac22012-05-18 23:39:48 +00001969 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001970 CacheView
1971 *mask_view;
1972
1973 Image
1974 *mask_image;
1975
1976 register Quantum
1977 *restrict q;
1978
1979 register ssize_t
1980 x;
1981
1982 ssize_t
1983 y;
1984
anthonyafa3dfc2012-03-03 11:31:30 +00001985 if (IfPlusOp) {
anthony4837ac22012-05-18 23:39:48 +00001986 /* use "+clip-mask" Remove the write mask for -clip-path */
anthony92c93bd2012-03-19 14:02:47 +00001987 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00001988 break;
1989 }
anthony92c93bd2012-03-19 14:02:47 +00001990 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001991 if (mask_image == (Image *) NULL)
1992 break;
anthony7bcfe7f2012-03-30 14:01:22 +00001993 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00001994 break;
anthony5330ae02012-03-20 14:17:01 +00001995 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00001996 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristy46ff2672012-12-14 15:32:26 +00001997 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001998 for (y=0; y < (ssize_t) mask_image->rows; y++)
1999 {
2000 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002001 _exception);
anthony805a2d42011-09-25 08:25:12 +00002002 if (q == (Quantum *) NULL)
2003 break;
2004 for (x=0; x < (ssize_t) mask_image->columns; x++)
2005 {
cristydc2d3272013-02-12 14:00:44 +00002006 if (mask_image->alpha_trait != BlendPixelTrait)
anthony805a2d42011-09-25 08:25:12 +00002007 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
cristy81ac7972013-03-31 19:25:23 +00002008 SetPixelGray(mask_image,GetPixelAlpha(mask_image,q),q);
anthony805a2d42011-09-25 08:25:12 +00002009 q+=GetPixelChannels(mask_image);
2010 }
anthony7bcfe7f2012-03-30 14:01:22 +00002011 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002012 break;
2013 }
anthonyfd706f92012-01-19 04:22:02 +00002014 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002015 mask_view=DestroyCacheView(mask_view);
cristy8a46d822012-08-28 23:32:39 +00002016 mask_image->alpha_trait=BlendPixelTrait;
cristy81ac7972013-03-31 19:25:23 +00002017 (void) SetImageColorspace(_image,GRAYColorspace,_exception);
anthony92c93bd2012-03-19 14:02:47 +00002018 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002019 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002020 break;
2021 }
anthonyafa3dfc2012-03-03 11:31:30 +00002022 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002023 {
anthonya322a832013-04-27 06:28:03 +00002024 (void) ClipImagePath(_image,arg1,IsNormalOp,_exception);
anthony4837ac22012-05-18 23:39:48 +00002025 /* Note: Use "+clip-mask" remove the write mask added */
anthony805a2d42011-09-25 08:25:12 +00002026 break;
2027 }
anthonyafa3dfc2012-03-03 11:31:30 +00002028 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002029 {
anthony7bcfe7f2012-03-30 14:01:22 +00002030 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002031 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002032 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002033 break;
2034 }
anthonyafa3dfc2012-03-03 11:31:30 +00002035 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002036 {
2037 KernelInfo
2038 *kernel;
2039
anthonyfd706f92012-01-19 04:22:02 +00002040 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002041 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002042 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002043 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002044 kernel=DestroyKernelInfo(kernel);
2045 break;
2046 }
anthonyafa3dfc2012-03-03 11:31:30 +00002047 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002048 {
anthony5330ae02012-03-20 14:17:01 +00002049 /* Reduce the number of colors in the image.
2050 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002051 */
anthony92c93bd2012-03-19 14:02:47 +00002052 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2053 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002054 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002055 if ((_image->storage_class == DirectClass) ||
2056 _image->colors > _quantize_info->number_colors)
2057 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002058 else
anthony92c93bd2012-03-19 14:02:47 +00002059 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002060 break;
2061 }
anthonyafa3dfc2012-03-03 11:31:30 +00002062 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002063 {
anthony5330ae02012-03-20 14:17:01 +00002064 /* WARNING: this is both a image_info setting (already done)
2065 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002066
2067 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002068 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002069
anthonyd2cdc862011-10-07 14:07:17 +00002070 Note that +colorspace sets "undefined" or no effect on
2071 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002072 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002073 */
anthony92c93bd2012-03-19 14:02:47 +00002074 (void) TransformImageColorspace(_image,
cristye0b9b8f2013-03-28 12:39:39 +00002075 IfNormalOp ? _image_info->colorspace : sRGBColorspace,
anthony92c93bd2012-03-19 14:02:47 +00002076 _exception);
anthony805a2d42011-09-25 08:25:12 +00002077 break;
2078 }
anthonyafa3dfc2012-03-03 11:31:30 +00002079 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002080 {
anthonya322a832013-04-27 06:28:03 +00002081 CLIWandWarnReplaced(IfNormalOp?"-level":"+level");
2082 (void) ContrastImage(_image,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002083 break;
2084 }
anthonyafa3dfc2012-03-03 11:31:30 +00002085 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002086 {
2087 double
2088 black_point,
2089 white_point;
2090
2091 MagickStatusType
2092 flags;
2093
anthonyfd706f92012-01-19 04:22:02 +00002094 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002095 if ((flags & RhoValue) == 0)
2096 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002097 black_point=geometry_info.rho;
2098 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2099 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002100 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002101 black_point*=(double) _image->columns*_image->rows/100.0;
2102 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002103 }
cristya19f1d72012-08-07 18:24:38 +00002104 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002105 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002106 (void) ContrastStretchImage(_image,black_point,white_point,
2107 _exception);
anthony805a2d42011-09-25 08:25:12 +00002108 break;
2109 }
anthonyafa3dfc2012-03-03 11:31:30 +00002110 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002111 {
2112 KernelInfo
2113 *kernel_info;
2114
anthonyfd706f92012-01-19 04:22:02 +00002115 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002116 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002117 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristya12d8ba2012-04-29 16:33:41 +00002118 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2119 _exception);
anthony805a2d42011-09-25 08:25:12 +00002120 kernel_info=DestroyKernelInfo(kernel_info);
2121 break;
2122 }
anthonyafa3dfc2012-03-03 11:31:30 +00002123 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002124 {
anthony31f1bf72012-01-30 12:37:22 +00002125 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002126 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002127 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002128 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002129 break;
2130 }
anthonyafa3dfc2012-03-03 11:31:30 +00002131 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002132 {
anthony7bcfe7f2012-03-30 14:01:22 +00002133 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002134 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002135 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2136 _exception);
anthony805a2d42011-09-25 08:25:12 +00002137 break;
2138 }
anthonyebb73a22012-03-22 14:25:52 +00002139 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002140 }
2141 case 'd':
2142 {
anthonyafa3dfc2012-03-03 11:31:30 +00002143 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002144 {
anthony4837ac22012-05-18 23:39:48 +00002145 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002146 StringInfo
2147 *passkey;
2148
cristy3a5987c2013-11-07 14:18:46 +00002149 passkey=FileToStringInfo(arg1,~0UL,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002150 if (passkey == (StringInfo *) NULL)
2151 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2152
2153 (void) PasskeyDecipherImage(_image,passkey,_exception);
2154 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002155 break;
2156 }
anthonyafa3dfc2012-03-03 11:31:30 +00002157 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002158 {
anthony92c93bd2012-03-19 14:02:47 +00002159 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002160 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002161
anthonydcf510d2011-10-30 13:51:40 +00002162 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2163 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002164
anthonyfd706f92012-01-19 04:22:02 +00002165 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002166 */
anthony92c93bd2012-03-19 14:02:47 +00002167 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002168 break;
2169 }
anthonyafa3dfc2012-03-03 11:31:30 +00002170 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002171 {
2172 double
2173 threshold;
2174
anthonyebb73a22012-03-22 14:25:52 +00002175 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002176 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002177 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002178 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002179 }
anthonyafa3dfc2012-03-03 11:31:30 +00002180 else
2181 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002182 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002183 break;
2184 }
anthonyafa3dfc2012-03-03 11:31:30 +00002185 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002186 {
anthony92c93bd2012-03-19 14:02:47 +00002187 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002188 break;
2189 }
anthonyafa3dfc2012-03-03 11:31:30 +00002190 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002191 {
anthony805a2d42011-09-25 08:25:12 +00002192 double
anthonyb1d483a2012-04-14 12:53:56 +00002193 *args;
anthony805a2d42011-09-25 08:25:12 +00002194
anthonyb1d483a2012-04-14 12:53:56 +00002195 ssize_t
2196 count;
anthony805a2d42011-09-25 08:25:12 +00002197
anthony2a0ec8c2012-03-24 04:35:56 +00002198 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2199 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002200 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2201 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002202 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002203 {
anthony80c37752012-01-16 01:03:11 +00002204 double
2205 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002206 /* Special Case - Argument is actually a resize geometry!
2207 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002208 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002209 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002210 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002211 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2212 option,arg2);
2213 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002214 resize_args[0]=(double) geometry.width;
2215 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002216 new_image=DistortImage(_image,(DistortImageMethod) parse,
2217 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002218 break;
2219 }
anthonyb1d483a2012-04-14 12:53:56 +00002220 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002221 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002222 if (args == (double *)NULL )
2223 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2224
2225 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
anthonya322a832013-04-27 06:28:03 +00002226 IsPlusOp,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002227 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002228 break;
2229 }
anthonyafa3dfc2012-03-03 11:31:30 +00002230 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002231 {
anthony92c93bd2012-03-19 14:02:47 +00002232 (void) CloneString(&_draw_info->primitive,arg1);
2233 (void) DrawImage(_image,_draw_info,_exception);
2234 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002235 break;
2236 }
anthonyebb73a22012-03-22 14:25:52 +00002237 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002238 }
2239 case 'e':
2240 {
anthonyafa3dfc2012-03-03 11:31:30 +00002241 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002242 {
anthonyfd706f92012-01-19 04:22:02 +00002243 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002244 if ((flags & (RhoValue|SigmaValue)) == 0)
2245 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy9dc4c512013-03-24 01:38:00 +00002246 new_image=EdgeImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002247 break;
2248 }
anthonyafa3dfc2012-03-03 11:31:30 +00002249 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002250 {
anthonyfd706f92012-01-19 04:22:02 +00002251 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002252 if ((flags & (RhoValue|SigmaValue)) == 0)
2253 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002254 if ((flags & SigmaValue) == 0)
2255 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002256 new_image=EmbossImage(_image,geometry_info.rho,
2257 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002258 break;
2259 }
anthonyafa3dfc2012-03-03 11:31:30 +00002260 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002261 {
anthony4837ac22012-05-18 23:39:48 +00002262 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002263 StringInfo
2264 *passkey;
2265
cristy3a5987c2013-11-07 14:18:46 +00002266 passkey=FileToStringInfo(arg1,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002267 if (passkey != (StringInfo *) NULL)
2268 {
anthony92c93bd2012-03-19 14:02:47 +00002269 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002270 passkey=DestroyStringInfo(passkey);
2271 }
2272 break;
2273 }
anthonyafa3dfc2012-03-03 11:31:30 +00002274 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002275 {
anthony92c93bd2012-03-19 14:02:47 +00002276 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002277 break;
2278 }
anthonyafa3dfc2012-03-03 11:31:30 +00002279 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002280 {
anthony92c93bd2012-03-19 14:02:47 +00002281 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002282 break;
2283 }
anthonyafa3dfc2012-03-03 11:31:30 +00002284 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002285 {
2286 double
2287 constant;
2288
anthony2a0ec8c2012-03-24 04:35:56 +00002289 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2290 if ( parse < 0 )
2291 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2292 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002293 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002294 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002295 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002296 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2297 _exception);
anthony805a2d42011-09-25 08:25:12 +00002298 break;
2299 }
anthonyafa3dfc2012-03-03 11:31:30 +00002300 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002301 {
anthony7bcfe7f2012-03-30 14:01:22 +00002302 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002303 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002304 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002305 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002306 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002307 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002308 geometry.height=_image->rows;
2309 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002310 break;
2311 }
anthonyebb73a22012-03-22 14:25:52 +00002312 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002313 }
2314 case 'f':
2315 {
anthonyafa3dfc2012-03-03 11:31:30 +00002316 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002317 {
anthony92c93bd2012-03-19 14:02:47 +00002318 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002319 break;
2320 }
anthonyafa3dfc2012-03-03 11:31:30 +00002321 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002322 {
anthony92c93bd2012-03-19 14:02:47 +00002323 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002324 break;
2325 }
anthonyafa3dfc2012-03-03 11:31:30 +00002326 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002327 {
2328 PixelInfo
2329 target;
2330
anthony7bcfe7f2012-03-30 14:01:22 +00002331 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002332 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002333 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2334 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2335 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
anthonya322a832013-04-27 06:28:03 +00002336 geometry.y,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002337 break;
2338 }
anthonyafa3dfc2012-03-03 11:31:30 +00002339 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002340 {
2341 FrameInfo
2342 frame_info;
2343
anthony31f1bf72012-01-30 12:37:22 +00002344 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002345 compose;
2346
2347 const char*
2348 value;
2349
anthony92c93bd2012-03-19 14:02:47 +00002350 value=GetImageOption(_image_info,"compose");
anthony92c93bd2012-03-19 14:02:47 +00002351 compose=OverCompositeOp; /* use Over not _image->compose */
cristy4b892612012-08-03 19:31:31 +00002352 if (value != (const char *) NULL)
2353 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2354 MagickFalse,value);
anthony7bcfe7f2012-03-30 14:01:22 +00002355 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002356 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002357 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002358 frame_info.width=geometry.width;
2359 frame_info.height=geometry.height;
anthony805a2d42011-09-25 08:25:12 +00002360 frame_info.outer_bevel=geometry.x;
2361 frame_info.inner_bevel=geometry.y;
2362 frame_info.x=(ssize_t) frame_info.width;
2363 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002364 frame_info.width=_image->columns+2*frame_info.width;
2365 frame_info.height=_image->rows+2*frame_info.height;
2366 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002367 break;
2368 }
anthonyafa3dfc2012-03-03 11:31:30 +00002369 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002370 {
anthony805a2d42011-09-25 08:25:12 +00002371 double
anthonyb1d483a2012-04-14 12:53:56 +00002372 *args;
anthony805a2d42011-09-25 08:25:12 +00002373
anthonyb1d483a2012-04-14 12:53:56 +00002374 ssize_t
2375 count;
anthony805a2d42011-09-25 08:25:12 +00002376
anthony2a0ec8c2012-03-24 04:35:56 +00002377 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2378 if ( parse < 0 )
2379 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2380 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002381 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002382 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002383 if (args == (double *)NULL )
2384 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2385
2386 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2387 _exception);
2388 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002389 break;
2390 }
anthonyebb73a22012-03-22 14:25:52 +00002391 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002392 }
2393 case 'g':
2394 {
anthonyafa3dfc2012-03-03 11:31:30 +00002395 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002396 {
anthony7a4d6102012-07-01 09:48:25 +00002397 double
2398 constant;
2399
anthony7bcfe7f2012-03-30 14:01:22 +00002400 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002401 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony7a4d6102012-07-01 09:48:25 +00002402 constant=StringToDouble(arg1,(char **) NULL);
2403#if 0
2404 /* Using Gamma, via a cache */
2405 if (IfPlusOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002406 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002407 (void) GammaImage(_image,constant,_exception);
2408#else
2409 /* Using Evaluate POW, direct update of values - more accurite */
anthonyafa3dfc2012-03-03 11:31:30 +00002410 if (IfNormalOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002411 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002412 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
2413#endif
2414 /* Set gamma setting -- Old meaning of "+gamma"
2415 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2416 */
anthony805a2d42011-09-25 08:25:12 +00002417 break;
2418 }
anthony975a8d72012-04-12 13:54:36 +00002419 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002420 {
anthonyfd706f92012-01-19 04:22:02 +00002421 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002422 if ((flags & (RhoValue|SigmaValue)) == 0)
2423 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002424 if ((flags & SigmaValue) == 0)
2425 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002426 new_image=GaussianBlurImage(_image,geometry_info.rho,
2427 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002428 break;
2429 }
anthony975a8d72012-04-12 13:54:36 +00002430 if (LocaleCompare("gaussian",option+1) == 0)
2431 {
anthony464f1c42012-04-22 08:51:01 +00002432 CLIWandWarnReplaced("-gaussian-blur");
anthony975a8d72012-04-12 13:54:36 +00002433 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2434 }
anthonyafa3dfc2012-03-03 11:31:30 +00002435 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002436 {
anthonyfd706f92012-01-19 04:22:02 +00002437 /*
anthony31f1bf72012-01-30 12:37:22 +00002438 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002439 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002440 FUTURE: Why if no 'offset' does this resize ALL images?
2441 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002442 */
anthonyafa3dfc2012-03-03 11:31:30 +00002443 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002444 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002445 if (_image->geometry != (char *) NULL)
2446 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002447 break;
2448 }
anthony7bcfe7f2012-03-30 14:01:22 +00002449 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002450 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002451 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002452 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002453 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002454 else
anthony92c93bd2012-03-19 14:02:47 +00002455 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002456 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002457 break;
2458 }
cristyab943592013-03-29 16:47:23 +00002459 if (LocaleCompare("grayscale",option+1) == 0)
cristye0b9b8f2013-03-28 12:39:39 +00002460 {
cristyab943592013-03-29 16:47:23 +00002461 parse=ParseCommandOption(MagickPixelIntensityOptions,
cristye0b9b8f2013-03-28 12:39:39 +00002462 MagickFalse,arg1);
cristyab943592013-03-29 16:47:23 +00002463 if (parse < 0)
2464 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
2465 option,arg1);
2466 (void) GrayscaleImage(_image,(PixelIntensityMethod) parse,_exception);
cristye0b9b8f2013-03-28 12:39:39 +00002467 break;
2468 }
anthonyebb73a22012-03-22 14:25:52 +00002469 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002470 }
anthony805a2d42011-09-25 08:25:12 +00002471 case 'i':
2472 {
anthonyafa3dfc2012-03-03 11:31:30 +00002473 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002474 {
anthony31f1bf72012-01-30 12:37:22 +00002475 const char
2476 *format,
anthony805a2d42011-09-25 08:25:12 +00002477 *text;
2478
anthony92c93bd2012-03-19 14:02:47 +00002479 format=GetImageOption(_image_info,"format");
cristyf9b9b662013-05-25 12:50:16 +00002480 if (format == (char *) NULL)
2481 {
2482 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2483 _exception);
2484 break;
2485 }
anthony92c93bd2012-03-19 14:02:47 +00002486 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002487 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002488 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
cristyf9b9b662013-05-25 12:50:16 +00002489 option);
anthony805a2d42011-09-25 08:25:12 +00002490 (void) fputs(text,stdout);
anthony31f1bf72012-01-30 12:37:22 +00002491 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002492 break;
2493 }
anthonyafa3dfc2012-03-03 11:31:30 +00002494 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002495 {
anthonyb1e21ed2012-04-20 12:43:12 +00002496 flags=ParseGeometry(arg1,&geometry_info);
2497 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002498 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002499 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2500 _exception);
anthony805a2d42011-09-25 08:25:12 +00002501 break;
2502 }
anthonyafa3dfc2012-03-03 11:31:30 +00002503 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002504 {
anthonyfe1aa782012-03-24 13:43:04 +00002505 /* FUTURE: New to IMv7
2506 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002507 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002508 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002509 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2510 new_image=InterpolativeResizeImage(_image,geometry.width,
2511 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002512 break;
2513 }
anthonyebb73a22012-03-22 14:25:52 +00002514 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002515 }
2516 case 'l':
2517 {
anthonyafa3dfc2012-03-03 11:31:30 +00002518 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002519 {
anthonyfd706f92012-01-19 04:22:02 +00002520 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002521 if ((flags & (RhoValue|SigmaValue)) == 0)
2522 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyb5c691e2012-09-14 17:12:40 +00002523 if ((flags & SigmaValue) == 0)
2524 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00002525 if ((flags & PercentValue) != 0)
2526 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002527 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002528 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002529 _exception);
anthony805a2d42011-09-25 08:25:12 +00002530 break;
2531 }
anthonyafa3dfc2012-03-03 11:31:30 +00002532 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002533 {
cristya19f1d72012-08-07 18:24:38 +00002534 double
anthony805a2d42011-09-25 08:25:12 +00002535 black_point,
2536 gamma,
2537 white_point;
2538
2539 MagickStatusType
2540 flags;
2541
anthonyfd706f92012-01-19 04:22:02 +00002542 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002543 if ((flags & RhoValue) == 0)
2544 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002545 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002546 white_point=(double) QuantumRange;
anthony805a2d42011-09-25 08:25:12 +00002547 if ((flags & SigmaValue) != 0)
2548 white_point=geometry_info.sigma;
2549 gamma=1.0;
2550 if ((flags & XiValue) != 0)
2551 gamma=geometry_info.xi;
2552 if ((flags & PercentValue) != 0)
2553 {
cristya19f1d72012-08-07 18:24:38 +00002554 black_point*=(double) (QuantumRange/100.0);
2555 white_point*=(double) (QuantumRange/100.0);
anthony805a2d42011-09-25 08:25:12 +00002556 }
2557 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002558 white_point=(double) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002559 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002560 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002561 else
anthony92c93bd2012-03-19 14:02:47 +00002562 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002563 break;
2564 }
anthonyafa3dfc2012-03-03 11:31:30 +00002565 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002566 {
2567 char
2568 token[MaxTextExtent];
2569
2570 const char
2571 *p;
2572
2573 PixelInfo
2574 black_point,
2575 white_point;
2576
anthonyfd706f92012-01-19 04:22:02 +00002577 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002578 GetMagickToken(p,&p,token); /* get black point color */
2579 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002580 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002581 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002582 else
cristy269c9412011-10-13 23:41:15 +00002583 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002584 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002585 if (isalpha((int) token[0]) || (token[0] == '#'))
2586 GetMagickToken(p,&p,token);
2587 if (*token == '\0')
2588 white_point=black_point; /* set everything to that color */
2589 else
2590 {
2591 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2592 GetMagickToken(p,&p,token); /* Get white point color. */
2593 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002594 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002595 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002596 else
cristy269c9412011-10-13 23:41:15 +00002597 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002598 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002599 }
anthony92c93bd2012-03-19 14:02:47 +00002600 (void) LevelImageColors(_image,&black_point,&white_point,
anthonya322a832013-04-27 06:28:03 +00002601 IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002602 break;
2603 }
anthonyafa3dfc2012-03-03 11:31:30 +00002604 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002605 {
2606 double
2607 black_point,
2608 white_point;
2609
2610 MagickStatusType
2611 flags;
2612
anthonyfd706f92012-01-19 04:22:02 +00002613 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002614 if ((flags & RhoValue) == 0)
2615 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002616 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002617 white_point=(double) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002618 if ((flags & SigmaValue) != 0)
2619 white_point=geometry_info.sigma;
2620 if ((flags & PercentValue) != 0)
2621 {
anthony92c93bd2012-03-19 14:02:47 +00002622 black_point*=(double) _image->columns*_image->rows/100.0;
2623 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002624 }
2625 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002626 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002627 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002628 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002629 break;
2630 }
anthonyafa3dfc2012-03-03 11:31:30 +00002631 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002632 {
anthonyfe1aa782012-03-24 13:43:04 +00002633 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002634 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002635 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002636 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002637 if ((flags & XValue) == 0)
2638 geometry.x=1;
2639 if ((flags & YValue) == 0)
2640 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002641 new_image=LiquidRescaleImage(_image,geometry.width,
2642 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002643 break;
2644 }
anthonyebb73a22012-03-22 14:25:52 +00002645 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002646 }
2647 case 'm':
2648 {
cristy7220ee42013-04-14 01:30:34 +00002649 if (LocaleCompare("magnify",option+1) == 0)
2650 {
2651 new_image=MagnifyImage(_image,_exception);
2652 break;
2653 }
anthonyafa3dfc2012-03-03 11:31:30 +00002654 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002655 {
anthony464f1c42012-04-22 08:51:01 +00002656 CLIWandWarnReplaced("-remap");
anthony975a8d72012-04-12 13:54:36 +00002657 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
anthony805a2d42011-09-25 08:25:12 +00002658 break;
2659 }
anthonyafa3dfc2012-03-03 11:31:30 +00002660 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002661 {
anthony4837ac22012-05-18 23:39:48 +00002662 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002663 Image
2664 *mask;
2665
anthonyafa3dfc2012-03-03 11:31:30 +00002666 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002667 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002668 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002669 break;
2670 }
anthony5330ae02012-03-20 14:17:01 +00002671 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002672 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002673 if (mask == (Image *) NULL)
2674 break;
anthony92c93bd2012-03-19 14:02:47 +00002675 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002676 mask=DestroyImage(mask);
2677 break;
2678 }
cristy52ad9e92013-02-08 23:23:29 +00002679 if (LocaleCompare("matte",option+1) == 0)
2680 {
2681 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2682 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2683 DeactivateAlphaChannel, _exception);
2684 break;
2685 }
2686 if (LocaleCompare("median",option+1) == 0)
2687 {
2688 CLIWandWarnReplaced("-statistic Median");
2689 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2690 break;
2691 }
2692 if (LocaleCompare("mode",option+1) == 0)
2693 {
2694 /* FUTURE: note this is also a special "montage" option */
2695 CLIWandWarnReplaced("-statistic Mode");
2696 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
2697 break;
2698 }
anthonyafa3dfc2012-03-03 11:31:30 +00002699 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002700 {
anthony7bcfe7f2012-03-30 14:01:22 +00002701 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002702 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002703 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002704 break;
2705 }
anthonyafa3dfc2012-03-03 11:31:30 +00002706 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002707 {
anthony92c93bd2012-03-19 14:02:47 +00002708 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002709 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002710 break;
2711 }
anthonyafa3dfc2012-03-03 11:31:30 +00002712 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002713 {
anthony92c93bd2012-03-19 14:02:47 +00002714 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002715 break;
2716 }
anthonyafa3dfc2012-03-03 11:31:30 +00002717 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002718 {
2719 char
2720 token[MaxTextExtent];
2721
2722 const char
2723 *p;
2724
2725 KernelInfo
2726 *kernel;
2727
anthony805a2d42011-09-25 08:25:12 +00002728 ssize_t
2729 iterations;
2730
anthonyfd706f92012-01-19 04:22:02 +00002731 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002732 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002733 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2734 if ( parse < 0 )
2735 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2736 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002737 iterations=1L;
2738 GetMagickToken(p,&p,token);
2739 if ((*p == ':') || (*p == ','))
2740 GetMagickToken(p,&p,token);
2741 if ((*p != '\0'))
2742 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002743 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002744 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002745 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2746 option,arg2);
2747 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2748 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002749 kernel=DestroyKernelInfo(kernel);
2750 break;
2751 }
anthonyafa3dfc2012-03-03 11:31:30 +00002752 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002753 {
anthonyfd706f92012-01-19 04:22:02 +00002754 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002755 if ((flags & (RhoValue|SigmaValue)) == 0)
2756 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002757 if ((flags & SigmaValue) == 0)
2758 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002759 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002760 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002761 break;
2762 }
anthonyebb73a22012-03-22 14:25:52 +00002763 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002764 }
2765 case 'n':
2766 {
anthonyafa3dfc2012-03-03 11:31:30 +00002767 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002768 {
anthonya322a832013-04-27 06:28:03 +00002769 (void) NegateImage(_image, IsPlusOp, _exception);
anthony805a2d42011-09-25 08:25:12 +00002770 break;
2771 }
anthonyafa3dfc2012-03-03 11:31:30 +00002772 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002773 {
anthony975a8d72012-04-12 13:54:36 +00002774 double
2775 attenuate;
2776
2777 const char*
2778 value;
2779
anthonyafa3dfc2012-03-03 11:31:30 +00002780 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002781 {
anthony464f1c42012-04-22 08:51:01 +00002782 CLIWandWarnReplaced("-statistic NonPeak");
anthony975a8d72012-04-12 13:54:36 +00002783 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2784 break;
anthony805a2d42011-09-25 08:25:12 +00002785 }
anthony975a8d72012-04-12 13:54:36 +00002786 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2787 if ( parse < 0 )
2788 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2789 option,arg1);
2790 attenuate=1.0;
2791 value=GetImageOption(_image_info,"attenuate");
2792 if (value != (const char *) NULL)
2793 attenuate=StringToDouble(value,(char **) NULL);
2794 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2795 _exception);
anthony805a2d42011-09-25 08:25:12 +00002796 break;
2797 }
anthonyafa3dfc2012-03-03 11:31:30 +00002798 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002799 {
anthony92c93bd2012-03-19 14:02:47 +00002800 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002801 break;
2802 }
anthonyebb73a22012-03-22 14:25:52 +00002803 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002804 }
2805 case 'o':
2806 {
anthonyafa3dfc2012-03-03 11:31:30 +00002807 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002808 {
2809 PixelInfo
2810 target;
2811
anthony92c93bd2012-03-19 14:02:47 +00002812 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
anthonya322a832013-04-27 06:28:03 +00002813 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,IsPlusOp,
anthony92c93bd2012-03-19 14:02:47 +00002814 _exception);
anthony805a2d42011-09-25 08:25:12 +00002815 break;
2816 }
anthonyafa3dfc2012-03-03 11:31:30 +00002817 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002818 {
anthony92c93bd2012-03-19 14:02:47 +00002819 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002820 break;
2821 }
anthonyebb73a22012-03-22 14:25:52 +00002822 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002823 }
2824 case 'p':
2825 {
anthonyafa3dfc2012-03-03 11:31:30 +00002826 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002827 {
anthony22de2722012-04-19 14:43:00 +00002828 flags=ParseGeometry(arg1,&geometry_info);
2829 if ((flags & (RhoValue|SigmaValue)) == 0)
2830 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002831 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2832 _exception);
anthony805a2d42011-09-25 08:25:12 +00002833 break;
2834 }
cristy7884a932012-11-04 14:33:51 +00002835 if (LocaleCompare("perceptible",option+1) == 0)
2836 {
2837 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2838 _exception);
2839 break;
2840 }
anthonyafa3dfc2012-03-03 11:31:30 +00002841 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002842 {
cristye9e3d382011-12-14 01:50:13 +00002843 const char
2844 *caption;
2845
anthony805a2d42011-09-25 08:25:12 +00002846 double
2847 angle;
2848
anthony7bc87992012-03-25 02:32:51 +00002849 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002850 RandomInfo
2851 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002852
anthonyf42014d2012-03-25 09:53:06 +00002853 random_info=AcquireRandomInfo();
2854 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2855 random_info=DestroyRandomInfo(random_info);
2856 }
anthony7bc87992012-03-25 02:32:51 +00002857 else {
anthonyf42014d2012-03-25 09:53:06 +00002858 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002859 if ((flags & RhoValue) == 0)
2860 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002861 angle=geometry_info.rho;
2862 }
anthony92c93bd2012-03-19 14:02:47 +00002863 caption=GetImageProperty(_image,"caption",_exception);
2864 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2865 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002866 break;
2867 }
anthonyafa3dfc2012-03-03 11:31:30 +00002868 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002869 {
anthony22de2722012-04-19 14:43:00 +00002870 flags=ParseGeometry(arg1,&geometry_info);
2871 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002872 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002873 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002874 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002875 break;
2876 }
anthonyafa3dfc2012-03-03 11:31:30 +00002877 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002878 {
anthony31f1bf72012-01-30 12:37:22 +00002879 /* FUTURE: should be a 'Genesis' option?
2880 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002881 Why???
cristy947cb4c2011-10-20 18:41:46 +00002882 */
anthony7bc87992012-03-25 02:32:51 +00002883 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2884 if ( parse < 0 )
2885 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2886 option,arg1);
2887 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002888 break;
2889 }
anthonyafa3dfc2012-03-03 11:31:30 +00002890 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002891 {
anthony4837ac22012-05-18 23:39:48 +00002892 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002893 const char
2894 *name;
2895
2896 const StringInfo
2897 *profile;
2898
2899 Image
2900 *profile_image;
2901
2902 ImageInfo
2903 *profile_info;
2904
anthonyafa3dfc2012-03-03 11:31:30 +00002905 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002906 { /* Remove a profile from the _image. */
2907 (void) ProfileImage(_image,arg1,(const unsigned char *)
2908 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002909 break;
2910 }
anthony92c93bd2012-03-19 14:02:47 +00002911 /* Associate a profile with the _image. */
2912 profile_info=CloneImageInfo(_image_info);
2913 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002914 if (profile != (StringInfo *) NULL)
2915 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002916 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002917 profile_info=DestroyImageInfo(profile_info);
2918 if (profile_image == (Image *) NULL)
2919 {
2920 StringInfo
2921 *profile;
2922
anthony92c93bd2012-03-19 14:02:47 +00002923 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002924 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002925 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002926 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002927 if (profile != (StringInfo *) NULL)
2928 {
anthony92c93bd2012-03-19 14:02:47 +00002929 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002930 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002931 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002932 profile=DestroyStringInfo(profile);
2933 }
2934 profile_info=DestroyImageInfo(profile_info);
2935 break;
2936 }
2937 ResetImageProfileIterator(profile_image);
2938 name=GetNextImageProfile(profile_image);
2939 while (name != (const char *) NULL)
2940 {
2941 profile=GetImageProfile(profile_image,name);
2942 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002943 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2944 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002945 name=GetNextImageProfile(profile_image);
2946 }
2947 profile_image=DestroyImage(profile_image);
2948 break;
2949 }
anthonyebb73a22012-03-22 14:25:52 +00002950 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002951 }
anthony805a2d42011-09-25 08:25:12 +00002952 case 'r':
2953 {
anthonyafa3dfc2012-03-03 11:31:30 +00002954 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002955 {
anthonyfd706f92012-01-19 04:22:02 +00002956 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002957 if ((flags & RhoValue) == 0)
2958 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyaa2c16c2012-03-25 22:21:35 +00002959 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002960 break;
2961 }
anthonyafa3dfc2012-03-03 11:31:30 +00002962 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002963 {
anthony7bcfe7f2012-03-30 14:01:22 +00002964 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002965 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002966 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthonya322a832013-04-27 06:28:03 +00002967 (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002968 break;
2969 }
anthonyafa3dfc2012-03-03 11:31:30 +00002970 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002971 {
anthony7bcfe7f2012-03-30 14:01:22 +00002972 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002973 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002974 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002975 break;
2976 }
anthony975a8d72012-04-12 13:54:36 +00002977 if (LocaleCompare("recolor",option+1) == 0)
2978 {
anthony464f1c42012-04-22 08:51:01 +00002979 CLIWandWarnReplaced("-color-matrix");
anthony975a8d72012-04-12 13:54:36 +00002980 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2981 }
anthonyafa3dfc2012-03-03 11:31:30 +00002982 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002983 {
anthony4837ac22012-05-18 23:39:48 +00002984 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002985 Image
2986 *remap_image;
2987
anthony92c93bd2012-03-19 14:02:47 +00002988 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002989 if (remap_image == (Image *) NULL)
2990 break;
anthony92c93bd2012-03-19 14:02:47 +00002991 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002992 remap_image=DestroyImage(remap_image);
2993 break;
2994 }
anthonyafa3dfc2012-03-03 11:31:30 +00002995 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002996 {
anthonyafa3dfc2012-03-03 11:31:30 +00002997 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00002998 {
anthony7bcfe7f2012-03-30 14:01:22 +00002999 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00003000 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3001 arg1);
3002 (void) ResetImagePage(_image,arg1);
3003 }
anthony31f1bf72012-01-30 12:37:22 +00003004 else
anthony92c93bd2012-03-19 14:02:47 +00003005 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003006 break;
3007 }
anthonyafa3dfc2012-03-03 11:31:30 +00003008 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003009 {
anthonyf46d4262012-03-26 03:30:34 +00003010 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00003011 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003012 if ((flags & (RhoValue|SigmaValue)) == 0)
3013 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003014 if ((flags & SigmaValue) == 0)
3015 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003016 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003017 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003018 break;
3019 }
anthonyafa3dfc2012-03-03 11:31:30 +00003020 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003021 {
anthony7bcfe7f2012-03-30 14:01:22 +00003022 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003023 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003024 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3025 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003026 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003027 break;
3028 }
anthonyafa3dfc2012-03-03 11:31:30 +00003029 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003030 {
anthony7bcfe7f2012-03-30 14:01:22 +00003031 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003032 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003033 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3034 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003035 break;
3036 }
anthonyafa3dfc2012-03-03 11:31:30 +00003037 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003038 {
anthony22de2722012-04-19 14:43:00 +00003039 flags=ParseGeometry(arg1,&geometry_info);
3040 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003041 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003042 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003043 break;
3044 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3045 break;
anthony92c93bd2012-03-19 14:02:47 +00003046 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003047 break;
3048 }
anthonyebb73a22012-03-22 14:25:52 +00003049 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003050 }
3051 case 's':
3052 {
anthonyafa3dfc2012-03-03 11:31:30 +00003053 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003054 {
anthonyfe1aa782012-03-24 13:43:04 +00003055 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003056 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003057 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003058 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3059 new_image=SampleImage(_image,geometry.width,geometry.height,
3060 _exception);
anthony805a2d42011-09-25 08:25:12 +00003061 break;
3062 }
anthonyafa3dfc2012-03-03 11:31:30 +00003063 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003064 {
anthonyfe1aa782012-03-24 13:43:04 +00003065 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003066 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003067 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003068 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3069 new_image=ScaleImage(_image,geometry.width,geometry.height,
3070 _exception);
anthony805a2d42011-09-25 08:25:12 +00003071 break;
3072 }
anthonyf42014d2012-03-25 09:53:06 +00003073 if (LocaleCompare("segment",option+1) == 0)
3074 {
anthonyf42014d2012-03-25 09:53:06 +00003075 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003076 if ((flags & (RhoValue|SigmaValue)) == 0)
3077 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003078 if ((flags & SigmaValue) == 0)
3079 geometry_info.sigma=1.0;
3080 (void) SegmentImage(_image,_image->colorspace,
3081 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3082 _exception);
3083 break;
3084 }
anthonyafa3dfc2012-03-03 11:31:30 +00003085 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003086 {
anthonyfd706f92012-01-19 04:22:02 +00003087 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003088 if ((flags & (RhoValue|SigmaValue)) == 0)
3089 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3090 if ((flags & SigmaValue) == 0)
3091 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003092 if ((flags & PercentValue) != 0)
3093 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003094 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003095 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003096 break;
3097 }
anthonyafa3dfc2012-03-03 11:31:30 +00003098 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003099 {
anthony31f1bf72012-01-30 12:37:22 +00003100 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003101 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003102 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003103 break;
3104 }
anthonyafa3dfc2012-03-03 11:31:30 +00003105 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003106 {
anthony7bcfe7f2012-03-30 14:01:22 +00003107 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003108 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3109 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3110 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003111 break;
3112 }
anthonyafa3dfc2012-03-03 11:31:30 +00003113 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003114 {
anthonyfd706f92012-01-19 04:22:02 +00003115 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003116 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3117 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya322a832013-04-27 06:28:03 +00003118 new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
anthony92c93bd2012-03-19 14:02:47 +00003119 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003120 break;
3121 }
anthonyafa3dfc2012-03-03 11:31:30 +00003122 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003123 {
anthonyfd706f92012-01-19 04:22:02 +00003124 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003125 if ((flags & (RhoValue|SigmaValue)) == 0)
3126 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003127 if ((flags & SigmaValue) == 0)
3128 geometry_info.sigma=1.0;
3129 if ((flags & XiValue) == 0)
3130 geometry_info.xi=4.0;
3131 if ((flags & PsiValue) == 0)
3132 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003133 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3134 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3135 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003136 break;
3137 }
anthonyafa3dfc2012-03-03 11:31:30 +00003138 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003139 {
anthonyfd706f92012-01-19 04:22:02 +00003140 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003141 if ((flags & (RhoValue|SigmaValue)) == 0)
3142 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003143 if ((flags & SigmaValue) == 0)
3144 geometry_info.sigma=1.0;
3145 if ((flags & XiValue) == 0)
3146 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003147 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3148 _exception);
anthony805a2d42011-09-25 08:25:12 +00003149 break;
3150 }
anthonyafa3dfc2012-03-03 11:31:30 +00003151 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003152 {
anthony7bcfe7f2012-03-30 14:01:22 +00003153 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003154 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003155 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3156 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003157 break;
3158 }
anthonyafa3dfc2012-03-03 11:31:30 +00003159 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003160 {
anthonyfd706f92012-01-19 04:22:02 +00003161 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003162 if ((flags & RhoValue) == 0)
3163 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003164 if ((flags & SigmaValue) == 0)
3165 geometry_info.sigma=geometry_info.rho;
cristy4b892612012-08-03 19:31:31 +00003166 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3167 _exception);
anthony805a2d42011-09-25 08:25:12 +00003168 break;
3169 }
anthonyafa3dfc2012-03-03 11:31:30 +00003170 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003171 {
anthonyfd706f92012-01-19 04:22:02 +00003172 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003173 if ((flags & RhoValue) == 0)
3174 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003175 if ((flags & SigmaValue) == 0)
3176 geometry_info.sigma=(double) QuantumRange/2.0;
3177 if ((flags & PercentValue) != 0)
3178 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3179 100.0;
anthonya322a832013-04-27 06:28:03 +00003180 (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003181 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003182 break;
3183 }
anthonyafa3dfc2012-03-03 11:31:30 +00003184 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003185 {
anthonyfd706f92012-01-19 04:22:02 +00003186 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003187 if ((flags & (RhoValue|SigmaValue)) == 0)
3188 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003189 if ((flags & SigmaValue) == 0)
3190 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003191 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003192 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003193 break;
3194 }
anthonyafa3dfc2012-03-03 11:31:30 +00003195 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003196 {
anthony7bcfe7f2012-03-30 14:01:22 +00003197 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003199 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3200 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003201 break;
3202 }
anthonyafa3dfc2012-03-03 11:31:30 +00003203 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003204 {
anthonyf42014d2012-03-25 09:53:06 +00003205 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3206 if ( parse < 0 )
3207 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3208 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003209 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3210 _exception);
anthony805a2d42011-09-25 08:25:12 +00003211 break;
3212 }
anthonyafa3dfc2012-03-03 11:31:30 +00003213 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003214 {
anthony7bcfe7f2012-03-30 14:01:22 +00003215 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003216 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003217 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003218 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003219 break;
3220 }
anthonyafa3dfc2012-03-03 11:31:30 +00003221 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003222 {
anthonyb1e21ed2012-04-20 12:43:12 +00003223 flags=ParseGeometry(arg1,&geometry_info);
3224 if ((flags & RhoValue) == 0)
3225 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003226 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3227 _exception);
anthony805a2d42011-09-25 08:25:12 +00003228 break;
3229 }
anthonyafa3dfc2012-03-03 11:31:30 +00003230 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003231 {
anthony7bc87992012-03-25 02:32:51 +00003232 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3233 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003234 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003235 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003236 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003237 if ((flags & RhoValue) == 0)
3238 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003239 if ((flags & SigmaValue) == 0)
3240 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003241 new_image=StatisticImage(_image,(StatisticType)parse,
3242 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3243 _exception);
anthony805a2d42011-09-25 08:25:12 +00003244 break;
3245 }
anthonyafa3dfc2012-03-03 11:31:30 +00003246 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003247 {
anthony92c93bd2012-03-19 14:02:47 +00003248 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003249 break;
3250 }
anthonyafa3dfc2012-03-03 11:31:30 +00003251 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003252 {
cristy898c6042012-06-24 00:36:34 +00003253 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00003254 if ((flags & RhoValue) == 0)
cristy898c6042012-06-24 00:36:34 +00003255 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003256 new_image=SwirlImage(_image,geometry_info.rho,
3257 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003258 break;
3259 }
anthonyebb73a22012-03-22 14:25:52 +00003260 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003261 }
3262 case 't':
3263 {
anthonyafa3dfc2012-03-03 11:31:30 +00003264 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003265 {
3266 double
3267 threshold;
3268
anthony52bef752012-03-27 13:54:47 +00003269 threshold=(double) QuantumRange/2;
anthonya322a832013-04-27 06:28:03 +00003270 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00003271 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003272 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003273 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003274 }
anthony92c93bd2012-03-19 14:02:47 +00003275 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003276 break;
3277 }
anthonyafa3dfc2012-03-03 11:31:30 +00003278 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003279 {
anthony7bcfe7f2012-03-30 14:01:22 +00003280 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003281 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003282 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3283 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3284 _exception);
anthony805a2d42011-09-25 08:25:12 +00003285 break;
3286 }
anthonyafa3dfc2012-03-03 11:31:30 +00003287 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003288 {
anthony7bcfe7f2012-03-30 14:01:22 +00003289 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003290 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003291 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003292 break;
3293 }
anthonyafa3dfc2012-03-03 11:31:30 +00003294 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003295 {
anthony464f1c42012-04-22 08:51:01 +00003296 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003297 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003298 break;
3299 }
anthonyafa3dfc2012-03-03 11:31:30 +00003300 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003301 {
3302 PixelInfo
3303 target;
3304
anthony92c93bd2012-03-19 14:02:47 +00003305 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3306 (void) TransparentPaintImage(_image,&target,(Quantum)
anthonya322a832013-04-27 06:28:03 +00003307 TransparentAlpha,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003308 break;
3309 }
anthonyafa3dfc2012-03-03 11:31:30 +00003310 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003311 {
anthony92c93bd2012-03-19 14:02:47 +00003312 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003313 break;
3314 }
anthonyafa3dfc2012-03-03 11:31:30 +00003315 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003316 {
anthony92c93bd2012-03-19 14:02:47 +00003317 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003318 break;
3319 }
anthonyafa3dfc2012-03-03 11:31:30 +00003320 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003321 {
anthony92c93bd2012-03-19 14:02:47 +00003322 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003323 break;
3324 }
anthonyafa3dfc2012-03-03 11:31:30 +00003325 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003326 {
anthonyab3a50c2011-10-27 11:48:57 +00003327 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003328 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003329 break;
3330 }
anthonyebb73a22012-03-22 14:25:52 +00003331 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003332 }
3333 case 'u':
3334 {
anthonyafa3dfc2012-03-03 11:31:30 +00003335 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003336 {
anthony52bef752012-03-27 13:54:47 +00003337 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3338 Option is not documented, bt appears to be for "identify".
3339 We may need a identify specific verbose!
3340 */
anthonya322a832013-04-27 06:28:03 +00003341 if (IsPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00003342 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003343 break;
3344 }
anthony92c93bd2012-03-19 14:02:47 +00003345 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3346 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003347 break;
3348 }
anthonyafa3dfc2012-03-03 11:31:30 +00003349 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003350 {
anthony92c93bd2012-03-19 14:02:47 +00003351 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003352 break;
3353 }
anthonyafa3dfc2012-03-03 11:31:30 +00003354 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003355 {
anthonyfd706f92012-01-19 04:22:02 +00003356 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003357 if ((flags & (RhoValue|SigmaValue)) == 0)
3358 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003359 if ((flags & SigmaValue) == 0)
3360 geometry_info.sigma=1.0;
3361 if ((flags & XiValue) == 0)
3362 geometry_info.xi=1.0;
3363 if ((flags & PsiValue) == 0)
3364 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003365 new_image=UnsharpMaskImage(_image,geometry_info.rho,
cristy3afd4012013-03-25 11:30:44 +00003366 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003367 break;
3368 }
anthonyebb73a22012-03-22 14:25:52 +00003369 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003370 }
3371 case 'v':
3372 {
anthonyafa3dfc2012-03-03 11:31:30 +00003373 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003374 {
anthonyafa3dfc2012-03-03 11:31:30 +00003375 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003376 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003377 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003378 */
anthony92c93bd2012-03-19 14:02:47 +00003379 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003380 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003381 break;
3382 }
anthonyafa3dfc2012-03-03 11:31:30 +00003383 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003384 {
anthonyfd706f92012-01-19 04:22:02 +00003385 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003386 if ((flags & (RhoValue|SigmaValue)) == 0)
3387 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003388 if ((flags & SigmaValue) == 0)
3389 geometry_info.sigma=1.0;
3390 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003391 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003392 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003393 geometry_info.psi=0.1*_image->rows;
cristy8e2392e2013-11-11 17:58:38 +00003394 if ((flags & PercentValue) != 0)
3395 {
cristy720d7562013-11-14 19:18:11 +00003396 geometry_info.xi*=(double) _image->columns/100.0;
3397 geometry_info.psi*=(double) _image->rows/100.0;
cristy8e2392e2013-11-11 17:58:38 +00003398 }
anthony92c93bd2012-03-19 14:02:47 +00003399 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003400 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3401 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003402 break;
3403 }
anthonyebb73a22012-03-22 14:25:52 +00003404 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003405 }
3406 case 'w':
3407 {
anthonyafa3dfc2012-03-03 11:31:30 +00003408 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003409 {
anthonyfd706f92012-01-19 04:22:02 +00003410 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003411 if ((flags & (RhoValue|SigmaValue)) == 0)
3412 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003413 if ((flags & SigmaValue) == 0)
3414 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003415 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3416 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003417 break;
3418 }
anthonyafa3dfc2012-03-03 11:31:30 +00003419 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003420 {
anthony7bcfe7f2012-03-30 14:01:22 +00003421 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003422 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003423 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003424 break;
3425 }
anthonyebb73a22012-03-22 14:25:52 +00003426 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003427 }
3428 default:
anthonyebb73a22012-03-22 14:25:52 +00003429 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003430 }
anthony964d28e2012-05-17 23:39:46 +00003431 /* clean up percent escape interpreted strings */
3432 if (arg1 != arg1n )
3433 arg1=DestroyString((char *)arg1);
3434 if (arg2 != arg2n )
3435 arg2=DestroyString((char *)arg2);
3436
3437 /* Replace current image with any image that was generated
3438 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003439 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003440 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003441
cristyfe831852013-02-12 14:56:07 +00003442 return(MagickTrue);
anthony92c93bd2012-03-19 14:02:47 +00003443#undef _image_info
3444#undef _draw_info
3445#undef _quantize_info
3446#undef _image
3447#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003448#undef IfNormalOp
3449#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00003450#undef IsNormalOp
3451#undef IsPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003452}
anthonyfd706f92012-01-19 04:22:02 +00003453
cristyfe831852013-02-12 14:56:07 +00003454WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
3455 const char *option,const char *arg1,const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003456{
anthonyc7994672012-11-17 05:33:27 +00003457#if !USE_WAND_METHODS
anthony31f1bf72012-01-30 12:37:22 +00003458 size_t
anthony43f425d2012-02-26 12:58:58 +00003459 n,
anthony31f1bf72012-01-30 12:37:22 +00003460 i;
anthonyc7994672012-11-17 05:33:27 +00003461#endif
anthony31f1bf72012-01-30 12:37:22 +00003462
anthony43f425d2012-02-26 12:58:58 +00003463 assert(cli_wand != (MagickCLI *) NULL);
3464 assert(cli_wand->signature == WandSignature);
3465 assert(cli_wand->wand.signature == WandSignature);
3466 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthonya322a832013-04-27 06:28:03 +00003467
anthony7bcfe7f2012-03-30 14:01:22 +00003468 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00003469 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3470 "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
anthony31f1bf72012-01-30 12:37:22 +00003471
anthonyafa3dfc2012-03-03 11:31:30 +00003472#if !USE_WAND_METHODS
3473 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003474 i=0;
anthony43f425d2012-02-26 12:58:58 +00003475 n=GetImageListLength(cli_wand->wand.images);
3476 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003477 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003478 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003479 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003480 if ( cli_wand->wand.images->next == (Image *) NULL )
3481 break;
3482 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003483 }
anthony43f425d2012-02-26 12:58:58 +00003484 assert( i == n );
3485 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003486#else
3487 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003488 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003489 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3490 MagickResetIterator(&cli_wand->wand);
3491#endif
cristyfe831852013-02-12 14:56:07 +00003492 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003493}
3494
3495/*
3496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3497% %
3498% %
3499% %
anthony43f425d2012-02-26 12:58:58 +00003500+ C L I L i s t O p e r a t o r I m a g e s %
anthony805a2d42011-09-25 08:25:12 +00003501% %
3502% %
3503% %
3504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3505%
anthony43f425d2012-02-26 12:58:58 +00003506% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003507% entire image list as a whole. The result is often a complete replacment
anthonyc7994672012-11-17 05:33:27 +00003508% of the image list with a completely new list, or with just a single image
3509% result.
anthony805a2d42011-09-25 08:25:12 +00003510%
3511% The format of the MogrifyImage method is:
3512%
cristyfe831852013-02-12 14:56:07 +00003513% MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3514% const char *option,const char *arg1,const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003515%
3516% A description of each parameter follows:
3517%
anthony43f425d2012-02-26 12:58:58 +00003518% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003519%
anthony36a8c2c2012-02-10 00:08:44 +00003520% o option: The option string for the operation
3521%
anthony31f1bf72012-01-30 12:37:22 +00003522% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003523% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003524%
anthony805a2d42011-09-25 08:25:12 +00003525*/
cristyfe831852013-02-12 14:56:07 +00003526WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3527 const char *option,const char *arg1n,const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003528{
anthonya322a832013-04-27 06:28:03 +00003529 const char /* percent escaped versions of the args */
cristya30f8e62013-02-19 15:03:45 +00003530 *arg1,
3531 *arg2;
anthony2a0ec8c2012-03-24 04:35:56 +00003532
anthony31f1bf72012-01-30 12:37:22 +00003533 Image
3534 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003535
cristya30f8e62013-02-19 15:03:45 +00003536 MagickStatusType
3537 status;
3538
3539 ssize_t
3540 parse;
anthony964d28e2012-05-17 23:39:46 +00003541
anthony2e4501b2012-03-30 04:41:54 +00003542#define _image_info (cli_wand->wand.image_info)
3543#define _images (cli_wand->wand.images)
3544#define _exception (cli_wand->wand.exception)
3545#define _draw_info (cli_wand->draw_info)
3546#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003547#define _process_flags (cli_wand->process_flags)
3548#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003549#define IfNormalOp (*option=='-')
3550#define IfPlusOp (*option!='-')
anthonya322a832013-04-27 06:28:03 +00003551#define IsNormalOp IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003552
anthony43f425d2012-02-26 12:58:58 +00003553 assert(cli_wand != (MagickCLI *) NULL);
3554 assert(cli_wand->signature == WandSignature);
3555 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003556 assert(_images != (Image *) NULL); /* _images must be present */
anthony31f1bf72012-01-30 12:37:22 +00003557
anthonya322a832013-04-27 06:28:03 +00003558 if (IfMagickTrue(cli_wand->wand.debug))
3559 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3560 "- List Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
3561
anthony964d28e2012-05-17 23:39:46 +00003562 arg1 = arg1n;
3563 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00003564
3565 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00003566 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3567 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3568 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3569 /* Interpret Percent escapes in argument 1 */
3570 if (arg1n != (char *) NULL) {
3571 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3572 if (arg1 == (char *) NULL) {
3573 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3574 arg1=arg1n; /* use the given argument as is */
3575 }
3576 }
3577 if (arg2n != (char *) NULL) {
3578 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3579 if (arg2 == (char *) NULL) {
3580 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3581 arg2=arg2n; /* use the given argument as is */
3582 }
3583 }
3584 }
anthony4837ac22012-05-18 23:39:48 +00003585#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003586#undef _option_type
3587
cristyfe831852013-02-12 14:56:07 +00003588 status=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00003589 new_images=NewImageList();
3590
anthonyafa3dfc2012-03-03 11:31:30 +00003591 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003592 {
3593 case 'a':
3594 {
anthonyafa3dfc2012-03-03 11:31:30 +00003595 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003596 {
anthonya322a832013-04-27 06:28:03 +00003597 new_images=AppendImages(_images,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003598 break;
3599 }
cristy52ad9e92013-02-08 23:23:29 +00003600 if (LocaleCompare("average",option+1) == 0)
3601 {
3602 CLIWandWarnReplaced("-evaluate-sequence Mean");
3603 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
3604 break;
3605 }
anthonyebb73a22012-03-22 14:25:52 +00003606 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003607 }
3608 case 'c':
3609 {
cristy5f257b22012-03-07 00:27:29 +00003610 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003611 {
anthony92c93bd2012-03-19 14:02:47 +00003612 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003613 break;
3614 }
anthonyafa3dfc2012-03-03 11:31:30 +00003615 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003616 {
anthony805a2d42011-09-25 08:25:12 +00003617 Image
anthony31f1bf72012-01-30 12:37:22 +00003618 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003619
anthonyafa3dfc2012-03-03 11:31:30 +00003620 /* FUTURE - make this a compose option, and thus can be used
3621 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003622 _images.
cristy87c02f42012-02-24 00:19:10 +00003623 */
anthony92c93bd2012-03-19 14:02:47 +00003624 new_images=RemoveFirstImageFromList(&_images);
3625 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003626 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003627 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003628 break;
cristye52fb5e2012-04-06 23:30:20 +00003629 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003630 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003631 break;
3632 }
anthonyafa3dfc2012-03-03 11:31:30 +00003633 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003634 {
anthony92c93bd2012-03-19 14:02:47 +00003635 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003636 break;
3637 }
anthonyafa3dfc2012-03-03 11:31:30 +00003638 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003639 {
anthony5a4ff372013-05-01 04:48:57 +00003640 parse = (ssize_t) sRGBColorspace; /* default (backward compatible) */
3641 if ( IfPlusOp )
3642 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
3643 arg1);
cristy8448a0d2013-02-15 18:20:53 +00003644 if (parse < 0)
3645 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3646 arg1);
cristy46f354c2012-07-04 13:31:29 +00003647 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003648 break;
3649 }
cristye863c052013-09-04 11:31:30 +00003650 if (LocaleCompare("compare",option+1) == 0)
3651 {
3652 double
3653 distortion;
3654
3655 Image
3656 *image,
3657 *reconstruct_image;
3658
3659 MetricType
3660 metric;
3661
3662 /*
3663 Mathematically and visually annotate the difference between an
3664 image and its reconstruction.
3665 */
3666 image=RemoveFirstImageFromList(&_images);
3667 reconstruct_image=RemoveFirstImageFromList(&_images);
3668 /* FUTURE - produce Exception, rather than silent fail */
3669 if (reconstruct_image == (Image *) NULL)
3670 break;
3671 metric=UndefinedErrorMetric;
3672 option=GetImageOption(_image_info,"metric");
3673 if (option != (const char *) NULL)
3674 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
3675 MagickFalse,option);
3676 new_images=CompareImages(image,reconstruct_image,metric,&distortion,
3677 _exception);
3678 (void) distortion;
3679 reconstruct_image=DestroyImage(reconstruct_image);
3680 image=DestroyImage(image);
3681 break;
3682 }
cristy790190d2013-10-04 00:51:51 +00003683 if (LocaleCompare("complex",option+1) == 0)
3684 {
3685 parse=ParseCommandOption(MagickComplexOptions,MagickFalse,arg1);
3686 if (parse < 0)
3687 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3688 option,arg1);
cristyb8f66bb2013-10-04 15:21:58 +00003689 new_images=ComplexImages(_images,(ComplexOperator) parse,_exception);
cristy790190d2013-10-04 00:51:51 +00003690 break;
3691 }
anthonyafa3dfc2012-03-03 11:31:30 +00003692 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003693 {
cristyfeb3e962012-03-29 17:25:55 +00003694 CompositeOperator
3695 compose;
3696
3697 const char*
3698 value;
3699
3700 MagickBooleanType
3701 clip_to_self;
3702
anthony805a2d42011-09-25 08:25:12 +00003703 Image
3704 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003705 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003706
3707 RectangleInfo
3708 geometry;
3709
anthony7bcfe7f2012-03-30 14:01:22 +00003710 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003711 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003712 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003713 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003714 else
3715 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3716 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003717
anthony7bcfe7f2012-03-30 14:01:22 +00003718 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003719 value=GetImageOption(_image_info,"compose:clip-to-self");
3720 if (value == (const char *) NULL)
3721 clip_to_self=MagickTrue;
3722 else
3723 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3724 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003725 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003726 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003727 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003728 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003729 }
3730
anthony92c93bd2012-03-19 14:02:47 +00003731 new_images=RemoveFirstImageFromList(&_images);
3732 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003733 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003734 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003735
anthony31f1bf72012-01-30 12:37:22 +00003736 /* FUTURE - this should not be here! - should be part of -geometry */
3737 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003738 source_image->geometry,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003739 SetGeometry(source_image,&geometry);
3740 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3741 GravityAdjustGeometry(new_images->columns,new_images->rows,
cristyfe831852013-02-12 14:56:07 +00003742 new_images->gravity, &geometry);
anthony92c93bd2012-03-19 14:02:47 +00003743 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003744 if (mask_image != (Image *) NULL)
cristyfe831852013-02-12 14:56:07 +00003745 {
anthony5f867ae2011-10-09 10:28:34 +00003746 if ((compose == DisplaceCompositeOp) ||
cristyfe831852013-02-12 14:56:07 +00003747 (compose == DistortCompositeOp))
3748 status&=CompositeImage(source_image,mask_image,
anthony7bcfe7f2012-03-30 14:01:22 +00003749 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
cristyfe831852013-02-12 14:56:07 +00003750 else
cristy15007e82013-02-17 18:46:40 +00003751 {
3752 Image
3753 *image;
3754
3755 RectangleInfo
3756 source_geometry;
3757
3758 source_geometry.width=mask_image->columns;
3759 source_geometry.height=mask_image->rows;
3760 source_geometry.x=(-geometry.x);
3761 source_geometry.y=(-geometry.y);
3762 geometry.x=0;
3763 geometry.y=0;
3764 image=ExtentImage(source_image,&source_geometry,_exception);
3765 if (image != (Image *) NULL)
3766 {
3767 source_image=DestroyImage(source_image);
3768 source_image=image;
3769 }
3770 status&=CompositeImage(source_image,mask_image,
3771 IntensityCompositeOp,MagickTrue,0,0,_exception);
3772 }
cristyfe831852013-02-12 14:56:07 +00003773 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003774 }
cristyfe831852013-02-12 14:56:07 +00003775 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
cristyfeb3e962012-03-29 17:25:55 +00003776 geometry.x,geometry.y,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003777 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003778 break;
3779 }
anthonyebb73a22012-03-22 14:25:52 +00003780 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003781 }
3782 case 'd':
3783 {
anthonyafa3dfc2012-03-03 11:31:30 +00003784 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003785 {
anthony464f1c42012-04-22 08:51:01 +00003786 CLIWandWarnReplaced("-layer CompareAny");
anthonyafa3dfc2012-03-03 11:31:30 +00003787 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003788 break;
3789 }
anthonyafa3dfc2012-03-03 11:31:30 +00003790 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003791 {
anthonyafa3dfc2012-03-03 11:31:30 +00003792 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003793 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003794 else
anthony92c93bd2012-03-19 14:02:47 +00003795 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003796 break;
3797 }
anthonyafa3dfc2012-03-03 11:31:30 +00003798 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003799 {
anthonyafa3dfc2012-03-03 11:31:30 +00003800 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003801 {
3802 const char
3803 *p;
3804
3805 size_t
3806 number_duplicates;
3807
anthony7bcfe7f2012-03-30 14:01:22 +00003808 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003809 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3810 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003811 number_duplicates=(size_t) StringToLong(arg1);
3812 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003813 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003814 new_images=DuplicateImages(_images,number_duplicates,"-1",
3815 _exception);
anthony805a2d42011-09-25 08:25:12 +00003816 else
anthony92c93bd2012-03-19 14:02:47 +00003817 new_images=DuplicateImages(_images,number_duplicates,p,
3818 _exception);
anthony805a2d42011-09-25 08:25:12 +00003819 }
anthonyafa3dfc2012-03-03 11:31:30 +00003820 else
anthony92c93bd2012-03-19 14:02:47 +00003821 new_images=DuplicateImages(_images,1,"-1",_exception);
3822 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003823 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003824 break;
3825 }
anthonyebb73a22012-03-22 14:25:52 +00003826 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003827 }
3828 case 'e':
3829 {
anthonyafa3dfc2012-03-03 11:31:30 +00003830 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003831 {
cristy790190d2013-10-04 00:51:51 +00003832 parse=ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3833 if (parse < 0)
anthony2a0ec8c2012-03-24 04:35:56 +00003834 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
cristy790190d2013-10-04 00:51:51 +00003835 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00003836 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
cristy790190d2013-10-04 00:51:51 +00003837 _exception);
anthony805a2d42011-09-25 08:25:12 +00003838 break;
3839 }
anthonyebb73a22012-03-22 14:25:52 +00003840 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003841 }
3842 case 'f':
3843 {
anthonyafa3dfc2012-03-03 11:31:30 +00003844 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003845 {
anthonya322a832013-04-27 06:28:03 +00003846 new_images=ForwardFourierTransformImage(_images,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003847 break;
3848 }
anthonyafa3dfc2012-03-03 11:31:30 +00003849 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003850 {
anthony319dac62012-03-06 04:12:44 +00003851 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003852 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003853 break;
3854 }
anthonyafa3dfc2012-03-03 11:31:30 +00003855 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003856 {
anthony92c93bd2012-03-19 14:02:47 +00003857 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003858 break;
3859 }
anthonyebb73a22012-03-22 14:25:52 +00003860 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003861 }
3862 case 'h':
3863 {
anthonyafa3dfc2012-03-03 11:31:30 +00003864 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003865 {
anthony31f1bf72012-01-30 12:37:22 +00003866 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003867 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003868 */
anthony805a2d42011-09-25 08:25:12 +00003869 Image
anthony31f1bf72012-01-30 12:37:22 +00003870 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003871
anthony92c93bd2012-03-19 14:02:47 +00003872 new_images=RemoveFirstImageFromList(&_images);
3873 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003874 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003875 break;
anthony92c93bd2012-03-19 14:02:47 +00003876 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003877 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003878 break;
3879 }
anthonyebb73a22012-03-22 14:25:52 +00003880 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003881 }
3882 case 'i':
3883 {
anthonyafa3dfc2012-03-03 11:31:30 +00003884 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003885 {
3886 Image
anthony805a2d42011-09-25 08:25:12 +00003887 *magnitude_image,
3888 *phase_image;
3889
anthony92c93bd2012-03-19 14:02:47 +00003890 magnitude_image=RemoveFirstImageFromList(&_images);
3891 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003892 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003893 if (phase_image == (Image *) NULL)
3894 break;
3895 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthonya322a832013-04-27 06:28:03 +00003896 IsNormalOp,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003897 magnitude_image=DestroyImage(magnitude_image);
3898 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003899 break;
3900 }
anthonyafa3dfc2012-03-03 11:31:30 +00003901 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003902 {
3903 Image
anthony31f1bf72012-01-30 12:37:22 +00003904 *insert_image,
3905 *index_image;
3906
3907 ssize_t
3908 index;
anthony805a2d42011-09-25 08:25:12 +00003909
anthony7bcfe7f2012-03-30 14:01:22 +00003910 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00003911 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003912 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003913 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003914 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003915 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003916 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003917 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003918 PrependImageToList(&_images,insert_image);
3919 else if (index == (ssize_t) GetImageListLength(_images))
3920 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003921 else
anthony43f425d2012-02-26 12:58:58 +00003922 {
anthony92c93bd2012-03-19 14:02:47 +00003923 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003924 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003925 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003926 InsertImageInList(&index_image,insert_image);
3927 }
anthony92c93bd2012-03-19 14:02:47 +00003928 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003929 break;
3930 }
anthonyebb73a22012-03-22 14:25:52 +00003931 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003932 }
3933 case 'l':
3934 {
anthonyafa3dfc2012-03-03 11:31:30 +00003935 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003936 {
anthonyfe1aa782012-03-24 13:43:04 +00003937 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3938 if ( parse < 0 )
3939 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3940 option,arg1);
cristya0417062012-09-02 23:34:56 +00003941 switch ((LayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003942 {
3943 case CoalesceLayer:
3944 {
anthony92c93bd2012-03-19 14:02:47 +00003945 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003946 break;
3947 }
3948 case CompareAnyLayer:
3949 case CompareClearLayer:
3950 case CompareOverlayLayer:
3951 default:
3952 {
cristya0417062012-09-02 23:34:56 +00003953 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00003954 _exception);
anthony805a2d42011-09-25 08:25:12 +00003955 break;
3956 }
3957 case MergeLayer:
3958 case FlattenLayer:
3959 case MosaicLayer:
3960 case TrimBoundsLayer:
3961 {
cristya0417062012-09-02 23:34:56 +00003962 new_images=MergeImageLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00003963 _exception);
anthony805a2d42011-09-25 08:25:12 +00003964 break;
3965 }
3966 case DisposeLayer:
3967 {
anthony92c93bd2012-03-19 14:02:47 +00003968 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003969 break;
3970 }
3971 case OptimizeImageLayer:
3972 {
anthony92c93bd2012-03-19 14:02:47 +00003973 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003974 break;
3975 }
3976 case OptimizePlusLayer:
3977 {
anthony92c93bd2012-03-19 14:02:47 +00003978 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003979 break;
3980 }
3981 case OptimizeTransLayer:
3982 {
anthony92c93bd2012-03-19 14:02:47 +00003983 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003984 break;
3985 }
3986 case RemoveDupsLayer:
3987 {
anthony92c93bd2012-03-19 14:02:47 +00003988 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003989 break;
3990 }
3991 case RemoveZeroLayer:
3992 {
anthony92c93bd2012-03-19 14:02:47 +00003993 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003994 break;
3995 }
3996 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003997 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003998 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003999 if (new_images == (Image *) NULL)
4000 break;
anthony92c93bd2012-03-19 14:02:47 +00004001 _images=DestroyImageList(_images);
4002 _images=OptimizeImageLayers(new_images,_exception);
4003 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004004 break;
4005 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004006 OptimizeImageTransparency(_images,_exception);
4007 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4008 _exception);
anthony805a2d42011-09-25 08:25:12 +00004009 break;
4010 }
4011 case CompositeLayer:
4012 {
anthony805a2d42011-09-25 08:25:12 +00004013 Image
4014 *source;
4015
4016 RectangleInfo
4017 geometry;
4018
anthony31f1bf72012-01-30 12:37:22 +00004019 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004020 compose;
4021
4022 const char*
4023 value;
4024
anthony92c93bd2012-03-19 14:02:47 +00004025 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004026 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004027 if (value != (const char *) NULL)
4028 compose=(CompositeOperator) ParseCommandOption(
4029 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004030
anthony31f1bf72012-01-30 12:37:22 +00004031 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004032 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004033 while (source != (Image *) NULL)
4034 {
4035 source=GetNextImageInList(source);
4036 if ((source != (Image *) NULL) &&
4037 (LocaleCompare(source->magick,"NULL") == 0))
4038 break;
4039 }
4040 if (source != (Image *) NULL)
4041 {
4042 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4043 (GetNextImageInList(source) == (Image *) NULL))
4044 source=(Image *) NULL;
4045 else
anthony31f1bf72012-01-30 12:37:22 +00004046 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004047 source=SplitImageList(source->previous);
4048 DeleteImageFromList(&source);
4049 }
4050 }
4051 if (source == (Image *) NULL)
4052 {
anthony92c93bd2012-03-19 14:02:47 +00004053 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004054 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004055 break;
4056 }
anthony31f1bf72012-01-30 12:37:22 +00004057 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004058 SetGeometry(_images,&geometry);
4059 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004060 geometry.width=source->page.width != 0 ?
4061 source->page.width : source->columns;
4062 geometry.height=source->page.height != 0 ?
4063 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004064 GravityAdjustGeometry(_images->page.width != 0 ?
4065 _images->page.width : _images->columns,
4066 _images->page.height != 0 ? _images->page.height :
4067 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004068
anthony31f1bf72012-01-30 12:37:22 +00004069 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004070 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4071 _exception);
anthony805a2d42011-09-25 08:25:12 +00004072 source=DestroyImageList(source);
4073 break;
4074 }
4075 }
anthony805a2d42011-09-25 08:25:12 +00004076 break;
4077 }
anthonyebb73a22012-03-22 14:25:52 +00004078 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004079 }
4080 case 'm':
4081 {
anthonyafa3dfc2012-03-03 11:31:30 +00004082 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004083 {
anthony464f1c42012-04-22 08:51:01 +00004084 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004085 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004086 break;
4087 }
cristye863c052013-09-04 11:31:30 +00004088 if (LocaleCompare("metric",option+1) == 0)
4089 break;
anthonyafa3dfc2012-03-03 11:31:30 +00004090 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004091 {
4092 Image
4093 *morph_image;
4094
anthony7bcfe7f2012-03-30 14:01:22 +00004095 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004096 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004097 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4098 _exception);
anthony805a2d42011-09-25 08:25:12 +00004099 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004100 break;
anthony92c93bd2012-03-19 14:02:47 +00004101 _images=DestroyImageList(_images);
4102 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004103 break;
4104 }
anthonyafa3dfc2012-03-03 11:31:30 +00004105 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004106 {
anthony319dac62012-03-06 04:12:44 +00004107 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004108 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004109 break;
4110 }
anthonyebb73a22012-03-22 14:25:52 +00004111 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004112 }
4113 case 'p':
4114 {
cristy02016cf2012-11-13 01:14:41 +00004115 if (LocaleCompare("poly",option+1) == 0)
4116 {
4117 double
4118 *args;
4119
4120 ssize_t
4121 count;
4122
4123 /* convert argument string into an array of doubles */
4124 args = StringToArrayOfDoubles(arg2,&count,_exception);
4125 if (args == (double *)NULL )
4126 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
4127 new_images=PolynomialImage(_images,count >> 1,args,_exception);
4128 args=(double *) RelinquishMagickMemory(args);
4129 break;
4130 }
anthonyafa3dfc2012-03-03 11:31:30 +00004131 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004132 {
anthonyb1d483a2012-04-14 12:53:56 +00004133 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004134 char
4135 **arguments;
4136
4137 int
4138 j,
4139 number_arguments;
4140
anthony31f1bf72012-01-30 12:37:22 +00004141 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004142 if (arguments == (char **) NULL)
4143 break;
anthony31f1bf72012-01-30 12:37:22 +00004144 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004145 {
4146 char
4147 breaker,
4148 quote,
4149 *token;
4150
4151 const char
4152 *arguments;
4153
4154 int
4155 next,
4156 status;
4157
4158 size_t
4159 length;
4160
4161 TokenInfo
4162 *token_info;
4163
4164 /*
anthony24aa8822012-03-11 00:56:06 +00004165 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004166 */
cristy4bc3dac2014-01-18 15:17:26 +00004167 assert(arg1 != (const char *) NULL);
anthony31f1bf72012-01-30 12:37:22 +00004168 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004169 token=(char *) NULL;
4170 if (~length >= (MaxTextExtent-1))
4171 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4172 sizeof(*token));
4173 if (token == (char *) NULL)
4174 break;
4175 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004176 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004177 token_info=AcquireTokenInfo();
4178 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4179 "\"",'\0',&breaker,&next,&quote);
4180 token_info=DestroyTokenInfo(token_info);
4181 if (status == 0)
4182 {
4183 const char
4184 *argv;
4185
4186 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004187 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4188 _exception);
anthony805a2d42011-09-25 08:25:12 +00004189 }
4190 token=DestroyString(token);
4191 break;
4192 }
4193 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004194 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4195 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004196 for (j=0; j < number_arguments; j++)
4197 arguments[j]=DestroyString(arguments[j]);
4198 arguments=(char **) RelinquishMagickMemory(arguments);
4199 break;
4200 }
anthonyebb73a22012-03-22 14:25:52 +00004201 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004202 }
4203 case 'r':
4204 {
anthonyafa3dfc2012-03-03 11:31:30 +00004205 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004206 {
anthony92c93bd2012-03-19 14:02:47 +00004207 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004208 break;
4209 }
anthonyafa3dfc2012-03-03 11:31:30 +00004210 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004211 {
anthony92c93bd2012-03-19 14:02:47 +00004212 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004213 break;
4214 }
anthonyebb73a22012-03-22 14:25:52 +00004215 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004216 }
4217 case 's':
4218 {
anthonyafa3dfc2012-03-03 11:31:30 +00004219 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004220 {
anthonycd358fc2012-04-16 13:59:03 +00004221 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004222 ssize_t
4223 offset;
4224
anthony7bcfe7f2012-03-30 14:01:22 +00004225 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004226 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004227 offset=(ssize_t) StringToLong(arg1);
anthonya322a832013-04-27 06:28:03 +00004228 new_images=SmushImages(_images,IsNormalOp,offset,_exception);
anthonycd358fc2012-04-16 13:59:03 +00004229 break;
4230 }
4231 if (LocaleCompare("subimage",option+1) == 0)
4232 {
4233 Image
4234 *base_image,
4235 *compare_image;
4236
4237 const char *
4238 value;
4239
4240 MetricType
4241 metric;
4242
4243 double
4244 similarity;
4245
4246 RectangleInfo
4247 offset;
4248
4249 base_image=GetImageFromList(_images,0);
4250 compare_image=GetImageFromList(_images,1);
4251
4252 /* Comparision Metric */
cristy08163292013-07-11 00:00:37 +00004253 metric=UndefinedErrorMetric;
anthonycd358fc2012-04-16 13:59:03 +00004254 value=GetImageOption(_image_info,"metric");
4255 if (value != (const char *) NULL)
4256 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4257 MagickFalse,value);
4258
cristy99fcec42013-03-15 21:37:59 +00004259 new_images=SimilarityImage(base_image,compare_image,metric,0.0,
anthonycd358fc2012-04-16 13:59:03 +00004260 &offset,&similarity,_exception);
4261
4262 if ( new_images != (Image *)NULL ) {
4263 char
4264 result[MaxTextExtent];
4265
4266 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4267 (void) SetImageProperty(new_images,"subimage:similarity",result,
4268 _exception);
4269 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4270 (long) offset.x);
4271 (void) SetImageProperty(new_images,"subimage:x",result,
4272 _exception);
4273 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4274 (long) offset.y);
4275 (void) SetImageProperty(new_images,"subimage:y",result,
4276 _exception);
4277 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4278 (unsigned long) offset.width,(unsigned long) offset.height,
4279 (long) offset.x,(long) offset.y);
4280 (void) SetImageProperty(new_images,"subimage:offset",result,
4281 _exception);
4282 }
anthony805a2d42011-09-25 08:25:12 +00004283 break;
4284 }
anthony0ea037a2012-04-03 12:14:39 +00004285 if (LocaleCompare("swap",option+1) == 0) {
4286 Image
4287 *p,
4288 *q,
4289 *swap;
anthony805a2d42011-09-25 08:25:12 +00004290
anthony0ea037a2012-04-03 12:14:39 +00004291 ssize_t
4292 index,
4293 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004294
cristy6b36c942013-02-17 00:36:24 +00004295 index=(-1);
4296 swap_index=(-2);
anthony0ea037a2012-04-03 12:14:39 +00004297 if (IfNormalOp) {
4298 GeometryInfo
4299 geometry_info;
4300
4301 MagickStatusType
4302 flags;
4303
4304 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004305 flags=ParseGeometry(arg1,&geometry_info);
cristy90fbd1c2013-02-17 00:35:35 +00004306 if ((flags & RhoValue) == 0)
anthonyb1e21ed2012-04-20 12:43:12 +00004307 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004308 index=(ssize_t) geometry_info.rho;
4309 if ((flags & SigmaValue) != 0)
4310 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004311 }
anthony0ea037a2012-04-03 12:14:39 +00004312 p=GetImageFromList(_images,index);
4313 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004314 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4315 if (IfNormalOp)
4316 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4317 else
4318 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4319 }
anthony0ea037a2012-04-03 12:14:39 +00004320 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004321 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004322 swap=CloneImage(p,0,0,MagickTrue,_exception);
4323 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4324 ReplaceImageInList(&q,swap);
4325 _images=GetFirstImageInList(q);
4326 break;
4327 }
anthonyebb73a22012-03-22 14:25:52 +00004328 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004329 }
anthony805a2d42011-09-25 08:25:12 +00004330 default:
anthonyebb73a22012-03-22 14:25:52 +00004331 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004332 }
anthony964d28e2012-05-17 23:39:46 +00004333
4334 /* clean up percent escape interpreted strings */
4335 if (arg1 != arg1n )
4336 arg1=DestroyString((char *)arg1);
4337 if (arg2 != arg2n )
4338 arg2=DestroyString((char *)arg2);
4339
4340 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004341 if (new_images == (Image *) NULL)
cristy6398ec72013-11-28 02:00:27 +00004342 return(status == 0 ? MagickFalse : MagickTrue);
anthony964d28e2012-05-17 23:39:46 +00004343 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004344 _images=GetFirstImageInList(new_images);
cristy6398ec72013-11-28 02:00:27 +00004345 return(status == 0 ? MagickFalse : MagickTrue);
anthony31f1bf72012-01-30 12:37:22 +00004346
anthony92c93bd2012-03-19 14:02:47 +00004347#undef _image_info
4348#undef _images
4349#undef _exception
4350#undef _draw_info
4351#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004352#undef IfNormalOp
4353#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00004354#undef IsNormalOp
anthony805a2d42011-09-25 08:25:12 +00004355}
anthony43f425d2012-02-26 12:58:58 +00004356
4357/*
4358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4359% %
4360% %
4361% %
anthony964d28e2012-05-17 23:39:46 +00004362+ C L I N o I m a g e O p e r a t i o n s %
anthony43f425d2012-02-26 12:58:58 +00004363% %
4364% %
4365% %
4366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4367%
anthony464f1c42012-04-22 08:51:01 +00004368% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004369% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004370%
anthony4837ac22012-05-18 23:39:48 +00004371% The classic operators of this type is "-read", which actually creates
4372% images even when no images are present. Or image stack operators, which
4373% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004374%
anthony4837ac22012-05-18 23:39:48 +00004375% Note that these operators may involve other special 'option' prefix
4376% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004377%
anthony464f1c42012-04-22 08:51:01 +00004378% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004379%
anthony464f1c42012-04-22 08:51:01 +00004380% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4381% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004382%
4383% A description of each parameter follows:
4384%
anthonyc7994672012-11-17 05:33:27 +00004385% o cli_wand: the main CLI Wand to use. (sometimes not required)
anthony43f425d2012-02-26 12:58:58 +00004386%
4387% o option: The special option (with any switch char) to process
4388%
anthony464f1c42012-04-22 08:51:01 +00004389% o arg1 & arg2: Argument for option, if required
4390% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004391%
4392*/
cristyfe831852013-02-12 14:56:07 +00004393WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
anthonya322a832013-04-27 06:28:03 +00004394 const char *option,const char *arg1n,const char *arg2n)
anthony43f425d2012-02-26 12:58:58 +00004395{
anthonya322a832013-04-27 06:28:03 +00004396 const char /* percent escaped versions of the args */
anthony4837ac22012-05-18 23:39:48 +00004397 *arg1,
4398 *arg2;
anthony4837ac22012-05-18 23:39:48 +00004399
anthony8226e722012-04-05 14:25:46 +00004400#define _image_info (cli_wand->wand.image_info)
4401#define _images (cli_wand->wand.images)
4402#define _exception (cli_wand->wand.exception)
anthonya322a832013-04-27 06:28:03 +00004403#define _process_flags (cli_wand->process_flags)
4404#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthony8226e722012-04-05 14:25:46 +00004405#define IfNormalOp (*option=='-')
4406#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004407
4408 assert(cli_wand != (MagickCLI *) NULL);
4409 assert(cli_wand->signature == WandSignature);
4410 assert(cli_wand->wand.signature == WandSignature);
anthonya322a832013-04-27 06:28:03 +00004411
anthony7bcfe7f2012-03-30 14:01:22 +00004412 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00004413 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
4414 "- NoImage Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
anthony43f425d2012-02-26 12:58:58 +00004415
anthony4837ac22012-05-18 23:39:48 +00004416 arg1 = arg1n;
4417 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00004418
4419 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +00004420 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4421 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4422 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4423 /* Interpret Percent escapes in argument 1 */
4424 if (arg1n != (char *) NULL) {
4425 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4426 if (arg1 == (char *) NULL) {
4427 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4428 arg1=arg1n; /* use the given argument as is */
4429 }
4430 }
4431 if (arg2n != (char *) NULL) {
4432 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4433 if (arg2 == (char *) NULL) {
4434 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4435 arg2=arg2n; /* use the given argument as is */
4436 }
4437 }
4438 }
4439#undef _process_flags
4440#undef _option_type
anthony4837ac22012-05-18 23:39:48 +00004441
4442 do { /* break to exit code */
4443 /*
4444 No-op options (ignore these)
4445 */
anthonyc7994672012-11-17 05:33:27 +00004446 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
anthony4837ac22012-05-18 23:39:48 +00004447 break;
4448 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4449 break;
anthonyc7994672012-11-17 05:33:27 +00004450 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4451 break;
4452 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
anthony4837ac22012-05-18 23:39:48 +00004453 break;
4454 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4455 break;
4456 /*
4457 Image Reading
4458 */
4459 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4460 ( LocaleCompare("--",option) == 0 ) ) {
4461 /* Do Glob filename Expansion for 'arg1' then read all images.
4462 *
4463 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4464 * (but attaching to the filenames in the generated argument list) any
4465 * [...] read modifiers that may be present.
4466 *
4467 * For example: It will expand '*.gif[20x20]' into a list such as
4468 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4469 *
4470 * NOTE: In IMv6 this was done globally across all images. This
4471 * meant you could include IM options in '@filename' lists, but you
4472 * could not include comments. Doing it only for image read makes
4473 * it far more secure.
4474 *
4475 * Note: arguments do not have percent escapes expanded for security
4476 * reasons.
4477 */
4478 int argc;
4479 char **argv;
4480 ssize_t i;
4481
4482 argc = 1;
4483 argv = (char **) &arg1;
4484
4485 /* Expand 'glob' expressions in the given filename.
4486 Expansion handles any 'coder:' prefix, or read modifiers attached
4487 to the filename, including them in the resulting expanded list.
4488 */
4489 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4490 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4491 option,GetExceptionMessage(errno));
4492
4493 /* loop over expanded filename list, and read then all in */
4494 for (i=0; i<argc; i++) {
4495 Image *
4496 new_images;
4497 if (IfMagickTrue(_image_info->ping))
4498 new_images=PingImages(_image_info,argv[i],_exception);
4499 else
4500 new_images=ReadImages(_image_info,argv[i],_exception);
4501 AppendImageToList(&_images, new_images);
4502 }
4503 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4504 break;
4505 }
4506 /*
4507 Image Writing
4508 Note: Writing a empty image list is valid in specific cases
4509 */
4510 if (LocaleCompare("write",option+1) == 0) {
4511 /* Note: arguments do not have percent escapes expanded */
4512 char
4513 key[MaxTextExtent];
4514
4515 Image
4516 *write_images;
4517
4518 ImageInfo
4519 *write_info;
4520
4521 /* Need images, unless a "null:" output coder is used */
anthonya322a832013-04-27 06:28:03 +00004522 if ( _images == (Image *) NULL ) {
anthony4837ac22012-05-18 23:39:48 +00004523 if ( LocaleCompare(arg1,"null:") == 0 )
4524 break;
4525 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4526 }
4527
4528 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4529 (void) DeleteImageRegistry(key);
4530 write_images=_images;
4531 if (IfPlusOp)
4532 write_images=CloneImageList(_images,_exception);
4533 write_info=CloneImageInfo(_image_info);
4534 (void) WriteImages(write_info,write_images,arg1,_exception);
4535 write_info=DestroyImageInfo(write_info);
4536 if (IfPlusOp)
4537 write_images=DestroyImageList(write_images);
4538 break;
4539 }
4540 /*
4541 Parenthesis and Brace operations
4542 */
4543 if (LocaleCompare("(",option) == 0) {
4544 /* stack 'push' images */
4545 Stack
4546 *node;
4547
4548 size_t
4549 size;
4550
4551 size=0;
4552 node=cli_wand->image_list_stack;
4553 for ( ; node != (Stack *)NULL; node=node->next)
4554 size++;
4555 if ( size >= MAX_STACK_DEPTH )
4556 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4557 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4558 if (node == (Stack *) NULL)
4559 CLIWandExceptionBreak(ResourceLimitFatalError,
4560 "MemoryAllocationFailed",option);
4561 node->data = (void *)cli_wand->wand.images;
anthony4837ac22012-05-18 23:39:48 +00004562 node->next = cli_wand->image_list_stack;
4563 cli_wand->image_list_stack = node;
anthonya322a832013-04-27 06:28:03 +00004564 cli_wand->wand.images = NewImageList();
anthony4837ac22012-05-18 23:39:48 +00004565
4566 /* handle respect-parenthesis */
4567 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4568 "respect-parenthesis"))))
4569 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004570 else
anthony4837ac22012-05-18 23:39:48 +00004571 break;
anthonya322a832013-04-27 06:28:03 +00004572 /* fall thru to operation */
anthony52bef752012-03-27 13:54:47 +00004573 }
anthony4837ac22012-05-18 23:39:48 +00004574 if (LocaleCompare("{",option) == 0) {
4575 /* stack 'push' of image_info settings */
4576 Stack
4577 *node;
anthony8226e722012-04-05 14:25:46 +00004578
anthony4837ac22012-05-18 23:39:48 +00004579 size_t
4580 size;
anthony8226e722012-04-05 14:25:46 +00004581
anthony4837ac22012-05-18 23:39:48 +00004582 size=0;
4583 node=cli_wand->image_info_stack;
4584 for ( ; node != (Stack *)NULL; node=node->next)
4585 size++;
4586 if ( size >= MAX_STACK_DEPTH )
4587 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4588 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4589 if (node == (Stack *) NULL)
4590 CLIWandExceptionBreak(ResourceLimitFatalError,
4591 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004592
anthony4837ac22012-05-18 23:39:48 +00004593 node->data = (void *)cli_wand->wand.image_info;
anthonya322a832013-04-27 06:28:03 +00004594 node->next = cli_wand->image_info_stack;
4595
4596 cli_wand->image_info_stack = node;
anthony4837ac22012-05-18 23:39:48 +00004597 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4598 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4599 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4600 option);
4601 cli_wand->wand.image_info = (ImageInfo *)node->data;
4602 node = (Stack *)RelinquishMagickMemory(node);
4603 break;
4604 }
4605
anthony4837ac22012-05-18 23:39:48 +00004606 break;
anthony8226e722012-04-05 14:25:46 +00004607 }
anthony4837ac22012-05-18 23:39:48 +00004608 if (LocaleCompare(")",option) == 0) {
4609 /* pop images from stack */
4610 Stack
4611 *node;
anthony8226e722012-04-05 14:25:46 +00004612
anthony4837ac22012-05-18 23:39:48 +00004613 node = (Stack *)cli_wand->image_list_stack;
4614 if ( node == (Stack *)NULL)
4615 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4616 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004617
anthony4837ac22012-05-18 23:39:48 +00004618 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4619 cli_wand->wand.images= (Image *)node->data;
4620 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004621
anthony4837ac22012-05-18 23:39:48 +00004622 /* handle respect-parenthesis - of the previous 'pushed' settings */
4623 node = cli_wand->image_info_stack;
4624 if ( node != (Stack *)NULL)
4625 {
4626 if (IfMagickTrue(IsStringTrue(GetImageOption(
4627 cli_wand->wand.image_info,"respect-parenthesis"))))
4628 option="}"; /* fall-thru so as to pop image settings too */
4629 else
4630 break;
4631 }
4632 else
4633 break;
4634 /* fall thru to next if */
4635 }
4636 if (LocaleCompare("}",option) == 0) {
4637 /* pop image_info settings from stack */
4638 Stack
4639 *node;
anthony43f425d2012-02-26 12:58:58 +00004640
anthony4837ac22012-05-18 23:39:48 +00004641 node = (Stack *)cli_wand->image_info_stack;
4642 if ( node == (Stack *)NULL)
4643 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4644 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004645
anthony4837ac22012-05-18 23:39:48 +00004646 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004647 cli_wand->wand.image_info = (ImageInfo *)node->data;
4648 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004649
4650 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4651 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4652 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4653
4654 break;
4655 }
anthonya322a832013-04-27 06:28:03 +00004656 if (LocaleCompare("print",option+1) == 0)
4657 {
4658 (void) FormatLocaleFile(stdout,"%s",arg1);
4659 break;
4660 }
anthonyc7994672012-11-17 05:33:27 +00004661 if (LocaleCompare("set",option+1) == 0)
4662 {
anthonya322a832013-04-27 06:28:03 +00004663 /* Settings are applied to each image in memory in turn (if any).
4664 While a option: only need to be applied once globally.
4665
4666 NOTE: rguments have not been automatically percent expaneded
anthonyc7994672012-11-17 05:33:27 +00004667 */
anthonya322a832013-04-27 06:28:03 +00004668
4669 /* escape the 'key' once only, using first image. */
4670 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4671 if (arg1 == (char *) NULL)
4672 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4673 option);
anthonyc7994672012-11-17 05:33:27 +00004674
4675 if (LocaleNCompare(arg1,"registry:",9) == 0)
4676 {
4677 if (IfPlusOp)
4678 {
4679 (void) DeleteImageRegistry(arg1+9);
anthonya322a832013-04-27 06:28:03 +00004680 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004681 break;
4682 }
anthonya322a832013-04-27 06:28:03 +00004683 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4684 if (arg2 == (char *) NULL) {
4685 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004686 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4687 option);
anthonya322a832013-04-27 06:28:03 +00004688 }
4689 (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
4690 arg1=DestroyString((char *)arg1);
4691 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004692 break;
4693 }
4694 if (LocaleNCompare(arg1,"option:",7) == 0)
4695 {
4696 /* delete equivelent artifact from all images (if any) */
anthonya322a832013-04-27 06:28:03 +00004697 if (_images != (Image *)NULL)
4698 {
4699 MagickResetIterator(&cli_wand->wand);
4700 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4701 (void) DeleteImageArtifact(_images,arg1+7);
4702 MagickResetIterator(&cli_wand->wand);
4703 }
anthonyc7994672012-11-17 05:33:27 +00004704 /* now set/delete the global option as needed */
anthonya322a832013-04-27 06:28:03 +00004705 /* FUTURE: make escapes in a global 'option:' delayed */
4706 arg2=(char *)NULL;
4707 if (IfNormalOp)
4708 {
4709 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4710 if (arg2 == (char *) NULL)
4711 CLIWandExceptionBreak(OptionWarning,
4712 "InterpretPropertyFailure",option);
4713 }
4714 (void) SetImageOption(_image_info,arg1+7,arg2);
4715 arg1=DestroyString((char *)arg1);
4716 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004717 break;
4718 }
anthonya322a832013-04-27 06:28:03 +00004719 /* Set Artifacts/Properties/Attributes all images (required) */
4720 if ( _images == (Image *) NULL )
4721 CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
4722
anthonyc7994672012-11-17 05:33:27 +00004723 MagickResetIterator(&cli_wand->wand);
4724 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4725 {
anthonya322a832013-04-27 06:28:03 +00004726 arg2=(char *)NULL;
4727 if (IfNormalOp)
4728 {
4729 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4730 if (arg2 == (char *) NULL)
4731 CLIWandExceptionBreak(OptionWarning,
4732 "InterpretPropertyFailure",option);
4733 }
4734 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4735 (void) SetImageArtifact(_images,arg1+9,arg2);
4736 else if (LocaleNCompare(arg1,"property:",9) == 0)
4737 (void) SetImageProperty(_images,arg1+9,arg2,_exception);
4738 else
4739 (void) SetImageProperty(_images,arg1,arg2,_exception);
4740 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004741 }
4742 MagickResetIterator(&cli_wand->wand);
anthonya322a832013-04-27 06:28:03 +00004743 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004744 break;
4745 }
anthony4837ac22012-05-18 23:39:48 +00004746 if (LocaleCompare("clone",option+1) == 0) {
4747 Image
4748 *new_images;
4749
4750 if (*option == '+')
4751 arg1="-1";
4752 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4753 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
4754 if ( cli_wand->image_list_stack == (Stack *)NULL)
4755 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4756 new_images = (Image *)cli_wand->image_list_stack->data;
4757 if (new_images == (Image *) NULL)
4758 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4759 new_images=CloneImages(new_images,arg1,_exception);
4760 if (new_images == (Image *) NULL)
4761 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4762 AppendImageToList(&_images,new_images);
4763 break;
4764 }
4765 /*
cristy422d5502012-12-22 22:20:57 +00004766 Informational Operations.
anthony4837ac22012-05-18 23:39:48 +00004767
anthonyc7994672012-11-17 05:33:27 +00004768 Note that these do not require either a cli-wand or images!
4769 Though currently a cli-wand much be provided regardless.
anthony4837ac22012-05-18 23:39:48 +00004770 */
cristy422d5502012-12-22 22:20:57 +00004771 if (LocaleCompare("version",option+1) == 0)
4772 {
cristy4f7a6132012-12-23 00:35:19 +00004773 ListMagickVersion(stdout);
cristy422d5502012-12-22 22:20:57 +00004774 break;
4775 }
anthony4837ac22012-05-18 23:39:48 +00004776 if (LocaleCompare("list",option+1) == 0) {
4777 /*
anthonyc7994672012-11-17 05:33:27 +00004778 FUTURE: This 'switch' should really be part of MagickCore
anthony4837ac22012-05-18 23:39:48 +00004779 */
4780 ssize_t
4781 list;
4782
4783 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4784 if ( list < 0 ) {
4785 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4786 break;
4787 }
4788 switch (list)
4789 {
4790 case MagickCoderOptions:
4791 {
4792 (void) ListCoderInfo((FILE *) NULL,_exception);
4793 break;
4794 }
4795 case MagickColorOptions:
4796 {
4797 (void) ListColorInfo((FILE *) NULL,_exception);
4798 break;
4799 }
4800 case MagickConfigureOptions:
4801 {
4802 (void) ListConfigureInfo((FILE *) NULL,_exception);
4803 break;
4804 }
4805 case MagickDelegateOptions:
4806 {
4807 (void) ListDelegateInfo((FILE *) NULL,_exception);
4808 break;
4809 }
4810 case MagickFontOptions:
4811 {
4812 (void) ListTypeInfo((FILE *) NULL,_exception);
4813 break;
4814 }
4815 case MagickFormatOptions:
4816 (void) ListMagickInfo((FILE *) NULL,_exception);
4817 break;
4818 case MagickLocaleOptions:
4819 (void) ListLocaleInfo((FILE *) NULL,_exception);
4820 break;
4821 case MagickLogOptions:
4822 (void) ListLogInfo((FILE *) NULL,_exception);
4823 break;
4824 case MagickMagicOptions:
4825 (void) ListMagicInfo((FILE *) NULL,_exception);
4826 break;
4827 case MagickMimeOptions:
4828 (void) ListMimeInfo((FILE *) NULL,_exception);
4829 break;
4830 case MagickModuleOptions:
4831 (void) ListModuleInfo((FILE *) NULL,_exception);
4832 break;
4833 case MagickPolicyOptions:
4834 (void) ListPolicyInfo((FILE *) NULL,_exception);
4835 break;
4836 case MagickResourceOptions:
4837 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4838 break;
4839 case MagickThresholdOptions:
4840 (void) ListThresholdMaps((FILE *) NULL,_exception);
4841 break;
4842 default:
4843 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4844 _exception);
4845 break;
4846 }
4847 break;
anthony43f425d2012-02-26 12:58:58 +00004848 }
anthony8226e722012-04-05 14:25:46 +00004849
anthony4837ac22012-05-18 23:39:48 +00004850 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony8226e722012-04-05 14:25:46 +00004851
dirk93b02b72013-11-16 16:03:36 +00004852DisableMSCWarning(4127)
anthony4837ac22012-05-18 23:39:48 +00004853 } while (0); /* break to exit code. */
dirk93b02b72013-11-16 16:03:36 +00004854RestoreMSCWarning
anthony43f425d2012-02-26 12:58:58 +00004855
anthony4837ac22012-05-18 23:39:48 +00004856 /* clean up percent escape interpreted strings */
4857 if (arg1 != arg1n )
4858 arg1=DestroyString((char *)arg1);
4859 if (arg2 != arg2n )
4860 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00004861
anthony8226e722012-04-05 14:25:46 +00004862#undef _image_info
4863#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004864#undef _exception
anthony8226e722012-04-05 14:25:46 +00004865#undef IfNormalOp
4866#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004867}
anthony464f1c42012-04-22 08:51:01 +00004868
4869/*
4870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4871% %
4872% %
4873% %
anthony964d28e2012-05-17 23:39:46 +00004874+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00004875% %
4876% %
4877% %
4878%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4879%
4880% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00004881% The option arguments can be variable in number, though at this time no more
4882% that two is actually used by any option (this may change). Excess options
4883% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00004884%
4885% If the cli_wand->command pointer is non-null, then it is assumed that the
4886% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00004887% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
4888% routine will do the lookup instead. The pointer is reset afterward.
4889%
4890% This action allows the caller to lookup and pre-handle any 'special'
4891% options, (such as implicit reads) before calling this general option
4892% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00004893%
4894% The format of the CLIOption method is:
4895%
4896% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4897%
4898% A description of each parameter follows:
4899%
4900% o cli_wand: the main CLI Wand to use.
4901%
4902% o option: The special option (with any switch char) to process
4903%
anthony964d28e2012-05-17 23:39:46 +00004904% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00004905%
4906% Example Usage...
4907%
4908% CLIoption(cli_wand,"-read","rose:");
4909% CLIoption(cli_wand,"-virtual-pixel","transparent");
4910% CLIoption(cli_wand,"-distort","SRT:","30");
4911% CLIoption(cli_wand,"-write","rotated_rose.png");
4912%
4913*/
4914WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4915{
anthonya322a832013-04-27 06:28:03 +00004916 const char /* extracted option args from args */
anthony464f1c42012-04-22 08:51:01 +00004917 *arg1,
4918 *arg2;
4919
4920 CommandOptionFlags
4921 option_type;
4922
4923 assert(cli_wand != (MagickCLI *) NULL);
4924 assert(cli_wand->signature == WandSignature);
4925 assert(cli_wand->wand.signature == WandSignature);
anthony464f1c42012-04-22 08:51:01 +00004926
anthony964d28e2012-05-17 23:39:46 +00004927 do { /* Break Code Block for error handling */
4928
4929 /* get information about option */
4930 if ( cli_wand->command == (const OptionInfo *) NULL )
4931 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00004932#if 0
anthony964d28e2012-05-17 23:39:46 +00004933 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4934 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00004935#endif
anthony964d28e2012-05-17 23:39:46 +00004936 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00004937
anthony964d28e2012-05-17 23:39:46 +00004938 if ( option_type == UndefinedOptionFlag )
4939 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00004940
anthony964d28e2012-05-17 23:39:46 +00004941 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00004942
anthony964d28e2012-05-17 23:39:46 +00004943 /* depreciated options */
4944 if ( (option_type & DeprecateOptionFlag) != 0 )
4945 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00004946
anthony964d28e2012-05-17 23:39:46 +00004947 /* options that this module does not handle */
4948 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4949 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00004950
anthony964d28e2012-05-17 23:39:46 +00004951 /* Get argument strings from VarArgs
anthonya322a832013-04-27 06:28:03 +00004952 How can you determine if enough arguments was supplied?
4953 What happens if not enough arguments were supplied?
4954 */
anthony964d28e2012-05-17 23:39:46 +00004955 { size_t
4956 count = cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00004957
anthony964d28e2012-05-17 23:39:46 +00004958 va_list
4959 operands;
anthony464f1c42012-04-22 08:51:01 +00004960
anthony964d28e2012-05-17 23:39:46 +00004961 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00004962
anthony964d28e2012-05-17 23:39:46 +00004963 arg1=arg2=NULL;
4964 if ( count >= 1 )
4965 arg1=(const char *) va_arg(operands, const char *);
4966 if ( count >= 2 )
4967 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00004968
anthony964d28e2012-05-17 23:39:46 +00004969 va_end(operands);
anthony52cb3df2012-04-24 03:29:32 +00004970#if 0
anthony964d28e2012-05-17 23:39:46 +00004971 (void) FormatLocaleFile(stderr,
4972 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4973 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00004974#endif
anthony964d28e2012-05-17 23:39:46 +00004975 }
4976
4977 /*
4978 Call the appropriate option handler
4979 */
4980
4981 /* FUTURE: this is temporary - get 'settings' to handle distribution of
4982 settings to images attributes,proprieties,artifacts */
4983 if ( cli_wand->wand.images != (Image *)NULL )
4984 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4985 cli_wand->wand.exception);
4986
4987 if ( (option_type & SettingOptionFlags) != 0 ) {
4988 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4989 // FUTURE: Sync Specific Settings into Image Properities (not global)
4990 }
4991
4992 /* Operators that do not need images - read, write, stack, clone */
4993 if ( (option_type & NoImageOperatorFlag) != 0)
4994 CLINoImageOperator(cli_wand, option, arg1, arg2);
4995
4996 /* FUTURE: The not a setting part below is a temporary hack due to
4997 * some options being both a Setting and a Simple operator.
4998 * Specifically -monitor, -depth, and -colorspace */
4999 if ( cli_wand->wand.images == (Image *)NULL )
5000 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
5001 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
5002 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
5003
anthonya322a832013-04-27 06:28:03 +00005004 /* Operators which loop of individual images, simply */
5005 if ( (option_type & SimpleOperatorFlag) != 0 &&
5006 cli_wand->wand.images != (Image *)NULL) /* temp hack */
anthony964d28e2012-05-17 23:39:46 +00005007 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
5008
5009 /* Operators that work on the image list as a whole */
5010 if ( (option_type & ListOperatorFlag) != 0 )
5011 CLIListOperatorImages(cli_wand, option, arg1, arg2);
5012
dirk93b02b72013-11-16 16:03:36 +00005013DisableMSCWarning(4127)
anthony964d28e2012-05-17 23:39:46 +00005014 } while (0); /* end Break code block */
dirk93b02b72013-11-16 16:03:36 +00005015RestoreMSCWarning
anthony464f1c42012-04-22 08:51:01 +00005016
5017 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00005018}