blob: 44b4c4477943cffb3a8a7f8fea2bb50adc84c568 [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% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 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
cristy151b66d2015-04-15 10:50:31 +000095 message[MagickPathExtent],
96 tag[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +000097
98 const char
99 *locale_message;
100
101 register char
102 *p;
103
104 if (extent < 2)
105 return(MagickTrue);
cristy151b66d2015-04-15 10:50:31 +0000106 (void) CopyMagickMemory(tag,text,MagickPathExtent);
anthony805a2d42011-09-25 08:25:12 +0000107 p=strrchr(tag,'/');
108 if (p != (char *) NULL)
109 *p='\0';
cristy151b66d2015-04-15 10:50:31 +0000110 (void) FormatLocaleString(message,MagickPathExtent,"Monitor/%s",tag);
anthony805a2d42011-09-25 08:25:12 +0000111 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
cristy151b66d2015-04-15 10:50:31 +0000136 key[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +0000137
138 ExceptionInfo
139 *sans_exception;
140
141 Image
142 *image;
143
144 ImageInfo
145 *read_info;
146
cristy151b66d2015-04-15 10:50:31 +0000147 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",path);
anthony805a2d42011-09-25 08:25:12 +0000148 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)
cristy151b66d2015-04-15 10:50:31 +0000155 (void) CopyMagickString(read_info->filename,path,MagickPathExtent);
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
cristy151b66d2015-04-15 10:50:31 +0000177 token[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +0000178
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);
cristye1c94d92015-06-28 12:16:33 +0000202 assert(image->signature == MagickCoreSignature);
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);
cristye1c94d92015-06-28 12:16:33 +0000206 assert(exception->signature == MagickCoreSignature);
anthony805a2d42011-09-25 08:25:12 +0000207 /*
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) &&
cristy7d6d3d82014-11-09 17:00:16 +0000222 image->alpha_trait != UndefinedPixelTrait)
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");
cristyf432c632014-12-07 15:11:28 +0000246 return( (Image *) NULL);
anthony805a2d42011-09-25 08:25:12 +0000247 }
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");
cristyf432c632014-12-07 15:11:28 +0000255 return( (Image *) NULL);
anthony805a2d42011-09-25 08:25:12 +0000256 }
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) &&
cristy7d6d3d82014-11-09 17:00:16 +0000301 image->alpha_trait != UndefinedPixelTrait)
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) &&
cristy7d6d3d82014-11-09 17:00:16 +0000341 image->alpha_trait != UndefinedPixelTrait)
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);
cristyf432c632014-12-07 15:11:28 +0000355 return( (Image *) NULL);
anthony805a2d42011-09-25 08:25:12 +0000356 }
357 if ( error )
cristyf432c632014-12-07 15:11:28 +0000358 return( (Image *) NULL);
anthony805a2d42011-09-25 08:25:12 +0000359
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);
cristye1c94d92015-06-28 12:16:33 +0000426 assert(cli_wand->signature == MagickWandSignature);
427 assert(cli_wand->wand.signature == MagickWandSignature);
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("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000608 {
anthonyafbaed72011-10-26 12:05:04 +0000609 /* Setting used for new images via AquireImage()
610 But also used as a SimpleImageOperator
611 Undefined colorspace means don't modify images on
612 read or as a operation */
cristy17ada022014-11-07 22:12:23 +0000613 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
614 ArgOption("undefined"));
anthony30b912a2012-03-22 01:20:28 +0000615 if (parse < 0)
cristy17ada022014-11-07 22:12:23 +0000616 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
617 arg1);
anthony30b912a2012-03-22 01:20:28 +0000618 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000619 break;
620 }
anthonyafa3dfc2012-03-03 11:31:30 +0000621 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000622 {
anthony92c93bd2012-03-19 14:02:47 +0000623 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000624 break;
625 }
anthonyafa3dfc2012-03-03 11:31:30 +0000626 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000627 {
anthony92c93bd2012-03-19 14:02:47 +0000628 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000629 SyncImageSettings() used to set per-image attribute. - REMOVE
630
anthonyafbaed72011-10-26 12:05:04 +0000631 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000632 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000633 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000634 */
anthonyebb73a22012-03-22 14:25:52 +0000635 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
636 ArgOption("undefined"));
637 if (parse < 0)
638 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
639 option,arg1);
640 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000641 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000642 break;
643 }
anthonyafa3dfc2012-03-03 11:31:30 +0000644 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000645 {
anthony92c93bd2012-03-19 14:02:47 +0000646 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000647 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000648 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000649
anthony92c93bd2012-03-19 14:02:47 +0000650 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000651 however the image attribute (for save) is set from the
652 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000653
654 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000655 */
anthonyebb73a22012-03-22 14:25:52 +0000656 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
657 ArgOption("undefined"));
658 if (parse < 0)
659 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
660 option,arg1);
661 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000662 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000663 break;
664 }
anthonyebb73a22012-03-22 14:25:52 +0000665 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000666 }
667 case 'd':
668 {
anthonyafa3dfc2012-03-03 11:31:30 +0000669 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000670 {
anthony72feaa62012-01-17 06:46:23 +0000671 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000672 arg1=ArgOption("none");
673 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
674 if (parse < 0)
675 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
676 option,arg1);
677 (void) SetLogEventMask(arg1);
678 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000679 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000680 break;
681 }
anthonyafa3dfc2012-03-03 11:31:30 +0000682 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000683 {
anthony24aa8822012-03-11 00:56:06 +0000684 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000685 {
anthony5f867ae2011-10-09 10:28:34 +0000686 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000687 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000688 else
anthony24aa8822012-03-11 00:56:06 +0000689 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000690 break;
691 }
anthony24aa8822012-03-11 00:56:06 +0000692 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000693 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000694 (void) DefineImageOption(_image_info,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +0000695 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000696 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000697 break;
698 }
anthonyafa3dfc2012-03-03 11:31:30 +0000699 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000700 {
anthonyafbaed72011-10-26 12:05:04 +0000701 /* Only used for new images via AcquireImage()
702 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000703 */
anthonyebb73a22012-03-22 14:25:52 +0000704 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000705 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000706 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
707 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000708 break;
709 }
anthonyafa3dfc2012-03-03 11:31:30 +0000710 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000711 {
anthony92c93bd2012-03-19 14:02:47 +0000712 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000713 Basically as density can be in a XxY form!
714
715 SyncImageSettings() used to set per-image attribute.
716 */
anthony7bcfe7f2012-03-30 14:01:22 +0000717 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000718 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000719 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
720 (void) CloneString(&_image_info->density,ArgOption(NULL));
721 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000722 break;
723 }
anthonyafa3dfc2012-03-03 11:31:30 +0000724 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000725 {
anthony72feaa62012-01-17 06:46:23 +0000726 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
727 SyncImageSettings() used to set per-image attribute.
728 */
anthony7bcfe7f2012-03-30 14:01:22 +0000729 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000730 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000731 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000732 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000733 break;
734 }
anthonyafa3dfc2012-03-03 11:31:30 +0000735 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000736 {
anthony92c93bd2012-03-19 14:02:47 +0000737 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000738 arg1=ArgOption("undefined");
739 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
740 if (parse < 0)
741 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
742 option,arg1);
743 _draw_info->direction=(DirectionType) parse;
744 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000745 break;
746 }
anthonyafa3dfc2012-03-03 11:31:30 +0000747 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000748 {
anthony92c93bd2012-03-19 14:02:47 +0000749 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
750 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000751 break;
752 }
anthonyafa3dfc2012-03-03 11:31:30 +0000753 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000754 {
anthony72feaa62012-01-17 06:46:23 +0000755 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000756 arg1=ArgOption("undefined");
757 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
758 if (parse < 0)
759 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
760 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000761 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000762 break;
763 }
anthonyb1d483a2012-04-14 12:53:56 +0000764 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
765 {
766 /* FUTURE: this is only used by CompareImages() which is used
767 only by the "compare" CLI program at this time. */
768 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
769 if (IfMagickFalse(IsGeometry(arg1)))
770 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
771 (void) SetImageOption(_image_info,option+1,arg1);
772 break;
773 }
anthonyafa3dfc2012-03-03 11:31:30 +0000774 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000775 {
anthony92c93bd2012-03-19 14:02:47 +0000776 /* _image_info attr (on/off), _quantize_info attr (on/off)
777 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000778 FUTURE: merge the duality of the dithering options
779 */
cristycbda6112012-05-27 20:57:16 +0000780 _image_info->dither = ArgBoolean;
anthony92c93bd2012-03-19 14:02:47 +0000781 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
782 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
cristycbda6112012-05-27 20:57:16 +0000783 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000784 if (_quantize_info->dither_method == NoDitherMethod)
cristycbda6112012-05-27 20:57:16 +0000785 _image_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000786 break;
787 }
anthonyebb73a22012-03-22 14:25:52 +0000788 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000789 }
790 case 'e':
791 {
anthonyafa3dfc2012-03-03 11:31:30 +0000792 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000793 {
anthony92c93bd2012-03-19 14:02:47 +0000794 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
795 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000796 break;
797 }
anthonyafa3dfc2012-03-03 11:31:30 +0000798 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000799 {
anthony92c93bd2012-03-19 14:02:47 +0000800 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000801 arg1 = ArgOption("undefined");
802 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
803 if (parse < 0)
804 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
805 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000806 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000807 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000808 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000809 break;
810 }
anthonyafa3dfc2012-03-03 11:31:30 +0000811 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000812 {
anthony92c93bd2012-03-19 14:02:47 +0000813 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000814 break;
815 }
anthonyebb73a22012-03-22 14:25:52 +0000816 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000817 }
818 case 'f':
819 {
anthonyafa3dfc2012-03-03 11:31:30 +0000820 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000821 {
anthony92c93bd2012-03-19 14:02:47 +0000822 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000823 break;
824 }
anthonya322a832013-04-27 06:28:03 +0000825 if (LocaleCompare("features",option+1) == 0)
826 {
827 (void) SetImageOption(_image_info,"identify:features",
cristyf9b9b662013-05-25 12:50:16 +0000828 ArgBooleanString);
anthonya322a832013-04-27 06:28:03 +0000829 if (IfSetOption)
830 (void) SetImageArtifact(_image,"verbose","true");
831 break;
832 }
anthonyafa3dfc2012-03-03 11:31:30 +0000833 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000834 {
anthony92c93bd2012-03-19 14:02:47 +0000835 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000836 The original fill color is preserved if a fill-pattern is given.
837 That way it does not effect other operations that directly using
838 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000839 */
anthony72feaa62012-01-17 06:46:23 +0000840 MagickBooleanType
841 status;
anthony6dc09cd2011-10-12 08:56:49 +0000842
843 ExceptionInfo
844 *sans;
845
anthonyfd706f92012-01-19 04:22:02 +0000846 PixelInfo
847 color;
848
anthony2a0ec8c2012-03-24 04:35:56 +0000849 arg1 = ArgOption("none"); /* +fill turns it off! */
850 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000851 if (_draw_info->fill_pattern != (Image *) NULL)
852 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000853
854 /* is it a color or a image? -- ignore exceptions */
855 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +0000856 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000857 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000858
anthony7bcfe7f2012-03-30 14:01:22 +0000859 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +0000860 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000861 else
anthony92c93bd2012-03-19 14:02:47 +0000862 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000863 break;
864 }
anthonyafa3dfc2012-03-03 11:31:30 +0000865 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000866 {
anthony72feaa62012-01-17 06:46:23 +0000867 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +0000868 arg1 = ArgOption("undefined");
869 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
870 if (parse < 0)
871 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
872 option,arg1);
873 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000874 break;
875 }
anthonyafa3dfc2012-03-03 11:31:30 +0000876 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000877 {
anthony92c93bd2012-03-19 14:02:47 +0000878 (void) CloneString(&_draw_info->font,ArgOption(NULL));
879 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000880 break;
881 }
anthonyafa3dfc2012-03-03 11:31:30 +0000882 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000883 {
anthonydcf510d2011-10-30 13:51:40 +0000884 /* FUTURE: why the ping test, you could set ping after this! */
885 /*
anthony805a2d42011-09-25 08:25:12 +0000886 register const char
887 *q;
888
anthony24aa8822012-03-11 00:56:06 +0000889 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000890 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000891 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000892 */
anthony92c93bd2012-03-19 14:02:47 +0000893 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000894 break;
895 }
anthonyafa3dfc2012-03-03 11:31:30 +0000896 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000897 {
anthony72feaa62012-01-17 06:46:23 +0000898 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000899 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000900 SyncImageSettings() used to set per-image attribute.
901
anthony2a0ec8c2012-03-24 04:35:56 +0000902 FUTURE: Can't find anything else using _image_info->fuzz directly!
anthonya322a832013-04-27 06:28:03 +0000903 convert structure attribute to 'option' string
anthony6613bf32011-10-15 07:24:44 +0000904 */
anthony2a0ec8c2012-03-24 04:35:56 +0000905 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000906 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +0000907 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
908 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +0000909 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +0000910 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000911 break;
912 }
anthonyebb73a22012-03-22 14:25:52 +0000913 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000914 }
915 case 'g':
916 {
anthonyafa3dfc2012-03-03 11:31:30 +0000917 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000918 {
anthony72feaa62012-01-17 06:46:23 +0000919 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000920 arg1 = ArgOption("none");
921 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
922 if (parse < 0)
923 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
924 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +0000925 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +0000926 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000927 break;
928 }
anthonyafa3dfc2012-03-03 11:31:30 +0000929 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000930 {
anthonydcf510d2011-10-30 13:51:40 +0000931 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000932 SyncImageSettings() used to set per-image attribute.
933 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000934 */
anthonyf42014d2012-03-25 09:53:06 +0000935 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000936 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000937 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000938 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000939 break;
940 }
anthonyebb73a22012-03-22 14:25:52 +0000941 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000942 }
anthonyb1d483a2012-04-14 12:53:56 +0000943 case 'h':
944 {
945 if (LocaleCompare("highlight-color",option+1) == 0)
946 {
947 /* FUTURE: this is only used by CompareImages() which is used
948 only by the "compare" CLI program at this time. */
949 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
950 break;
951 }
952 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
953 }
anthony805a2d42011-09-25 08:25:12 +0000954 case 'i':
955 {
cristy70e9f682013-03-12 22:31:22 +0000956 if (LocaleCompare("intensity",option+1) == 0)
957 {
958 arg1 = ArgOption("undefined");
cristy8f84fdd2013-03-28 17:52:55 +0000959 parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
960 arg1);
cristy70e9f682013-03-12 22:31:22 +0000961 if (parse < 0)
cristy8f84fdd2013-03-28 17:52:55 +0000962 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityType",
963 option,arg1);
cristy70e9f682013-03-12 22:31:22 +0000964 (void) SetImageOption(_image_info,option+1,arg1);
965 break;
966 }
anthonyafa3dfc2012-03-03 11:31:30 +0000967 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000968 {
anthony72feaa62012-01-17 06:46:23 +0000969 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000970 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000971 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000972 */
cristy70e9f682013-03-12 22:31:22 +0000973 arg1 = ArgOption("undefined");
anthonyfe1aa782012-03-24 13:43:04 +0000974 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
975 if (parse < 0)
976 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
977 option,arg1);
978 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000979 break;
980 }
anthonyafa3dfc2012-03-03 11:31:30 +0000981 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000982 {
anthony92c93bd2012-03-19 14:02:47 +0000983 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000984 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000985 */
anthonyfe1aa782012-03-24 13:43:04 +0000986 arg1 = ArgOption("undefined");
987 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
988 if (parse < 0)
989 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
990 option,arg1);
991 _image_info->interlace=(InterlaceType) parse;
992 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000993 break;
994 }
anthonyafa3dfc2012-03-03 11:31:30 +0000995 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000996 {
anthony7bcfe7f2012-03-30 14:01:22 +0000997 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000998 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000999 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1000 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001001 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001002 break;
1003 }
anthonyafa3dfc2012-03-03 11:31:30 +00001004 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001005 {
anthonyfd706f92012-01-19 04:22:02 +00001006 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001007 arg1 = ArgOption("undefined");
1008 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1009 if (parse < 0)
1010 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1011 option,arg1);
1012 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001013 break;
1014 }
anthonyafa3dfc2012-03-03 11:31:30 +00001015 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001016 {
anthony7bcfe7f2012-03-30 14:01:22 +00001017 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001018 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001019 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1020 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001021 break;
1022 }
anthonyebb73a22012-03-22 14:25:52 +00001023 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001024 }
1025 case 'k':
1026 {
anthonyafa3dfc2012-03-03 11:31:30 +00001027 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001028 {
anthony7bcfe7f2012-03-30 14:01:22 +00001029 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001030 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001031 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1032 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001033 break;
1034 }
anthonyebb73a22012-03-22 14:25:52 +00001035 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001036 }
1037 case 'l':
1038 {
anthonyafa3dfc2012-03-03 11:31:30 +00001039 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001040 {
anthony72feaa62012-01-17 06:46:23 +00001041 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001042 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001043 break;
1044 }
anthony756cd0d2012-04-08 12:41:44 +00001045 if (LocaleCompare("limit",option+1) == 0)
1046 {
1047 MagickSizeType
1048 limit;
1049
1050 limit=MagickResourceInfinity;
1051 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1052 if ( parse < 0 )
1053 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1054 option,arg1);
1055 if (LocaleCompare("unlimited",arg2) != 0)
1056 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1057 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1058 break;
1059 }
anthonyafa3dfc2012-03-03 11:31:30 +00001060 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001061 {
anthonyfe1aa782012-03-24 13:43:04 +00001062 if (IfSetOption) {
1063 if ((strchr(arg1,'%') == (char *) NULL))
1064 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001065 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001066 }
anthony805a2d42011-09-25 08:25:12 +00001067 break;
1068 }
anthony975a8d72012-04-12 13:54:36 +00001069 if (LocaleCompare("lowlight-color",option+1) == 0)
1070 {
anthonyb1d483a2012-04-14 12:53:56 +00001071 /* FUTURE: this is only used by CompareImages() which is used
1072 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001073 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1074 break;
1075 }
anthonyafa3dfc2012-03-03 11:31:30 +00001076 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001077 {
anthony72feaa62012-01-17 06:46:23 +00001078 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001079 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001080 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001081 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1082 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001083 break;
1084 }
anthonyebb73a22012-03-22 14:25:52 +00001085 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001086 }
1087 case 'm':
1088 {
anthonyafa3dfc2012-03-03 11:31:30 +00001089 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001090 {
anthony72feaa62012-01-17 06:46:23 +00001091 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001092 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
cristyd7df81d2014-01-18 18:42:05 +00001093 (void) QueryColorCompliance(ArgOption(MogrifyMatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001094 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001095 break;
anthonycd358fc2012-04-16 13:59:03 +00001096 }
anthonyb1d483a2012-04-14 12:53:56 +00001097 if (LocaleCompare("metric",option+1) == 0)
1098 {
1099 /* FUTURE: this is only used by CompareImages() which is used
1100 only by the "compare" CLI program at this time. */
1101 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1102 if ( parse < 0 )
1103 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1104 option,arg1);
1105 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001106 break;
anthony805a2d42011-09-25 08:25:12 +00001107 }
cristybd4a3c22014-01-07 15:09:37 +00001108 if (LocaleCompare("moments",option+1) == 0)
1109 {
1110 (void) SetImageOption(_image_info,"identify:moments",
1111 ArgBooleanString);
1112 if (IfSetOption)
1113 (void) SetImageArtifact(_image,"verbose","true");
1114 break;
1115 }
anthonyafa3dfc2012-03-03 11:31:30 +00001116 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001117 {
anthony92c93bd2012-03-19 14:02:47 +00001118 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001119 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001120 break;
1121 }
anthonyafa3dfc2012-03-03 11:31:30 +00001122 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001123 {
anthony24aa8822012-03-11 00:56:06 +00001124 /* Setting (used by some input coders!) -- why?
1125 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001126 */
anthony92c93bd2012-03-19 14:02:47 +00001127 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001128 break;
1129 }
anthonyebb73a22012-03-22 14:25:52 +00001130 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001131 }
1132 case 'o':
1133 {
anthonyafa3dfc2012-03-03 11:31:30 +00001134 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001135 {
anthony72feaa62012-01-17 06:46:23 +00001136 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001137 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001138 FUTURE: make set meta-data operator instead.
1139 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001140 */
anthony7bc87992012-03-25 02:32:51 +00001141 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1142 ArgOption("undefined"));
1143 if (parse < 0)
1144 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1145 option,arg1);
1146 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001147 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001148 break;
1149 }
anthonyebb73a22012-03-22 14:25:52 +00001150 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001151 }
1152 case 'p':
1153 {
anthonyafa3dfc2012-03-03 11:31:30 +00001154 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001155 {
anthony7bc87992012-03-25 02:32:51 +00001156 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001157 SyncImageSettings() used to set per-image attribute. ?????
1158 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001159 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001160 */
anthony805a2d42011-09-25 08:25:12 +00001161 char
1162 *canonical_page,
cristy151b66d2015-04-15 10:50:31 +00001163 page[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00001164
1165 const char
1166 *image_option;
1167
1168 MagickStatusType
1169 flags;
1170
1171 RectangleInfo
1172 geometry;
1173
anthonydcf510d2011-10-30 13:51:40 +00001174 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001175 {
anthony92c93bd2012-03-19 14:02:47 +00001176 (void) DeleteImageOption(_image_info,option+1);
1177 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001178 break;
1179 }
1180 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001181 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001182 if (image_option != (const char *) NULL)
1183 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001184 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001185 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1186 canonical_page=DestroyString(canonical_page);
cristy151b66d2015-04-15 10:50:31 +00001187 (void) FormatLocaleString(page,MagickPathExtent,"%lux%lu",
anthony805a2d42011-09-25 08:25:12 +00001188 (unsigned long) geometry.width,(unsigned long) geometry.height);
1189 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
cristy151b66d2015-04-15 10:50:31 +00001190 (void) FormatLocaleString(page,MagickPathExtent,"%lux%lu%+ld%+ld",
anthony805a2d42011-09-25 08:25:12 +00001191 (unsigned long) geometry.width,(unsigned long) geometry.height,
1192 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001193 (void) SetImageOption(_image_info,option+1,page);
1194 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001195 break;
1196 }
anthonyafa3dfc2012-03-03 11:31:30 +00001197 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001198 {
anthony92c93bd2012-03-19 14:02:47 +00001199 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001200 break;
1201 }
anthonyafa3dfc2012-03-03 11:31:30 +00001202 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001203 {
anthonyf42014d2012-03-25 09:53:06 +00001204 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001205 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001206 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1207 _image_info->pointsize =
1208 _draw_info->pointsize =
1209 StringToDouble(arg1,(char **) NULL);
1210 }
1211 else {
1212 _image_info->pointsize=0.0; /* unset pointsize */
1213 _draw_info->pointsize=12.0;
1214 }
anthony805a2d42011-09-25 08:25:12 +00001215 break;
1216 }
anthonyafa3dfc2012-03-03 11:31:30 +00001217 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001218 {
anthonyf42014d2012-03-25 09:53:06 +00001219 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001220 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001221 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1222 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001223 break;
1224 }
anthonydcf510d2011-10-30 13:51:40 +00001225 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001226 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001227 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001228 {
anthony92c93bd2012-03-19 14:02:47 +00001229 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001230 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001231 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001232 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001233 break;
1234 }
anthonydcf510d2011-10-30 13:51:40 +00001235 */
anthonyebb73a22012-03-22 14:25:52 +00001236 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001237 }
1238 case 'q':
1239 {
anthonyafa3dfc2012-03-03 11:31:30 +00001240 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001241 {
anthony7bcfe7f2012-03-30 14:01:22 +00001242 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001243 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001244 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1245 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001246 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001247 break;
1248 }
anthonyafa3dfc2012-03-03 11:31:30 +00001249 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001250 {
anthony92c93bd2012-03-19 14:02:47 +00001251 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001252 arg1=ArgOption("undefined");
1253 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1254 if (parse < 0)
1255 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1256 option,arg1);
1257 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001258 break;
1259 }
anthonyafa3dfc2012-03-03 11:31:30 +00001260 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001261 {
anthonyf42014d2012-03-25 09:53:06 +00001262 /* FUTURE: if two -quiet is performed you can not do +quiet!
1263 This needs to be checked over thoughly.
1264 */
anthony805a2d42011-09-25 08:25:12 +00001265 static WarningHandler
1266 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001267
anthonyafbaed72011-10-26 12:05:04 +00001268 WarningHandler
1269 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001270
anthonyafbaed72011-10-26 12:05:04 +00001271 if ( tmp != (WarningHandler) NULL)
1272 warning_handler = tmp; /* remember the old handler */
1273 if (!IfSetOption) /* set the old handler */
1274 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001275 break;
1276 }
anthonyebb73a22012-03-22 14:25:52 +00001277 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001278 }
1279 case 'r':
1280 {
anthonyafa3dfc2012-03-03 11:31:30 +00001281 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001282 {
anthonydcf510d2011-10-30 13:51:40 +00001283 /* Image chromaticity X,Y NB: Y=X if Y not defined
1284 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001285 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001286 */
anthonyf42014d2012-03-25 09:53:06 +00001287 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001288 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001289 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001290 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001291 break;
1292 }
cristyb0f7a182012-04-06 23:33:11 +00001293 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001294 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001295 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001296 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001297 {
anthony92c93bd2012-03-19 14:02:47 +00001298 /* _draw_info only setting */
1299 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001300 break;
1301 }
anthony756cd0d2012-04-08 12:41:44 +00001302 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1303 {
1304 /* link image and setting stacks - option is itself saved on stack! */
1305 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1306 break;
1307 }
anthonyebb73a22012-03-22 14:25:52 +00001308 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001309 }
1310 case 's':
1311 {
anthonyafa3dfc2012-03-03 11:31:30 +00001312 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001313 {
anthonyafbaed72011-10-26 12:05:04 +00001314 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001315 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001316 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001317 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001318 break;
1319 }
anthonyafa3dfc2012-03-03 11:31:30 +00001320 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001321 {
anthonyf42014d2012-03-25 09:53:06 +00001322 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001323 What ??? Why ????
1324 */
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) SetImageOption(_image_info,option+1,ArgOption(NULL));
1328 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001329 break;
1330 }
anthonyafa3dfc2012-03-03 11:31:30 +00001331 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001332 {
anthony7bcfe7f2012-03-30 14:01:22 +00001333 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001334 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001335 SetRandomSecretKey(
cristya30f8e62013-02-19 15:03:45 +00001336 IfSetOption ? (unsigned long) StringToUnsignedLong(arg1)
1337 : (unsigned long) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001338 break;
1339 }
anthonyafa3dfc2012-03-03 11:31:30 +00001340 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001341 {
anthony92c93bd2012-03-19 14:02:47 +00001342 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001343 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001344 */
anthony92c93bd2012-03-19 14:02:47 +00001345 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001346 break;
1347 }
anthonyafa3dfc2012-03-03 11:31:30 +00001348 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001349 {
anthonyf42014d2012-03-25 09:53:06 +00001350 arg1=ArgOption("undefined");
1351 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1352 if (parse < 0)
1353 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1354 option,arg1);
1355 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001356 break;
1357 }
anthonyafa3dfc2012-03-03 11:31:30 +00001358 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001359 {
anthonyafbaed72011-10-26 12:05:04 +00001360 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001361 UPDATE: ensure stroke color is not destroyed is a pattern
1362 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001363 */
anthony72feaa62012-01-17 06:46:23 +00001364 MagickBooleanType
1365 status;
anthonyafbaed72011-10-26 12:05:04 +00001366
1367 ExceptionInfo
1368 *sans;
1369
anthonyfd706f92012-01-19 04:22:02 +00001370 PixelInfo
1371 color;
1372
anthony2a0ec8c2012-03-24 04:35:56 +00001373 arg1 = ArgOption("none"); /* +fill turns it off! */
1374 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001375 if (_draw_info->stroke_pattern != (Image *) NULL)
1376 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001377
1378 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001379 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001380 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001381 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001382
anthony7bcfe7f2012-03-30 14:01:22 +00001383 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001384 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001385 else
anthony92c93bd2012-03-19 14:02:47 +00001386 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001387 break;
1388 }
anthonyafa3dfc2012-03-03 11:31:30 +00001389 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001390 {
anthony7bcfe7f2012-03-30 14:01:22 +00001391 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001392 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001393 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1394 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001395 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001396 break;
1397 }
anthonyafa3dfc2012-03-03 11:31:30 +00001398 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001399 {
anthonyf42014d2012-03-25 09:53:06 +00001400 arg1=ArgOption("undefined");
1401 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1402 if (parse < 0)
1403 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1404 option,arg1);
1405 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001406 break;
1407 }
anthonycd358fc2012-04-16 13:59:03 +00001408#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001409 if (LocaleCompare("subimage-search",option+1) == 0)
1410 {
1411 /* FUTURE: this is only used by CompareImages() which is used
1412 only by the "compare" CLI program at this time. */
1413 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1414 break;
1415 }
anthonycd358fc2012-04-16 13:59:03 +00001416#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001417 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001418 {
anthonyf42014d2012-03-25 09:53:06 +00001419 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001420 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001421 break;
1422 }
anthonyebb73a22012-03-22 14:25:52 +00001423 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001424 }
1425 case 't':
1426 {
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001428 {
anthony72feaa62012-01-17 06:46:23 +00001429 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001430 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001431 break;
1432 }
anthonyafa3dfc2012-03-03 11:31:30 +00001433 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001434 {
anthony4837ac22012-05-18 23:39:48 +00001435 /* Note: arguments do not have percent escapes expanded */
anthony52bef752012-03-27 13:54:47 +00001436 /* FUTURE: move _image_info string to option splay-tree
1437 Other than "montage" what uses "texture" ????
1438 */
anthony92c93bd2012-03-19 14:02:47 +00001439 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001440 break;
1441 }
anthonyafa3dfc2012-03-03 11:31:30 +00001442 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001443 {
anthony4837ac22012-05-18 23:39:48 +00001444 /* Note: arguments do not have percent escapes expanded */
anthony92c93bd2012-03-19 14:02:47 +00001445 _draw_info->fill_pattern=IfSetOption
1446 ?GetImageCache(_image_info,arg1,_exception)
1447 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001448 break;
1449 }
anthonyafa3dfc2012-03-03 11:31:30 +00001450 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001451 {
anthony72feaa62012-01-17 06:46:23 +00001452 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001453 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001454 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001455 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1456 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001457 break;
1458 }
anthonyafa3dfc2012-03-03 11:31:30 +00001459 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001460 {
anthony92c93bd2012-03-19 14:02:47 +00001461 /* FUTURE: both _image_info attribute & ImageOption in use!
1462 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001463 SyncImageSettings() used to set per-image attribute.
1464
anthonyafbaed72011-10-26 12:05:04 +00001465 Note that +transparent-color, means fall-back to image
1466 attribute so ImageOption is deleted, not set to a default.
1467 */
anthony7bcfe7f2012-03-30 14:01:22 +00001468 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001469 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001470 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001471 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001472 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001473 break;
1474 }
anthonyafa3dfc2012-03-03 11:31:30 +00001475 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001476 {
anthony92c93bd2012-03-19 14:02:47 +00001477 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1478 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001479 break;
1480 }
anthonyafa3dfc2012-03-03 11:31:30 +00001481 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001482 {
anthony72feaa62012-01-17 06:46:23 +00001483 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001484 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1485 ArgOption("undefined"));
1486 if (parse < 0)
1487 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1488 option,arg1);
1489 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001490 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001491 break;
1492 }
anthonyebb73a22012-03-22 14:25:52 +00001493 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001494 }
1495 case 'u':
1496 {
anthonyafa3dfc2012-03-03 11:31:30 +00001497 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001498 {
anthony92c93bd2012-03-19 14:02:47 +00001499 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001500 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001501 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001502 break;
1503 }
anthonyafa3dfc2012-03-03 11:31:30 +00001504 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001505 {
anthony72feaa62012-01-17 06:46:23 +00001506 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001507 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001508 FUTURE: this probably should be part of the density setting
1509 */
anthony52bef752012-03-27 13:54:47 +00001510 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1511 ArgOption("undefined"));
1512 if (parse < 0)
1513 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1514 option,arg1);
1515 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001516 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001517 break;
1518 }
anthonyebb73a22012-03-22 14:25:52 +00001519 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001520 }
1521 case 'v':
1522 {
anthonyafa3dfc2012-03-03 11:31:30 +00001523 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001524 {
anthony24aa8822012-03-11 00:56:06 +00001525 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001526 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001527 */
anthony92c93bd2012-03-19 14:02:47 +00001528 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1529 _image_info->verbose= ArgBoolean;
1530 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001531 break;
1532 }
anthonyafa3dfc2012-03-03 11:31:30 +00001533 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001534 {
anthony92c93bd2012-03-19 14:02:47 +00001535 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001536 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001537 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001538 */
anthony92c93bd2012-03-19 14:02:47 +00001539 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001540 break;
1541 }
anthonyafa3dfc2012-03-03 11:31:30 +00001542 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001543 {
anthonyfd706f92012-01-19 04:22:02 +00001544 /* SyncImageSettings() used to set per-image attribute.
1545 This is VERY deep in the image caching structure.
1546 */
anthony52bef752012-03-27 13:54:47 +00001547 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1548 ArgOption("undefined"));
1549 if (parse < 0)
1550 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1551 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001552 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001553 break;
1554 }
anthonyebb73a22012-03-22 14:25:52 +00001555 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001556 }
1557 case 'w':
1558 {
anthonyafa3dfc2012-03-03 11:31:30 +00001559 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001560 {
anthony72feaa62012-01-17 06:46:23 +00001561 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001562 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001563 */
anthony52bef752012-03-27 13:54:47 +00001564 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001565 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001566 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001567 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001568 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001569 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001570 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001571 if (_draw_info->weight <= 800)
1572 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001573 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001574 if (_draw_info->weight >= 100)
1575 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001576 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001577 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001578 break;
1579 }
anthonyafa3dfc2012-03-03 11:31:30 +00001580 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001581 {
anthony72feaa62012-01-17 06:46:23 +00001582 /* Used as a image chromaticity setting
1583 SyncImageSettings() used to set per-image attribute.
1584 */
anthony52bef752012-03-27 13:54:47 +00001585 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001586 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1588 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001589 break;
1590 }
anthonyebb73a22012-03-22 14:25:52 +00001591 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001592 }
1593 default:
anthonyebb73a22012-03-22 14:25:52 +00001594 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001595 }
anthony24aa8822012-03-11 00:56:06 +00001596
anthony4837ac22012-05-18 23:39:48 +00001597 /* clean up percent escape interpreted strings */
cristy862fc612015-02-16 20:49:10 +00001598 if ((arg1 && arg1n) && (arg1 != arg1n ))
1599 arg1=DestroyString((char *) arg1);
1600 if ((arg2 && arg2n) && (arg2 != arg2n ))
1601 arg2=DestroyString((char *) arg2);
anthony4837ac22012-05-18 23:39:48 +00001602
anthony92c93bd2012-03-19 14:02:47 +00001603#undef _image_info
1604#undef _exception
1605#undef _draw_info
1606#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001607#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001608#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001609#undef ArgBooleanNot
1610#undef ArgBooleanString
1611#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001612
anthony31f1bf72012-01-30 12:37:22 +00001613 return;
anthony805a2d42011-09-25 08:25:12 +00001614}
1615
1616/*
1617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1618% %
1619% %
1620% %
anthony43f425d2012-02-26 12:58:58 +00001621+ 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 +00001622% %
1623% %
1624% %
1625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1626%
anthonyc7994672012-11-17 05:33:27 +00001627% CLISimpleOperatorImages() applys one simple image operation given to all
1628% the images in the CLI wand, using any per-image or global settings that was
1629% previously saved in the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001630%
anthonyc7994672012-11-17 05:33:27 +00001631% It is assumed that any such settings are up-to-date.
anthony805a2d42011-09-25 08:25:12 +00001632%
anthony7a4d6102012-07-01 09:48:25 +00001633% The format of the WandSimpleOperatorImages method is:
anthony805a2d42011-09-25 08:25:12 +00001634%
cristy52b632a2014-11-08 00:31:34 +00001635% MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,const char *option,
cristy2c57b742014-10-31 00:40:34 +00001636% const char *arg1, const char *arg2,ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +00001637%
1638% A description of each parameter follows:
1639%
anthony43f425d2012-02-26 12:58:58 +00001640% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001641%
anthonyfd706f92012-01-19 04:22:02 +00001642% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001643%
anthonyfd706f92012-01-19 04:22:02 +00001644% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001645%
anthony805a2d42011-09-25 08:25:12 +00001646*/
anthony31f1bf72012-01-30 12:37:22 +00001647
1648/*
anthonyc7994672012-11-17 05:33:27 +00001649 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1650 image operation to the current image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001651
1652 The image in the list may be modified in three different ways...
1653 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1654 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1655 * one image replace by a list of images (-separate and -crop only!)
1656
anthonyafa3dfc2012-03-03 11:31:30 +00001657 In each case the result replaces the single original image in the list, as
1658 well as the pointer to the modified image (last image added if replaced by a
1659 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001660
1661 As the image pointed to may be replaced, the first image in the list may
1662 also change. GetFirstImageInList() should be used by caller if they wish
1663 return the Image pointer to the first image in list.
1664*/
cristyfe831852013-02-12 14:56:07 +00001665static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
cristy2c57b742014-10-31 00:40:34 +00001666 const char *option, const char *arg1n, const char *arg2n,
1667 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +00001668{
1669 Image *
1670 new_image;
1671
anthony805a2d42011-09-25 08:25:12 +00001672 GeometryInfo
1673 geometry_info;
1674
1675 RectangleInfo
1676 geometry;
1677
1678 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001679 flags;
1680
anthony92c93bd2012-03-19 14:02:47 +00001681 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001682 parse;
anthony92c93bd2012-03-19 14:02:47 +00001683
anthonya322a832013-04-27 06:28:03 +00001684 const char /* percent escaped versions of the args */
anthony964d28e2012-05-17 23:39:46 +00001685 *arg1,
1686 *arg2;
1687
anthonya322a832013-04-27 06:28:03 +00001688#define _image_info (cli_wand->wand.image_info)
1689#define _image (cli_wand->wand.images)
1690#define _exception (cli_wand->wand.exception)
1691#define _draw_info (cli_wand->draw_info)
1692#define _quantize_info (cli_wand->quantize_info)
1693#define _process_flags (cli_wand->process_flags)
1694#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
1695#define IfNormalOp (*option=='-')
1696#define IfPlusOp (*option!='-')
1697#define IsNormalOp IsMagickTrue(IfNormalOp)
1698#define IsPlusOp IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001699
anthony43f425d2012-02-26 12:58:58 +00001700 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001701 assert(cli_wand->signature == MagickWandSignature);
1702 assert(cli_wand->wand.signature == MagickWandSignature);
anthony5330ae02012-03-20 14:17:01 +00001703 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001704 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001705 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001706
anthony964d28e2012-05-17 23:39:46 +00001707 arg1 = arg1n,
1708 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00001709
1710 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00001711 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1712 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1713 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1714 /* Interpret Percent escapes in argument 1 */
1715 if (arg1n != (char *) NULL) {
1716 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1717 if (arg1 == (char *) NULL) {
1718 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1719 arg1=arg1n; /* use the given argument as is */
1720 }
1721 }
1722 if (arg2n != (char *) NULL) {
1723 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1724 if (arg2 == (char *) NULL) {
1725 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1726 arg2=arg2n; /* use the given argument as is */
1727 }
1728 }
1729 }
anthony4837ac22012-05-18 23:39:48 +00001730#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00001731#undef _option_type
1732
1733#if 0
1734 (void) FormatLocaleFile(stderr,
1735 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1736#endif
anthony805a2d42011-09-25 08:25:12 +00001737
cristyf432c632014-12-07 15:11:28 +00001738 new_image = (Image *) NULL; /* the replacement image, if not null at end */
anthony964d28e2012-05-17 23:39:46 +00001739 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001740
anthonyafa3dfc2012-03-03 11:31:30 +00001741 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001742 {
1743 case 'a':
1744 {
anthonyafa3dfc2012-03-03 11:31:30 +00001745 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001746 {
anthonyfd706f92012-01-19 04:22:02 +00001747 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001748 if ((flags & (RhoValue|SigmaValue)) == 0)
1749 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001750 if ((flags & SigmaValue) == 0)
1751 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001752 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001753 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001754 break;
1755 }
anthonyafa3dfc2012-03-03 11:31:30 +00001756 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001757 {
anthonyfe1aa782012-03-24 13:43:04 +00001758 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001759 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001760 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1761 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1762 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001763 _exception);
anthony805a2d42011-09-25 08:25:12 +00001764 break;
1765 }
anthonyafa3dfc2012-03-03 11:31:30 +00001766 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001767 {
anthonyfd706f92012-01-19 04:22:02 +00001768 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001769 if ((flags & (RhoValue|SigmaValue)) == 0)
1770 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001771 if ((flags & SigmaValue) == 0)
1772 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001773 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001774 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001775 break;
1776 }
anthonyafa3dfc2012-03-03 11:31:30 +00001777 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001778 {
cristy288a3532012-08-28 00:19:44 +00001779 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001780 if (parse < 0)
cristyb15b06c2012-08-28 11:36:48 +00001781 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
cristy4366cb82014-09-13 17:57:26 +00001782 option,arg1);
1783 (void) SetImageAlphaChannel(_image,(AlphaChannelOption) parse,
cristy61d844e2014-09-14 00:30:34 +00001784 _exception);
anthony805a2d42011-09-25 08:25:12 +00001785 break;
1786 }
anthonyafa3dfc2012-03-03 11:31:30 +00001787 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001788 {
1789 char
cristy151b66d2015-04-15 10:50:31 +00001790 geometry[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00001791
anthony805a2d42011-09-25 08:25:12 +00001792 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001793 flags=ParseGeometry(arg1,&geometry_info);
cristy8592b052013-02-07 01:24:54 +00001794 if (flags == 0)
anthony22de2722012-04-19 14:43:00 +00001795 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001796 if ((flags & SigmaValue) == 0)
1797 geometry_info.sigma=geometry_info.rho;
anthony964d28e2012-05-17 23:39:46 +00001798 (void) CloneString(&_draw_info->text,arg2);
cristy151b66d2015-04-15 10:50:31 +00001799 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
anthony805a2d42011-09-25 08:25:12 +00001800 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001801 (void) CloneString(&_draw_info->geometry,geometry);
1802 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001803 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001804 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001805 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001806 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001807 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001808 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001809 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001810 (void) AnnotateImage(_image,_draw_info,_exception);
1811 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001812 break;
1813 }
anthonyafa3dfc2012-03-03 11:31:30 +00001814 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001815 {
anthony92c93bd2012-03-19 14:02:47 +00001816 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001817 break;
1818 }
anthonyafa3dfc2012-03-03 11:31:30 +00001819 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001820 {
anthony92c93bd2012-03-19 14:02:47 +00001821 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001822 break;
1823 }
anthonyafa3dfc2012-03-03 11:31:30 +00001824 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001825 {
cristyfa5f6c72013-01-01 14:37:35 +00001826 new_image=AutoOrientImage(_image,_image->orientation,_exception);
anthony805a2d42011-09-25 08:25:12 +00001827 break;
1828 }
anthonyebb73a22012-03-22 14:25:52 +00001829 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001830 }
1831 case 'b':
1832 {
anthonyafa3dfc2012-03-03 11:31:30 +00001833 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001834 {
anthony7bcfe7f2012-03-30 14:01:22 +00001835 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001836 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001837 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001838 break;
1839 }
anthonyafa3dfc2012-03-03 11:31:30 +00001840 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001841 {
anthony805a2d42011-09-25 08:25:12 +00001842 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001843 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001844 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001845 if ((flags & RhoValue) == 0)
1846 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001847 }
anthony92c93bd2012-03-19 14:02:47 +00001848 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001849 break;
1850 }
anthonyafa3dfc2012-03-03 11:31:30 +00001851 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001852 {
anthonyfd706f92012-01-19 04:22:02 +00001853 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001854 if ((flags & (RhoValue|SigmaValue)) == 0)
1855 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001856 if ((flags & SigmaValue) == 0)
1857 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001858 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1859 _exception);
anthony805a2d42011-09-25 08:25:12 +00001860 break;
1861 }
anthonyafa3dfc2012-03-03 11:31:30 +00001862 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001863 {
anthony31f1bf72012-01-30 12:37:22 +00001864 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001865 compose;
1866
1867 const char*
anthony5f867ae2011-10-09 10:28:34 +00001868 value;
1869
anthony22de2722012-04-19 14:43:00 +00001870 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
cristy64ad8f92012-08-03 00:58:24 +00001871 if ((flags & (WidthValue | HeightValue)) == 0)
anthony5330ae02012-03-20 14:17:01 +00001872 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy64ad8f92012-08-03 00:58:24 +00001873 compose=OverCompositeOp;
anthony92c93bd2012-03-19 14:02:47 +00001874 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001875 if (value != (const char *) NULL)
cristy64ad8f92012-08-03 00:58:24 +00001876 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1877 MagickFalse,value);
anthony92c93bd2012-03-19 14:02:47 +00001878 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001879 break;
1880 }
anthonyafa3dfc2012-03-03 11:31:30 +00001881 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001882 {
1883 double
1884 brightness,
1885 contrast;
1886
1887 GeometryInfo
1888 geometry_info;
1889
1890 MagickStatusType
1891 flags;
1892
anthonyfd706f92012-01-19 04:22:02 +00001893 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001894 if ((flags & RhoValue) == 0)
1895 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001896 brightness=geometry_info.rho;
1897 contrast=0.0;
1898 if ((flags & SigmaValue) != 0)
1899 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001900 (void) BrightnessContrastImage(_image,brightness,contrast,
1901 _exception);
anthony805a2d42011-09-25 08:25:12 +00001902 break;
1903 }
anthonyebb73a22012-03-22 14:25:52 +00001904 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001905 }
1906 case 'c':
1907 {
cristy4ceadb82014-03-29 15:30:43 +00001908 if (LocaleCompare("canny",option+1) == 0)
1909 {
1910 flags=ParseGeometry(arg1,&geometry_info);
1911 if ((flags & (RhoValue|SigmaValue)) == 0)
1912 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1913 if ((flags & SigmaValue) == 0)
1914 geometry_info.sigma=1.0;
1915 if ((flags & XiValue) == 0)
cristy2fc10e52014-04-26 14:13:53 +00001916 geometry_info.xi=10;
cristy4ceadb82014-03-29 15:30:43 +00001917 if ((flags & PsiValue) == 0)
cristy2fc10e52014-04-26 14:13:53 +00001918 geometry_info.psi=30;
cristy2b72f792014-03-29 21:58:42 +00001919 if ((flags & PercentValue) != 0)
1920 {
cristy41814f22014-04-09 20:53:11 +00001921 geometry_info.xi/=100.0;
1922 geometry_info.psi/=100.0;
cristy2b72f792014-03-29 21:58:42 +00001923 }
cristy41814f22014-04-09 20:53:11 +00001924 new_image=CannyEdgeImage(_image,geometry_info.rho,geometry_info.sigma,
1925 geometry_info.xi,geometry_info.psi,_exception);
cristy4ceadb82014-03-29 15:30:43 +00001926 break;
1927 }
anthonyafa3dfc2012-03-03 11:31:30 +00001928 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001929 {
anthony4837ac22012-05-18 23:39:48 +00001930 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001931 char
1932 *color_correction_collection;
1933
1934 /*
1935 Color correct with a color decision list.
1936 */
cristy3a5987c2013-11-07 14:18:46 +00001937 color_correction_collection=FileToString(arg1,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001938 if (color_correction_collection == (char *) NULL)
1939 break;
anthony92c93bd2012-03-19 14:02:47 +00001940 (void) ColorDecisionListImage(_image,color_correction_collection,
1941 _exception);
anthony805a2d42011-09-25 08:25:12 +00001942 break;
1943 }
cristy17ada022014-11-07 22:12:23 +00001944 if (LocaleCompare("channel",option+1) == 0)
1945 {
1946 if (IfPlusOp)
1947 {
cristybcd59342015-06-07 14:07:19 +00001948 (void) SetPixelChannelMask(_image,DefaultChannels);
cristy17ada022014-11-07 22:12:23 +00001949 break;
1950 }
1951 parse=ParseChannelOption(arg1);
1952 if (parse < 0)
1953 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
1954 option,arg1);
cristybcd59342015-06-07 14:07:19 +00001955 (void) SetPixelChannelMask(_image,(ChannelType) parse);
cristy17ada022014-11-07 22:12:23 +00001956 break;
1957 }
anthonyafa3dfc2012-03-03 11:31:30 +00001958 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001959 {
anthonyfd706f92012-01-19 04:22:02 +00001960 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001961 if ((flags & (RhoValue|SigmaValue)) == 0)
1962 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001963 if ((flags & SigmaValue) == 0)
1964 geometry_info.sigma=1.0;
1965 if ((flags & XiValue) == 0)
1966 geometry_info.xi=1.0;
cristyee3f7522012-12-21 19:27:44 +00001967 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1968 _exception);
anthony805a2d42011-09-25 08:25:12 +00001969 break;
1970 }
anthonyafa3dfc2012-03-03 11:31:30 +00001971 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001972 {
anthony7bcfe7f2012-03-30 14:01:22 +00001973 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001974 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001975 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1976 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001977 break;
1978 }
anthonyafa3dfc2012-03-03 11:31:30 +00001979 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001980 {
anthony92c93bd2012-03-19 14:02:47 +00001981 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001982 break;
1983 }
anthonyafa3dfc2012-03-03 11:31:30 +00001984 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001985 {
anthonyafa3dfc2012-03-03 11:31:30 +00001986 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001987 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001988 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001989 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001990 break;
1991 }
anthonyafa3dfc2012-03-03 11:31:30 +00001992 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001993 {
anthony4837ac22012-05-18 23:39:48 +00001994 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001995 CacheView
1996 *mask_view;
1997
1998 Image
1999 *mask_image;
2000
2001 register Quantum
2002 *restrict q;
2003
2004 register ssize_t
2005 x;
2006
2007 ssize_t
2008 y;
2009
anthonyafa3dfc2012-03-03 11:31:30 +00002010 if (IfPlusOp) {
anthony4837ac22012-05-18 23:39:48 +00002011 /* use "+clip-mask" Remove the write mask for -clip-path */
anthony92c93bd2012-03-19 14:02:47 +00002012 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002013 break;
2014 }
anthony92c93bd2012-03-19 14:02:47 +00002015 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002016 if (mask_image == (Image *) NULL)
2017 break;
anthony7bcfe7f2012-03-30 14:01:22 +00002018 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00002019 break;
anthony5330ae02012-03-20 14:17:01 +00002020 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002021 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristy46ff2672012-12-14 15:32:26 +00002022 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002023 for (y=0; y < (ssize_t) mask_image->rows; y++)
2024 {
2025 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002026 _exception);
anthony805a2d42011-09-25 08:25:12 +00002027 if (q == (Quantum *) NULL)
2028 break;
2029 for (x=0; x < (ssize_t) mask_image->columns; x++)
2030 {
cristy7d6d3d82014-11-09 17:00:16 +00002031 if (mask_image->alpha_trait == UndefinedPixelTrait)
cristy52b632a2014-11-08 00:31:34 +00002032 SetPixelAlpha(mask_image,(Quantum)
2033 GetPixelIntensity(mask_image,q),q);
cristy81ac7972013-03-31 19:25:23 +00002034 SetPixelGray(mask_image,GetPixelAlpha(mask_image,q),q);
anthony805a2d42011-09-25 08:25:12 +00002035 q+=GetPixelChannels(mask_image);
2036 }
anthony7bcfe7f2012-03-30 14:01:22 +00002037 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002038 break;
2039 }
anthonyfd706f92012-01-19 04:22:02 +00002040 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002041 mask_view=DestroyCacheView(mask_view);
cristy8a46d822012-08-28 23:32:39 +00002042 mask_image->alpha_trait=BlendPixelTrait;
cristy81ac7972013-03-31 19:25:23 +00002043 (void) SetImageColorspace(_image,GRAYColorspace,_exception);
anthony92c93bd2012-03-19 14:02:47 +00002044 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002045 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002046 break;
2047 }
anthonyafa3dfc2012-03-03 11:31:30 +00002048 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002049 {
anthonya322a832013-04-27 06:28:03 +00002050 (void) ClipImagePath(_image,arg1,IsNormalOp,_exception);
anthony4837ac22012-05-18 23:39:48 +00002051 /* Note: Use "+clip-mask" remove the write mask added */
anthony805a2d42011-09-25 08:25:12 +00002052 break;
2053 }
anthonyafa3dfc2012-03-03 11:31:30 +00002054 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002055 {
anthony7bcfe7f2012-03-30 14:01:22 +00002056 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002057 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002058 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002059 break;
2060 }
anthonyafa3dfc2012-03-03 11:31:30 +00002061 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002062 {
2063 KernelInfo
2064 *kernel;
2065
cristy2c57b742014-10-31 00:40:34 +00002066 kernel=AcquireKernelInfo(arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002067 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002068 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002069 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002070 kernel=DestroyKernelInfo(kernel);
2071 break;
2072 }
anthonyafa3dfc2012-03-03 11:31:30 +00002073 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002074 {
anthony5330ae02012-03-20 14:17:01 +00002075 /* Reduce the number of colors in the image.
2076 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002077 */
anthony92c93bd2012-03-19 14:02:47 +00002078 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2079 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002080 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002081 if ((_image->storage_class == DirectClass) ||
2082 _image->colors > _quantize_info->number_colors)
2083 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002084 else
anthony92c93bd2012-03-19 14:02:47 +00002085 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002086 break;
2087 }
anthonyafa3dfc2012-03-03 11:31:30 +00002088 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002089 {
anthony5330ae02012-03-20 14:17:01 +00002090 /* WARNING: this is both a image_info setting (already done)
2091 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002092
2093 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002094 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002095
anthonyd2cdc862011-10-07 14:07:17 +00002096 Note that +colorspace sets "undefined" or no effect on
2097 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002098 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002099 */
anthony92c93bd2012-03-19 14:02:47 +00002100 (void) TransformImageColorspace(_image,
cristye0b9b8f2013-03-28 12:39:39 +00002101 IfNormalOp ? _image_info->colorspace : sRGBColorspace,
anthony92c93bd2012-03-19 14:02:47 +00002102 _exception);
anthony805a2d42011-09-25 08:25:12 +00002103 break;
2104 }
cristy6e0b3bc2014-10-19 17:51:42 +00002105 if (LocaleCompare("connected-components",option+1) == 0)
2106 {
2107 if (IfMagickFalse(IsGeometry(arg1)))
2108 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy52b632a2014-11-08 00:31:34 +00002109 new_image=ConnectedComponentsImage(_image,(size_t)
2110 StringToInteger(arg1),_exception);
cristy6e0b3bc2014-10-19 17:51:42 +00002111 break;
2112 }
anthonyafa3dfc2012-03-03 11:31:30 +00002113 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002114 {
anthonya322a832013-04-27 06:28:03 +00002115 CLIWandWarnReplaced(IfNormalOp?"-level":"+level");
2116 (void) ContrastImage(_image,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002117 break;
2118 }
anthonyafa3dfc2012-03-03 11:31:30 +00002119 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002120 {
2121 double
2122 black_point,
2123 white_point;
2124
2125 MagickStatusType
2126 flags;
2127
anthonyfd706f92012-01-19 04:22:02 +00002128 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002129 if ((flags & RhoValue) == 0)
2130 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002131 black_point=geometry_info.rho;
2132 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2133 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002134 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002135 black_point*=(double) _image->columns*_image->rows/100.0;
2136 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002137 }
cristy496225b2014-11-05 01:50:39 +00002138 white_point=(double) _image->columns*_image->rows-white_point;
anthony92c93bd2012-03-19 14:02:47 +00002139 (void) ContrastStretchImage(_image,black_point,white_point,
2140 _exception);
anthony805a2d42011-09-25 08:25:12 +00002141 break;
2142 }
anthonyafa3dfc2012-03-03 11:31:30 +00002143 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002144 {
cristy77923262015-02-23 21:57:13 +00002145 double
2146 gamma;
2147
anthony805a2d42011-09-25 08:25:12 +00002148 KernelInfo
2149 *kernel_info;
cristy77923262015-02-23 21:57:13 +00002150
2151 register ssize_t
2152 j;
anthony805a2d42011-09-25 08:25:12 +00002153
cristy2c57b742014-10-31 00:40:34 +00002154 kernel_info=AcquireKernelInfo(arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002155 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002156 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy77923262015-02-23 21:57:13 +00002157 gamma=0.0;
2158 for (j=0; j < (ssize_t) (kernel_info->width*kernel_info->height); j++)
2159 gamma+=kernel_info->values[j];
2160 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
2161 for (j=0; j < (ssize_t) (kernel_info->width*kernel_info->height); j++)
2162 kernel_info->values[j]*=gamma;
cristya12d8ba2012-04-29 16:33:41 +00002163 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2164 _exception);
anthony805a2d42011-09-25 08:25:12 +00002165 kernel_info=DestroyKernelInfo(kernel_info);
2166 break;
2167 }
anthonyafa3dfc2012-03-03 11:31:30 +00002168 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002169 {
anthony31f1bf72012-01-30 12:37:22 +00002170 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002171 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002172 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002173 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002174 break;
2175 }
anthonyafa3dfc2012-03-03 11:31:30 +00002176 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002177 {
anthony7bcfe7f2012-03-30 14:01:22 +00002178 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002179 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002180 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2181 _exception);
anthony805a2d42011-09-25 08:25:12 +00002182 break;
2183 }
anthonyebb73a22012-03-22 14:25:52 +00002184 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002185 }
2186 case 'd':
2187 {
anthonyafa3dfc2012-03-03 11:31:30 +00002188 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002189 {
anthony4837ac22012-05-18 23:39:48 +00002190 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002191 StringInfo
2192 *passkey;
2193
cristy3a5987c2013-11-07 14:18:46 +00002194 passkey=FileToStringInfo(arg1,~0UL,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002195 if (passkey == (StringInfo *) NULL)
2196 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2197
2198 (void) PasskeyDecipherImage(_image,passkey,_exception);
2199 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002200 break;
2201 }
anthonyafa3dfc2012-03-03 11:31:30 +00002202 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002203 {
anthony92c93bd2012-03-19 14:02:47 +00002204 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002205 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002206
anthonydcf510d2011-10-30 13:51:40 +00002207 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2208 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002209
anthonyfd706f92012-01-19 04:22:02 +00002210 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002211 */
anthony92c93bd2012-03-19 14:02:47 +00002212 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002213 break;
2214 }
anthonyafa3dfc2012-03-03 11:31:30 +00002215 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002216 {
2217 double
2218 threshold;
2219
anthonyebb73a22012-03-22 14:25:52 +00002220 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002221 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002222 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002223 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002224 }
anthonyafa3dfc2012-03-03 11:31:30 +00002225 else
2226 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002227 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002228 break;
2229 }
anthonyafa3dfc2012-03-03 11:31:30 +00002230 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002231 {
anthony92c93bd2012-03-19 14:02:47 +00002232 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002233 break;
2234 }
anthonyafa3dfc2012-03-03 11:31:30 +00002235 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002236 {
anthony805a2d42011-09-25 08:25:12 +00002237 double
anthonyb1d483a2012-04-14 12:53:56 +00002238 *args;
anthony805a2d42011-09-25 08:25:12 +00002239
anthonyb1d483a2012-04-14 12:53:56 +00002240 ssize_t
2241 count;
anthony805a2d42011-09-25 08:25:12 +00002242
anthony2a0ec8c2012-03-24 04:35:56 +00002243 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2244 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002245 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2246 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002247 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002248 {
anthony80c37752012-01-16 01:03:11 +00002249 double
2250 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002251 /* Special Case - Argument is actually a resize geometry!
2252 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002253 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002254 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002255 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002256 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2257 option,arg2);
2258 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002259 resize_args[0]=(double) geometry.width;
2260 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002261 new_image=DistortImage(_image,(DistortImageMethod) parse,
2262 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002263 break;
2264 }
anthonyb1d483a2012-04-14 12:53:56 +00002265 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002266 args = StringToArrayOfDoubles(arg2,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00002267 if (args == (double *) NULL )
anthonyb1d483a2012-04-14 12:53:56 +00002268 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2269
cristy52b632a2014-11-08 00:31:34 +00002270 new_image=DistortImage(_image,(DistortImageMethod) parse,(size_t)
2271 count,args,IsPlusOp,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002272 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002273 break;
2274 }
anthonyafa3dfc2012-03-03 11:31:30 +00002275 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002276 {
anthony92c93bd2012-03-19 14:02:47 +00002277 (void) CloneString(&_draw_info->primitive,arg1);
2278 (void) DrawImage(_image,_draw_info,_exception);
cristyf432c632014-12-07 15:11:28 +00002279 (void) CloneString(&_draw_info->primitive,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002280 break;
2281 }
anthonyebb73a22012-03-22 14:25:52 +00002282 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002283 }
2284 case 'e':
2285 {
anthonyafa3dfc2012-03-03 11:31:30 +00002286 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002287 {
anthonyfd706f92012-01-19 04:22:02 +00002288 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002289 if ((flags & (RhoValue|SigmaValue)) == 0)
2290 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy9dc4c512013-03-24 01:38:00 +00002291 new_image=EdgeImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002292 break;
2293 }
anthonyafa3dfc2012-03-03 11:31:30 +00002294 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002295 {
anthonyfd706f92012-01-19 04:22:02 +00002296 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002297 if ((flags & (RhoValue|SigmaValue)) == 0)
2298 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002299 if ((flags & SigmaValue) == 0)
2300 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002301 new_image=EmbossImage(_image,geometry_info.rho,
2302 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002303 break;
2304 }
anthonyafa3dfc2012-03-03 11:31:30 +00002305 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002306 {
anthony4837ac22012-05-18 23:39:48 +00002307 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002308 StringInfo
2309 *passkey;
2310
cristy3a5987c2013-11-07 14:18:46 +00002311 passkey=FileToStringInfo(arg1,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002312 if (passkey != (StringInfo *) NULL)
2313 {
anthony92c93bd2012-03-19 14:02:47 +00002314 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002315 passkey=DestroyStringInfo(passkey);
2316 }
2317 break;
2318 }
anthonyafa3dfc2012-03-03 11:31:30 +00002319 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002320 {
anthony92c93bd2012-03-19 14:02:47 +00002321 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002322 break;
2323 }
anthonyafa3dfc2012-03-03 11:31:30 +00002324 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002325 {
anthony92c93bd2012-03-19 14:02:47 +00002326 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002327 break;
2328 }
anthonyafa3dfc2012-03-03 11:31:30 +00002329 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002330 {
2331 double
2332 constant;
2333
anthony2a0ec8c2012-03-24 04:35:56 +00002334 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2335 if ( parse < 0 )
2336 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2337 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002338 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002339 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002340 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002341 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2342 _exception);
anthony805a2d42011-09-25 08:25:12 +00002343 break;
2344 }
anthonyafa3dfc2012-03-03 11:31:30 +00002345 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002346 {
anthony7bcfe7f2012-03-30 14:01:22 +00002347 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002348 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002349 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002350 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002351 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002352 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002353 geometry.height=_image->rows;
2354 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002355 break;
2356 }
anthonyebb73a22012-03-22 14:25:52 +00002357 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002358 }
2359 case 'f':
2360 {
anthonyafa3dfc2012-03-03 11:31:30 +00002361 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002362 {
anthony92c93bd2012-03-19 14:02:47 +00002363 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002364 break;
2365 }
anthonyafa3dfc2012-03-03 11:31:30 +00002366 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002367 {
anthony92c93bd2012-03-19 14:02:47 +00002368 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002369 break;
2370 }
anthonyafa3dfc2012-03-03 11:31:30 +00002371 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002372 {
2373 PixelInfo
2374 target;
2375
anthony7bcfe7f2012-03-30 14:01:22 +00002376 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002377 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002378 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2379 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2380 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
anthonya322a832013-04-27 06:28:03 +00002381 geometry.y,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002382 break;
2383 }
anthonyafa3dfc2012-03-03 11:31:30 +00002384 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002385 {
2386 FrameInfo
2387 frame_info;
2388
anthony31f1bf72012-01-30 12:37:22 +00002389 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002390 compose;
2391
2392 const char*
2393 value;
2394
anthony92c93bd2012-03-19 14:02:47 +00002395 value=GetImageOption(_image_info,"compose");
anthony92c93bd2012-03-19 14:02:47 +00002396 compose=OverCompositeOp; /* use Over not _image->compose */
cristy4b892612012-08-03 19:31:31 +00002397 if (value != (const char *) NULL)
2398 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2399 MagickFalse,value);
anthony7bcfe7f2012-03-30 14:01:22 +00002400 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002401 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002402 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002403 frame_info.width=geometry.width;
2404 frame_info.height=geometry.height;
anthony805a2d42011-09-25 08:25:12 +00002405 frame_info.outer_bevel=geometry.x;
2406 frame_info.inner_bevel=geometry.y;
2407 frame_info.x=(ssize_t) frame_info.width;
2408 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002409 frame_info.width=_image->columns+2*frame_info.width;
2410 frame_info.height=_image->rows+2*frame_info.height;
2411 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002412 break;
2413 }
anthonyafa3dfc2012-03-03 11:31:30 +00002414 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002415 {
anthony805a2d42011-09-25 08:25:12 +00002416 double
anthonyb1d483a2012-04-14 12:53:56 +00002417 *args;
anthony805a2d42011-09-25 08:25:12 +00002418
anthonyb1d483a2012-04-14 12:53:56 +00002419 ssize_t
2420 count;
anthony805a2d42011-09-25 08:25:12 +00002421
anthony2a0ec8c2012-03-24 04:35:56 +00002422 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2423 if ( parse < 0 )
2424 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2425 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002426 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002427 args = StringToArrayOfDoubles(arg2,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00002428 if (args == (double *) NULL )
anthonyb1d483a2012-04-14 12:53:56 +00002429 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2430
cristy52b632a2014-11-08 00:31:34 +00002431 (void) FunctionImage(_image,(MagickFunction)parse,(size_t) count,args,
anthonyb1d483a2012-04-14 12:53:56 +00002432 _exception);
2433 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002434 break;
2435 }
anthonyebb73a22012-03-22 14:25:52 +00002436 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002437 }
2438 case 'g':
2439 {
anthonyafa3dfc2012-03-03 11:31:30 +00002440 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002441 {
anthony7a4d6102012-07-01 09:48:25 +00002442 double
2443 constant;
2444
anthony7bcfe7f2012-03-30 14:01:22 +00002445 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002446 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony7a4d6102012-07-01 09:48:25 +00002447 constant=StringToDouble(arg1,(char **) NULL);
2448#if 0
2449 /* Using Gamma, via a cache */
2450 if (IfPlusOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002451 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002452 (void) GammaImage(_image,constant,_exception);
2453#else
2454 /* Using Evaluate POW, direct update of values - more accurite */
anthonyafa3dfc2012-03-03 11:31:30 +00002455 if (IfNormalOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002456 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002457 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
cristya4943882015-02-11 11:25:46 +00002458 _image->gamma*=StringToDouble(arg1,(char **) NULL);
anthony7a4d6102012-07-01 09:48:25 +00002459#endif
2460 /* Set gamma setting -- Old meaning of "+gamma"
2461 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2462 */
anthony805a2d42011-09-25 08:25:12 +00002463 break;
2464 }
anthony975a8d72012-04-12 13:54:36 +00002465 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002466 {
anthonyfd706f92012-01-19 04:22:02 +00002467 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002468 if ((flags & (RhoValue|SigmaValue)) == 0)
2469 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002470 if ((flags & SigmaValue) == 0)
2471 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002472 new_image=GaussianBlurImage(_image,geometry_info.rho,
2473 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002474 break;
2475 }
anthony975a8d72012-04-12 13:54:36 +00002476 if (LocaleCompare("gaussian",option+1) == 0)
2477 {
anthony464f1c42012-04-22 08:51:01 +00002478 CLIWandWarnReplaced("-gaussian-blur");
cristy52b632a2014-11-08 00:31:34 +00002479 (void) CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL,exception);
anthony975a8d72012-04-12 13:54:36 +00002480 }
anthonyafa3dfc2012-03-03 11:31:30 +00002481 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002482 {
anthonyfd706f92012-01-19 04:22:02 +00002483 /*
anthony31f1bf72012-01-30 12:37:22 +00002484 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002485 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002486 FUTURE: Why if no 'offset' does this resize ALL images?
2487 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002488 */
anthonyafa3dfc2012-03-03 11:31:30 +00002489 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002490 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002491 if (_image->geometry != (char *) NULL)
2492 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002493 break;
2494 }
anthony7bcfe7f2012-03-30 14:01:22 +00002495 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002496 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002497 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002498 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002499 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002500 else
anthony92c93bd2012-03-19 14:02:47 +00002501 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002502 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002503 break;
2504 }
cristyab943592013-03-29 16:47:23 +00002505 if (LocaleCompare("grayscale",option+1) == 0)
cristye0b9b8f2013-03-28 12:39:39 +00002506 {
cristyab943592013-03-29 16:47:23 +00002507 parse=ParseCommandOption(MagickPixelIntensityOptions,
cristye0b9b8f2013-03-28 12:39:39 +00002508 MagickFalse,arg1);
cristyab943592013-03-29 16:47:23 +00002509 if (parse < 0)
2510 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
2511 option,arg1);
2512 (void) GrayscaleImage(_image,(PixelIntensityMethod) parse,_exception);
cristye0b9b8f2013-03-28 12:39:39 +00002513 break;
2514 }
anthonyebb73a22012-03-22 14:25:52 +00002515 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002516 }
cristy2fc10e52014-04-26 14:13:53 +00002517 case 'h':
2518 {
2519 if (LocaleCompare("hough-lines",option+1) == 0)
2520 {
2521 flags=ParseGeometry(arg1,&geometry_info);
2522 if ((flags & (RhoValue|SigmaValue)) == 0)
2523 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2524 if ((flags & SigmaValue) == 0)
cristyd5b8d2a2014-04-27 17:43:33 +00002525 geometry_info.sigma=geometry_info.rho;
cristy2fc10e52014-04-26 14:13:53 +00002526 if ((flags & XiValue) == 0)
cristy20f90422014-04-27 13:34:21 +00002527 geometry_info.xi=40;
2528 new_image=HoughLineImage(_image,(size_t) geometry_info.rho,
2529 (size_t) geometry_info.sigma,(size_t) geometry_info.xi,_exception);
cristy2fc10e52014-04-26 14:13:53 +00002530 break;
2531 }
2532 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2533 }
anthony805a2d42011-09-25 08:25:12 +00002534 case 'i':
2535 {
anthonyafa3dfc2012-03-03 11:31:30 +00002536 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002537 {
anthony31f1bf72012-01-30 12:37:22 +00002538 const char
2539 *format,
anthony805a2d42011-09-25 08:25:12 +00002540 *text;
2541
anthony92c93bd2012-03-19 14:02:47 +00002542 format=GetImageOption(_image_info,"format");
cristyf9b9b662013-05-25 12:50:16 +00002543 if (format == (char *) NULL)
2544 {
2545 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2546 _exception);
2547 break;
2548 }
anthony92c93bd2012-03-19 14:02:47 +00002549 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002550 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002551 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
cristyf9b9b662013-05-25 12:50:16 +00002552 option);
anthony805a2d42011-09-25 08:25:12 +00002553 (void) fputs(text,stdout);
anthony31f1bf72012-01-30 12:37:22 +00002554 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002555 break;
2556 }
anthonyafa3dfc2012-03-03 11:31:30 +00002557 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002558 {
anthonyb1e21ed2012-04-20 12:43:12 +00002559 flags=ParseGeometry(arg1,&geometry_info);
2560 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002561 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002562 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2563 _exception);
anthony805a2d42011-09-25 08:25:12 +00002564 break;
2565 }
anthonyafa3dfc2012-03-03 11:31:30 +00002566 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002567 {
anthonyfe1aa782012-03-24 13:43:04 +00002568 /* FUTURE: New to IMv7
2569 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002570 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002571 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002572 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2573 new_image=InterpolativeResizeImage(_image,geometry.width,
2574 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002575 break;
2576 }
anthonyebb73a22012-03-22 14:25:52 +00002577 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002578 }
cristy3b207f82014-09-27 14:21:20 +00002579 case 'k':
2580 {
2581 if (LocaleCompare("kuwahara",option+1) == 0)
2582 {
2583 /*
2584 Edge preserving blur.
2585 */
2586 flags=ParseGeometry(arg1,&geometry_info);
2587 if ((flags & (RhoValue|SigmaValue)) == 0)
2588 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2589 if ((flags & SigmaValue) == 0)
cristy25ea9362014-10-04 01:12:09 +00002590 geometry_info.sigma=geometry_info.rho-0.5;
cristy3b207f82014-09-27 14:21:20 +00002591 new_image=KuwaharaImage(_image,geometry_info.rho,geometry_info.sigma,
2592 _exception);
2593 break;
2594 }
2595 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2596 }
anthony805a2d42011-09-25 08:25:12 +00002597 case 'l':
2598 {
anthonyafa3dfc2012-03-03 11:31:30 +00002599 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002600 {
anthonyfd706f92012-01-19 04:22:02 +00002601 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002602 if ((flags & (RhoValue|SigmaValue)) == 0)
2603 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyb5c691e2012-09-14 17:12:40 +00002604 if ((flags & SigmaValue) == 0)
2605 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00002606 if ((flags & PercentValue) != 0)
2607 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002608 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002609 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002610 _exception);
anthony805a2d42011-09-25 08:25:12 +00002611 break;
2612 }
anthonyafa3dfc2012-03-03 11:31:30 +00002613 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002614 {
cristya19f1d72012-08-07 18:24:38 +00002615 double
anthony805a2d42011-09-25 08:25:12 +00002616 black_point,
2617 gamma,
2618 white_point;
2619
2620 MagickStatusType
2621 flags;
2622
anthonyfd706f92012-01-19 04:22:02 +00002623 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002624 if ((flags & RhoValue) == 0)
2625 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002626 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002627 white_point=(double) QuantumRange;
anthony805a2d42011-09-25 08:25:12 +00002628 if ((flags & SigmaValue) != 0)
2629 white_point=geometry_info.sigma;
2630 gamma=1.0;
2631 if ((flags & XiValue) != 0)
2632 gamma=geometry_info.xi;
2633 if ((flags & PercentValue) != 0)
2634 {
cristya19f1d72012-08-07 18:24:38 +00002635 black_point*=(double) (QuantumRange/100.0);
2636 white_point*=(double) (QuantumRange/100.0);
anthony805a2d42011-09-25 08:25:12 +00002637 }
2638 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002639 white_point=(double) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002640 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002641 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002642 else
anthony92c93bd2012-03-19 14:02:47 +00002643 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002644 break;
2645 }
anthonyafa3dfc2012-03-03 11:31:30 +00002646 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002647 {
2648 char
cristy151b66d2015-04-15 10:50:31 +00002649 token[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00002650
2651 const char
2652 *p;
2653
2654 PixelInfo
2655 black_point,
2656 white_point;
2657
anthonyfd706f92012-01-19 04:22:02 +00002658 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002659 GetMagickToken(p,&p,token); /* get black point color */
2660 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002661 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002662 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002663 else
cristy269c9412011-10-13 23:41:15 +00002664 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002665 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002666 if (isalpha((int) token[0]) || (token[0] == '#'))
2667 GetMagickToken(p,&p,token);
2668 if (*token == '\0')
2669 white_point=black_point; /* set everything to that color */
2670 else
2671 {
2672 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2673 GetMagickToken(p,&p,token); /* Get white point color. */
2674 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002675 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002676 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002677 else
cristy269c9412011-10-13 23:41:15 +00002678 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002679 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002680 }
anthony92c93bd2012-03-19 14:02:47 +00002681 (void) LevelImageColors(_image,&black_point,&white_point,
anthonya322a832013-04-27 06:28:03 +00002682 IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002683 break;
2684 }
anthonyafa3dfc2012-03-03 11:31:30 +00002685 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002686 {
2687 double
2688 black_point,
2689 white_point;
2690
2691 MagickStatusType
2692 flags;
2693
anthonyfd706f92012-01-19 04:22:02 +00002694 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002695 if ((flags & RhoValue) == 0)
2696 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002697 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002698 white_point=(double) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002699 if ((flags & SigmaValue) != 0)
2700 white_point=geometry_info.sigma;
2701 if ((flags & PercentValue) != 0)
2702 {
anthony92c93bd2012-03-19 14:02:47 +00002703 black_point*=(double) _image->columns*_image->rows/100.0;
2704 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002705 }
2706 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002707 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002708 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002709 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002710 break;
2711 }
anthonyafa3dfc2012-03-03 11:31:30 +00002712 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002713 {
anthonyfe1aa782012-03-24 13:43:04 +00002714 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002715 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002716 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002717 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002718 if ((flags & XValue) == 0)
2719 geometry.x=1;
2720 if ((flags & YValue) == 0)
2721 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002722 new_image=LiquidRescaleImage(_image,geometry.width,
2723 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002724 break;
2725 }
anthonyebb73a22012-03-22 14:25:52 +00002726 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002727 }
2728 case 'm':
2729 {
cristy7220ee42013-04-14 01:30:34 +00002730 if (LocaleCompare("magnify",option+1) == 0)
2731 {
2732 new_image=MagnifyImage(_image,_exception);
2733 break;
2734 }
anthonyafa3dfc2012-03-03 11:31:30 +00002735 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002736 {
anthony464f1c42012-04-22 08:51:01 +00002737 CLIWandWarnReplaced("-remap");
cristy52b632a2014-11-08 00:31:34 +00002738 (void) CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002739 break;
2740 }
anthonyafa3dfc2012-03-03 11:31:30 +00002741 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002742 {
anthony4837ac22012-05-18 23:39:48 +00002743 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002744 Image
2745 *mask;
2746
anthonyafa3dfc2012-03-03 11:31:30 +00002747 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002748 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002749 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002750 break;
2751 }
anthony5330ae02012-03-20 14:17:01 +00002752 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002753 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002754 if (mask == (Image *) NULL)
2755 break;
anthony92c93bd2012-03-19 14:02:47 +00002756 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002757 mask=DestroyImage(mask);
2758 break;
2759 }
cristy52ad9e92013-02-08 23:23:29 +00002760 if (LocaleCompare("matte",option+1) == 0)
2761 {
2762 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2763 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
cristy1309fc32014-04-26 18:48:37 +00002764 DeactivateAlphaChannel, _exception);
cristy52ad9e92013-02-08 23:23:29 +00002765 break;
2766 }
cristy2fc10e52014-04-26 14:13:53 +00002767 if (LocaleCompare("mean-shift",option+1) == 0)
2768 {
2769 flags=ParseGeometry(arg1,&geometry_info);
2770 if ((flags & (RhoValue|SigmaValue)) == 0)
2771 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2772 if ((flags & SigmaValue) == 0)
2773 geometry_info.sigma=1.0;
2774 if ((flags & XiValue) == 0)
cristy1309fc32014-04-26 18:48:37 +00002775 geometry_info.xi=0.10*QuantumRange;
2776 if ((flags & PercentValue) != 0)
2777 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2778 new_image=MeanShiftImage(_image,(size_t) geometry_info.rho,
2779 (size_t) geometry_info.sigma,geometry_info.xi,_exception);
cristy2fc10e52014-04-26 14:13:53 +00002780 break;
2781 }
cristy52ad9e92013-02-08 23:23:29 +00002782 if (LocaleCompare("median",option+1) == 0)
2783 {
2784 CLIWandWarnReplaced("-statistic Median");
cristy52b632a2014-11-08 00:31:34 +00002785 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1,exception);
cristy52ad9e92013-02-08 23:23:29 +00002786 break;
2787 }
2788 if (LocaleCompare("mode",option+1) == 0)
2789 {
2790 /* FUTURE: note this is also a special "montage" option */
2791 CLIWandWarnReplaced("-statistic Mode");
cristy52b632a2014-11-08 00:31:34 +00002792 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1,exception);
cristy52ad9e92013-02-08 23:23:29 +00002793 break;
2794 }
anthonyafa3dfc2012-03-03 11:31:30 +00002795 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002796 {
anthony7bcfe7f2012-03-30 14:01:22 +00002797 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002798 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002799 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002800 break;
2801 }
anthonyafa3dfc2012-03-03 11:31:30 +00002802 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002803 {
anthony92c93bd2012-03-19 14:02:47 +00002804 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002805 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002806 break;
2807 }
anthonyafa3dfc2012-03-03 11:31:30 +00002808 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002809 {
anthony92c93bd2012-03-19 14:02:47 +00002810 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002811 break;
2812 }
anthonyafa3dfc2012-03-03 11:31:30 +00002813 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002814 {
2815 char
cristy151b66d2015-04-15 10:50:31 +00002816 token[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00002817
2818 const char
2819 *p;
2820
2821 KernelInfo
2822 *kernel;
2823
anthony805a2d42011-09-25 08:25:12 +00002824 ssize_t
2825 iterations;
2826
anthonyfd706f92012-01-19 04:22:02 +00002827 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002828 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002829 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2830 if ( parse < 0 )
cristy2c57b742014-10-31 00:40:34 +00002831 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",option,
2832 arg1);
anthony805a2d42011-09-25 08:25:12 +00002833 iterations=1L;
2834 GetMagickToken(p,&p,token);
2835 if ((*p == ':') || (*p == ','))
2836 GetMagickToken(p,&p,token);
2837 if ((*p != '\0'))
2838 iterations=(ssize_t) StringToLong(p);
cristy2c57b742014-10-31 00:40:34 +00002839 kernel=AcquireKernelInfo(arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00002840 if (kernel == (KernelInfo *) NULL)
cristy2c57b742014-10-31 00:40:34 +00002841 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",option,arg2);
2842 new_image=MorphologyImage(_image,(MorphologyMethod)parse,iterations,
2843 kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002844 kernel=DestroyKernelInfo(kernel);
2845 break;
2846 }
anthonyafa3dfc2012-03-03 11:31:30 +00002847 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002848 {
anthonyfd706f92012-01-19 04:22:02 +00002849 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002850 if ((flags & (RhoValue|SigmaValue)) == 0)
2851 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002852 if ((flags & SigmaValue) == 0)
2853 geometry_info.sigma=1.0;
cristy2c57b742014-10-31 00:40:34 +00002854 new_image=MotionBlurImage(_image,geometry_info.rho,geometry_info.sigma,
2855 geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002856 break;
2857 }
anthonyebb73a22012-03-22 14:25:52 +00002858 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002859 }
2860 case 'n':
2861 {
anthonyafa3dfc2012-03-03 11:31:30 +00002862 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002863 {
anthonya322a832013-04-27 06:28:03 +00002864 (void) NegateImage(_image, IsPlusOp, _exception);
anthony805a2d42011-09-25 08:25:12 +00002865 break;
2866 }
anthonyafa3dfc2012-03-03 11:31:30 +00002867 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002868 {
anthony975a8d72012-04-12 13:54:36 +00002869 double
2870 attenuate;
2871
2872 const char*
2873 value;
2874
anthonyafa3dfc2012-03-03 11:31:30 +00002875 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002876 {
anthony464f1c42012-04-22 08:51:01 +00002877 CLIWandWarnReplaced("-statistic NonPeak");
cristy52b632a2014-11-08 00:31:34 +00002878 (void) CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1,exception);
anthony975a8d72012-04-12 13:54:36 +00002879 break;
anthony805a2d42011-09-25 08:25:12 +00002880 }
anthony975a8d72012-04-12 13:54:36 +00002881 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2882 if ( parse < 0 )
2883 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2884 option,arg1);
2885 attenuate=1.0;
2886 value=GetImageOption(_image_info,"attenuate");
2887 if (value != (const char *) NULL)
2888 attenuate=StringToDouble(value,(char **) NULL);
2889 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2890 _exception);
anthony805a2d42011-09-25 08:25:12 +00002891 break;
2892 }
anthonyafa3dfc2012-03-03 11:31:30 +00002893 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002894 {
anthony92c93bd2012-03-19 14:02:47 +00002895 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002896 break;
2897 }
anthonyebb73a22012-03-22 14:25:52 +00002898 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002899 }
2900 case 'o':
2901 {
anthonyafa3dfc2012-03-03 11:31:30 +00002902 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002903 {
2904 PixelInfo
2905 target;
2906
anthony92c93bd2012-03-19 14:02:47 +00002907 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
anthonya322a832013-04-27 06:28:03 +00002908 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,IsPlusOp,
anthony92c93bd2012-03-19 14:02:47 +00002909 _exception);
anthony805a2d42011-09-25 08:25:12 +00002910 break;
2911 }
anthonyafa3dfc2012-03-03 11:31:30 +00002912 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002913 {
anthony92c93bd2012-03-19 14:02:47 +00002914 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002915 break;
2916 }
anthonyebb73a22012-03-22 14:25:52 +00002917 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002918 }
2919 case 'p':
2920 {
anthonyafa3dfc2012-03-03 11:31:30 +00002921 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002922 {
anthony22de2722012-04-19 14:43:00 +00002923 flags=ParseGeometry(arg1,&geometry_info);
2924 if ((flags & (RhoValue|SigmaValue)) == 0)
2925 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002926 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2927 _exception);
anthony805a2d42011-09-25 08:25:12 +00002928 break;
2929 }
cristy7884a932012-11-04 14:33:51 +00002930 if (LocaleCompare("perceptible",option+1) == 0)
2931 {
2932 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2933 _exception);
2934 break;
2935 }
anthonyafa3dfc2012-03-03 11:31:30 +00002936 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002937 {
cristye9e3d382011-12-14 01:50:13 +00002938 const char
2939 *caption;
2940
anthony805a2d42011-09-25 08:25:12 +00002941 double
2942 angle;
2943
anthony7bc87992012-03-25 02:32:51 +00002944 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002945 RandomInfo
cristy2c57b742014-10-31 00:40:34 +00002946 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002947
anthonyf42014d2012-03-25 09:53:06 +00002948 random_info=AcquireRandomInfo();
2949 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2950 random_info=DestroyRandomInfo(random_info);
2951 }
anthony7bc87992012-03-25 02:32:51 +00002952 else {
anthonyf42014d2012-03-25 09:53:06 +00002953 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002954 if ((flags & RhoValue) == 0)
2955 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002956 angle=geometry_info.rho;
2957 }
anthony92c93bd2012-03-19 14:02:47 +00002958 caption=GetImageProperty(_image,"caption",_exception);
2959 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2960 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002961 break;
2962 }
anthonyafa3dfc2012-03-03 11:31:30 +00002963 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002964 {
anthony22de2722012-04-19 14:43:00 +00002965 flags=ParseGeometry(arg1,&geometry_info);
2966 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002967 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002968 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002969 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002970 break;
2971 }
anthonyafa3dfc2012-03-03 11:31:30 +00002972 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002973 {
anthony31f1bf72012-01-30 12:37:22 +00002974 /* FUTURE: should be a 'Genesis' option?
2975 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002976 Why???
cristy947cb4c2011-10-20 18:41:46 +00002977 */
anthony7bc87992012-03-25 02:32:51 +00002978 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2979 if ( parse < 0 )
2980 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2981 option,arg1);
2982 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002983 break;
2984 }
anthonyafa3dfc2012-03-03 11:31:30 +00002985 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002986 {
anthony4837ac22012-05-18 23:39:48 +00002987 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002988 const char
2989 *name;
2990
2991 const StringInfo
2992 *profile;
2993
2994 Image
2995 *profile_image;
2996
2997 ImageInfo
2998 *profile_info;
2999
anthonyafa3dfc2012-03-03 11:31:30 +00003000 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003001 { /* Remove a profile from the _image. */
3002 (void) ProfileImage(_image,arg1,(const unsigned char *)
3003 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003004 break;
3005 }
anthony92c93bd2012-03-19 14:02:47 +00003006 /* Associate a profile with the _image. */
3007 profile_info=CloneImageInfo(_image_info);
3008 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003009 if (profile != (StringInfo *) NULL)
3010 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003011 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003012 profile_info=DestroyImageInfo(profile_info);
3013 if (profile_image == (Image *) NULL)
3014 {
3015 StringInfo
3016 *profile;
3017
anthony92c93bd2012-03-19 14:02:47 +00003018 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003019 (void) CopyMagickString(profile_info->filename,arg1,
cristy151b66d2015-04-15 10:50:31 +00003020 MagickPathExtent);
anthony92c93bd2012-03-19 14:02:47 +00003021 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003022 if (profile != (StringInfo *) NULL)
3023 {
anthony92c93bd2012-03-19 14:02:47 +00003024 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003025 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003026 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003027 profile=DestroyStringInfo(profile);
3028 }
3029 profile_info=DestroyImageInfo(profile_info);
3030 break;
3031 }
3032 ResetImageProfileIterator(profile_image);
3033 name=GetNextImageProfile(profile_image);
3034 while (name != (const char *) NULL)
3035 {
3036 profile=GetImageProfile(profile_image,name);
3037 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003038 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3039 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003040 name=GetNextImageProfile(profile_image);
3041 }
3042 profile_image=DestroyImage(profile_image);
3043 break;
3044 }
anthonyebb73a22012-03-22 14:25:52 +00003045 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003046 }
anthony805a2d42011-09-25 08:25:12 +00003047 case 'r':
3048 {
dirk6d612cf2014-03-13 21:17:23 +00003049 if (LocaleCompare("rotational-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003050 {
anthonyfd706f92012-01-19 04:22:02 +00003051 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003052 if ((flags & RhoValue) == 0)
3053 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
dirk6d612cf2014-03-13 21:17:23 +00003054 new_image=RotationalBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003055 break;
3056 }
anthonyafa3dfc2012-03-03 11:31:30 +00003057 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003058 {
anthony7bcfe7f2012-03-30 14:01:22 +00003059 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003060 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003061 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthonya322a832013-04-27 06:28:03 +00003062 (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003063 break;
3064 }
anthonyafa3dfc2012-03-03 11:31:30 +00003065 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003066 {
anthony7bcfe7f2012-03-30 14:01:22 +00003067 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003068 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003069 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003070 break;
3071 }
anthony975a8d72012-04-12 13:54:36 +00003072 if (LocaleCompare("recolor",option+1) == 0)
3073 {
anthony464f1c42012-04-22 08:51:01 +00003074 CLIWandWarnReplaced("-color-matrix");
cristy52b632a2014-11-08 00:31:34 +00003075 (void) CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL,exception);
anthony975a8d72012-04-12 13:54:36 +00003076 }
anthonyafa3dfc2012-03-03 11:31:30 +00003077 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003078 {
anthony4837ac22012-05-18 23:39:48 +00003079 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00003080 Image
3081 *remap_image;
3082
anthony92c93bd2012-03-19 14:02:47 +00003083 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003084 if (remap_image == (Image *) NULL)
3085 break;
anthony92c93bd2012-03-19 14:02:47 +00003086 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003087 remap_image=DestroyImage(remap_image);
3088 break;
3089 }
anthonyafa3dfc2012-03-03 11:31:30 +00003090 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003091 {
anthonyafa3dfc2012-03-03 11:31:30 +00003092 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003093 {
anthony7bcfe7f2012-03-30 14:01:22 +00003094 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00003095 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3096 arg1);
3097 (void) ResetImagePage(_image,arg1);
3098 }
anthony31f1bf72012-01-30 12:37:22 +00003099 else
anthony92c93bd2012-03-19 14:02:47 +00003100 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003101 break;
3102 }
anthonyafa3dfc2012-03-03 11:31:30 +00003103 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003104 {
anthonyf46d4262012-03-26 03:30:34 +00003105 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00003106 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003107 if ((flags & (RhoValue|SigmaValue)) == 0)
3108 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003109 if ((flags & SigmaValue) == 0)
3110 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003111 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003112 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003113 break;
3114 }
anthonyafa3dfc2012-03-03 11:31:30 +00003115 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003116 {
anthony7bcfe7f2012-03-30 14:01:22 +00003117 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003118 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003119 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3120 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003121 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003122 break;
3123 }
anthonyafa3dfc2012-03-03 11:31:30 +00003124 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003125 {
anthony7bcfe7f2012-03-30 14:01:22 +00003126 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003127 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003128 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3129 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003130 break;
3131 }
anthonyafa3dfc2012-03-03 11:31:30 +00003132 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003133 {
anthony22de2722012-04-19 14:43:00 +00003134 flags=ParseGeometry(arg1,&geometry_info);
3135 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003136 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003137 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003138 break;
3139 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3140 break;
anthony92c93bd2012-03-19 14:02:47 +00003141 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003142 break;
3143 }
anthonyebb73a22012-03-22 14:25:52 +00003144 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003145 }
3146 case 's':
3147 {
anthonyafa3dfc2012-03-03 11:31:30 +00003148 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003149 {
anthonyfe1aa782012-03-24 13:43:04 +00003150 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003151 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003152 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003153 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3154 new_image=SampleImage(_image,geometry.width,geometry.height,
3155 _exception);
anthony805a2d42011-09-25 08:25:12 +00003156 break;
3157 }
anthonyafa3dfc2012-03-03 11:31:30 +00003158 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003159 {
anthonyfe1aa782012-03-24 13:43:04 +00003160 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003161 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003162 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003163 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3164 new_image=ScaleImage(_image,geometry.width,geometry.height,
3165 _exception);
anthony805a2d42011-09-25 08:25:12 +00003166 break;
3167 }
anthonyf42014d2012-03-25 09:53:06 +00003168 if (LocaleCompare("segment",option+1) == 0)
3169 {
anthonyf42014d2012-03-25 09:53:06 +00003170 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003171 if ((flags & (RhoValue|SigmaValue)) == 0)
3172 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003173 if ((flags & SigmaValue) == 0)
3174 geometry_info.sigma=1.0;
3175 (void) SegmentImage(_image,_image->colorspace,
3176 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3177 _exception);
3178 break;
3179 }
anthonyafa3dfc2012-03-03 11:31:30 +00003180 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003181 {
anthonyfd706f92012-01-19 04:22:02 +00003182 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003183 if ((flags & (RhoValue|SigmaValue)) == 0)
3184 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3185 if ((flags & SigmaValue) == 0)
3186 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003187 if ((flags & PercentValue) != 0)
3188 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003189 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003190 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003191 break;
3192 }
anthonyafa3dfc2012-03-03 11:31:30 +00003193 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003194 {
anthony31f1bf72012-01-30 12:37:22 +00003195 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003196 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003197 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003198 break;
3199 }
anthonyafa3dfc2012-03-03 11:31:30 +00003200 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003201 {
anthony7bcfe7f2012-03-30 14:01:22 +00003202 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003203 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3204 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3205 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003206 break;
3207 }
anthonyafa3dfc2012-03-03 11:31:30 +00003208 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003209 {
anthonyfd706f92012-01-19 04:22:02 +00003210 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003211 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3212 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya322a832013-04-27 06:28:03 +00003213 new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
anthony92c93bd2012-03-19 14:02:47 +00003214 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003215 break;
3216 }
anthonyafa3dfc2012-03-03 11:31:30 +00003217 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003218 {
anthonyfd706f92012-01-19 04:22:02 +00003219 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003220 if ((flags & (RhoValue|SigmaValue)) == 0)
3221 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003222 if ((flags & SigmaValue) == 0)
3223 geometry_info.sigma=1.0;
3224 if ((flags & XiValue) == 0)
3225 geometry_info.xi=4.0;
3226 if ((flags & PsiValue) == 0)
3227 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003228 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3229 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3230 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003231 break;
3232 }
anthonyafa3dfc2012-03-03 11:31:30 +00003233 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003234 {
anthonyfd706f92012-01-19 04:22:02 +00003235 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003236 if ((flags & (RhoValue|SigmaValue)) == 0)
3237 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003238 if ((flags & SigmaValue) == 0)
3239 geometry_info.sigma=1.0;
3240 if ((flags & XiValue) == 0)
3241 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003242 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3243 _exception);
anthony805a2d42011-09-25 08:25:12 +00003244 break;
3245 }
anthonyafa3dfc2012-03-03 11:31:30 +00003246 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003247 {
anthony7bcfe7f2012-03-30 14:01:22 +00003248 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003249 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003250 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3251 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003252 break;
3253 }
anthonyafa3dfc2012-03-03 11:31:30 +00003254 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003255 {
anthonyfd706f92012-01-19 04:22:02 +00003256 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003257 if ((flags & RhoValue) == 0)
3258 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003259 if ((flags & SigmaValue) == 0)
3260 geometry_info.sigma=geometry_info.rho;
cristy4b892612012-08-03 19:31:31 +00003261 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3262 _exception);
anthony805a2d42011-09-25 08:25:12 +00003263 break;
3264 }
anthonyafa3dfc2012-03-03 11:31:30 +00003265 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003266 {
anthonyfd706f92012-01-19 04:22:02 +00003267 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003268 if ((flags & RhoValue) == 0)
3269 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003270 if ((flags & SigmaValue) == 0)
3271 geometry_info.sigma=(double) QuantumRange/2.0;
3272 if ((flags & PercentValue) != 0)
3273 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3274 100.0;
anthonya322a832013-04-27 06:28:03 +00003275 (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003276 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003277 break;
3278 }
anthonyafa3dfc2012-03-03 11:31:30 +00003279 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003280 {
anthonyfd706f92012-01-19 04:22:02 +00003281 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003282 if ((flags & (RhoValue|SigmaValue)) == 0)
3283 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003284 if ((flags & SigmaValue) == 0)
3285 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003286 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003287 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003288 break;
3289 }
anthonyafa3dfc2012-03-03 11:31:30 +00003290 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003291 {
anthony7bcfe7f2012-03-30 14:01:22 +00003292 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003293 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003294 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3295 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003296 break;
3297 }
anthonyafa3dfc2012-03-03 11:31:30 +00003298 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003299 {
anthonyf42014d2012-03-25 09:53:06 +00003300 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3301 if ( parse < 0 )
3302 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3303 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003304 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3305 _exception);
anthony805a2d42011-09-25 08:25:12 +00003306 break;
3307 }
anthonyafa3dfc2012-03-03 11:31:30 +00003308 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003309 {
anthony7bcfe7f2012-03-30 14:01:22 +00003310 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003311 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003312 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003313 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003314 break;
3315 }
anthonyafa3dfc2012-03-03 11:31:30 +00003316 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003317 {
anthonyb1e21ed2012-04-20 12:43:12 +00003318 flags=ParseGeometry(arg1,&geometry_info);
3319 if ((flags & RhoValue) == 0)
3320 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003321 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3322 _exception);
anthony805a2d42011-09-25 08:25:12 +00003323 break;
3324 }
anthonyafa3dfc2012-03-03 11:31:30 +00003325 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003326 {
anthony7bc87992012-03-25 02:32:51 +00003327 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3328 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003329 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003330 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003331 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003332 if ((flags & RhoValue) == 0)
3333 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003334 if ((flags & SigmaValue) == 0)
3335 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003336 new_image=StatisticImage(_image,(StatisticType)parse,
3337 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3338 _exception);
anthony805a2d42011-09-25 08:25:12 +00003339 break;
3340 }
anthonyafa3dfc2012-03-03 11:31:30 +00003341 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003342 {
anthony92c93bd2012-03-19 14:02:47 +00003343 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003344 break;
3345 }
anthonyafa3dfc2012-03-03 11:31:30 +00003346 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003347 {
cristy898c6042012-06-24 00:36:34 +00003348 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00003349 if ((flags & RhoValue) == 0)
cristy898c6042012-06-24 00:36:34 +00003350 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003351 new_image=SwirlImage(_image,geometry_info.rho,
3352 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003353 break;
3354 }
anthonyebb73a22012-03-22 14:25:52 +00003355 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003356 }
3357 case 't':
3358 {
anthonyafa3dfc2012-03-03 11:31:30 +00003359 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003360 {
3361 double
3362 threshold;
3363
anthony52bef752012-03-27 13:54:47 +00003364 threshold=(double) QuantumRange/2;
anthonya322a832013-04-27 06:28:03 +00003365 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00003366 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003367 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003368 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003369 }
anthony92c93bd2012-03-19 14:02:47 +00003370 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003371 break;
3372 }
anthonyafa3dfc2012-03-03 11:31:30 +00003373 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003374 {
anthony7bcfe7f2012-03-30 14:01:22 +00003375 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003376 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003377 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3378 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3379 _exception);
anthony805a2d42011-09-25 08:25:12 +00003380 break;
3381 }
anthonyafa3dfc2012-03-03 11:31:30 +00003382 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003383 {
anthony7bcfe7f2012-03-30 14:01:22 +00003384 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003385 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003386 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003387 break;
3388 }
anthonyafa3dfc2012-03-03 11:31:30 +00003389 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003390 {
anthony464f1c42012-04-22 08:51:01 +00003391 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003392 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003393 break;
3394 }
anthonyafa3dfc2012-03-03 11:31:30 +00003395 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003396 {
3397 PixelInfo
3398 target;
3399
anthony92c93bd2012-03-19 14:02:47 +00003400 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3401 (void) TransparentPaintImage(_image,&target,(Quantum)
anthonya322a832013-04-27 06:28:03 +00003402 TransparentAlpha,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003403 break;
3404 }
anthonyafa3dfc2012-03-03 11:31:30 +00003405 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003406 {
anthony92c93bd2012-03-19 14:02:47 +00003407 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003408 break;
3409 }
anthonyafa3dfc2012-03-03 11:31:30 +00003410 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003411 {
anthony92c93bd2012-03-19 14:02:47 +00003412 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003413 break;
3414 }
anthonyafa3dfc2012-03-03 11:31:30 +00003415 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003416 {
anthony92c93bd2012-03-19 14:02:47 +00003417 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003418 break;
3419 }
anthonyafa3dfc2012-03-03 11:31:30 +00003420 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003421 {
anthonyab3a50c2011-10-27 11:48:57 +00003422 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003423 (void) SetImageType(_image,_image_info->type,_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 case 'u':
3429 {
anthonyafa3dfc2012-03-03 11:31:30 +00003430 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003431 {
anthony52bef752012-03-27 13:54:47 +00003432 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3433 Option is not documented, bt appears to be for "identify".
3434 We may need a identify specific verbose!
3435 */
anthonya322a832013-04-27 06:28:03 +00003436 if (IsPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00003437 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003438 break;
3439 }
anthony92c93bd2012-03-19 14:02:47 +00003440 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3441 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003442 break;
3443 }
anthonyafa3dfc2012-03-03 11:31:30 +00003444 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003445 {
anthony92c93bd2012-03-19 14:02:47 +00003446 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003447 break;
3448 }
anthonyafa3dfc2012-03-03 11:31:30 +00003449 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003450 {
anthonyfd706f92012-01-19 04:22:02 +00003451 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003452 if ((flags & (RhoValue|SigmaValue)) == 0)
3453 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003454 if ((flags & SigmaValue) == 0)
3455 geometry_info.sigma=1.0;
3456 if ((flags & XiValue) == 0)
3457 geometry_info.xi=1.0;
3458 if ((flags & PsiValue) == 0)
3459 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003460 new_image=UnsharpMaskImage(_image,geometry_info.rho,
cristy3afd4012013-03-25 11:30:44 +00003461 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003462 break;
3463 }
anthonyebb73a22012-03-22 14:25:52 +00003464 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003465 }
3466 case 'v':
3467 {
anthonyafa3dfc2012-03-03 11:31:30 +00003468 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003469 {
anthonyafa3dfc2012-03-03 11:31:30 +00003470 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003471 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003472 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003473 */
anthony92c93bd2012-03-19 14:02:47 +00003474 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003475 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003476 break;
3477 }
anthonyafa3dfc2012-03-03 11:31:30 +00003478 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003479 {
anthonyfd706f92012-01-19 04:22:02 +00003480 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003481 if ((flags & (RhoValue|SigmaValue)) == 0)
3482 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003483 if ((flags & SigmaValue) == 0)
3484 geometry_info.sigma=1.0;
3485 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003486 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003487 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003488 geometry_info.psi=0.1*_image->rows;
cristy8e2392e2013-11-11 17:58:38 +00003489 if ((flags & PercentValue) != 0)
3490 {
cristy720d7562013-11-14 19:18:11 +00003491 geometry_info.xi*=(double) _image->columns/100.0;
3492 geometry_info.psi*=(double) _image->rows/100.0;
cristy8e2392e2013-11-11 17:58:38 +00003493 }
anthony92c93bd2012-03-19 14:02:47 +00003494 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003495 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3496 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003497 break;
3498 }
anthonyebb73a22012-03-22 14:25:52 +00003499 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003500 }
3501 case 'w':
3502 {
anthonyafa3dfc2012-03-03 11:31:30 +00003503 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003504 {
anthonyfd706f92012-01-19 04:22:02 +00003505 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003506 if ((flags & (RhoValue|SigmaValue)) == 0)
3507 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003508 if ((flags & SigmaValue) == 0)
3509 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003510 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3511 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003512 break;
3513 }
anthonyafa3dfc2012-03-03 11:31:30 +00003514 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003515 {
anthony7bcfe7f2012-03-30 14:01:22 +00003516 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003517 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003518 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003519 break;
3520 }
anthonyebb73a22012-03-22 14:25:52 +00003521 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003522 }
3523 default:
anthonyebb73a22012-03-22 14:25:52 +00003524 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003525 }
anthony964d28e2012-05-17 23:39:46 +00003526 /* clean up percent escape interpreted strings */
3527 if (arg1 != arg1n )
3528 arg1=DestroyString((char *)arg1);
3529 if (arg2 != arg2n )
3530 arg2=DestroyString((char *)arg2);
3531
3532 /* Replace current image with any image that was generated
3533 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003534 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003535 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003536
cristyfe831852013-02-12 14:56:07 +00003537 return(MagickTrue);
anthony92c93bd2012-03-19 14:02:47 +00003538#undef _image_info
3539#undef _draw_info
3540#undef _quantize_info
3541#undef _image
3542#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003543#undef IfNormalOp
3544#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00003545#undef IsNormalOp
3546#undef IsPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003547}
anthonyfd706f92012-01-19 04:22:02 +00003548
cristyfe831852013-02-12 14:56:07 +00003549WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
cristy2c57b742014-10-31 00:40:34 +00003550 const char *option,const char *arg1,const char *arg2,ExceptionInfo *exception)
anthony31f1bf72012-01-30 12:37:22 +00003551{
anthonyc7994672012-11-17 05:33:27 +00003552#if !USE_WAND_METHODS
anthony31f1bf72012-01-30 12:37:22 +00003553 size_t
anthony43f425d2012-02-26 12:58:58 +00003554 n,
anthony31f1bf72012-01-30 12:37:22 +00003555 i;
anthonyc7994672012-11-17 05:33:27 +00003556#endif
anthony31f1bf72012-01-30 12:37:22 +00003557
anthony43f425d2012-02-26 12:58:58 +00003558 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003559 assert(cli_wand->signature == MagickWandSignature);
3560 assert(cli_wand->wand.signature == MagickWandSignature);
anthony43f425d2012-02-26 12:58:58 +00003561 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthonya322a832013-04-27 06:28:03 +00003562
anthony7bcfe7f2012-03-30 14:01:22 +00003563 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00003564 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3565 "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
anthony31f1bf72012-01-30 12:37:22 +00003566
anthonyafa3dfc2012-03-03 11:31:30 +00003567#if !USE_WAND_METHODS
3568 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003569 i=0;
anthony43f425d2012-02-26 12:58:58 +00003570 n=GetImageListLength(cli_wand->wand.images);
3571 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003572 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003573 i++;
cristy2c57b742014-10-31 00:40:34 +00003574 CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
anthony43f425d2012-02-26 12:58:58 +00003575 if ( cli_wand->wand.images->next == (Image *) NULL )
3576 break;
3577 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003578 }
anthony43f425d2012-02-26 12:58:58 +00003579 assert( i == n );
3580 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003581#else
3582 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003583 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
cristy52b632a2014-11-08 00:31:34 +00003584 (void) CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003585 MagickResetIterator(&cli_wand->wand);
3586#endif
cristyfe831852013-02-12 14:56:07 +00003587 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003588}
3589
3590/*
3591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3592% %
3593% %
3594% %
anthony43f425d2012-02-26 12:58:58 +00003595+ 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 +00003596% %
3597% %
3598% %
3599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3600%
anthony43f425d2012-02-26 12:58:58 +00003601% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003602% entire image list as a whole. The result is often a complete replacment
anthonyc7994672012-11-17 05:33:27 +00003603% of the image list with a completely new list, or with just a single image
3604% result.
anthony805a2d42011-09-25 08:25:12 +00003605%
3606% The format of the MogrifyImage method is:
3607%
cristyfe831852013-02-12 14:56:07 +00003608% MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3609% const char *option,const char *arg1,const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003610%
3611% A description of each parameter follows:
3612%
anthony43f425d2012-02-26 12:58:58 +00003613% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003614%
anthony36a8c2c2012-02-10 00:08:44 +00003615% o option: The option string for the operation
3616%
anthony31f1bf72012-01-30 12:37:22 +00003617% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003618% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003619%
anthony805a2d42011-09-25 08:25:12 +00003620*/
cristyfe831852013-02-12 14:56:07 +00003621WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3622 const char *option,const char *arg1n,const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003623{
anthonya322a832013-04-27 06:28:03 +00003624 const char /* percent escaped versions of the args */
cristya30f8e62013-02-19 15:03:45 +00003625 *arg1,
3626 *arg2;
anthony2a0ec8c2012-03-24 04:35:56 +00003627
anthony31f1bf72012-01-30 12:37:22 +00003628 Image
3629 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003630
cristya30f8e62013-02-19 15:03:45 +00003631 MagickStatusType
3632 status;
3633
3634 ssize_t
3635 parse;
anthony964d28e2012-05-17 23:39:46 +00003636
anthony2e4501b2012-03-30 04:41:54 +00003637#define _image_info (cli_wand->wand.image_info)
3638#define _images (cli_wand->wand.images)
3639#define _exception (cli_wand->wand.exception)
3640#define _draw_info (cli_wand->draw_info)
3641#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003642#define _process_flags (cli_wand->process_flags)
3643#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003644#define IfNormalOp (*option=='-')
3645#define IfPlusOp (*option!='-')
anthonya322a832013-04-27 06:28:03 +00003646#define IsNormalOp IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003647
anthony43f425d2012-02-26 12:58:58 +00003648 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003649 assert(cli_wand->signature == MagickWandSignature);
3650 assert(cli_wand->wand.signature == MagickWandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003651 assert(_images != (Image *) NULL); /* _images must be present */
anthony31f1bf72012-01-30 12:37:22 +00003652
anthonya322a832013-04-27 06:28:03 +00003653 if (IfMagickTrue(cli_wand->wand.debug))
3654 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3655 "- List Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
3656
anthony964d28e2012-05-17 23:39:46 +00003657 arg1 = arg1n;
3658 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00003659
3660 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00003661 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3662 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3663 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3664 /* Interpret Percent escapes in argument 1 */
3665 if (arg1n != (char *) NULL) {
3666 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3667 if (arg1 == (char *) NULL) {
3668 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3669 arg1=arg1n; /* use the given argument as is */
3670 }
3671 }
3672 if (arg2n != (char *) NULL) {
3673 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3674 if (arg2 == (char *) NULL) {
3675 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3676 arg2=arg2n; /* use the given argument as is */
3677 }
3678 }
3679 }
anthony4837ac22012-05-18 23:39:48 +00003680#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003681#undef _option_type
3682
cristyfe831852013-02-12 14:56:07 +00003683 status=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00003684 new_images=NewImageList();
3685
anthonyafa3dfc2012-03-03 11:31:30 +00003686 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003687 {
3688 case 'a':
3689 {
anthonyafa3dfc2012-03-03 11:31:30 +00003690 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003691 {
anthonya322a832013-04-27 06:28:03 +00003692 new_images=AppendImages(_images,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003693 break;
3694 }
cristy52ad9e92013-02-08 23:23:29 +00003695 if (LocaleCompare("average",option+1) == 0)
3696 {
3697 CLIWandWarnReplaced("-evaluate-sequence Mean");
cristy52b632a2014-11-08 00:31:34 +00003698 (void) CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
cristy52ad9e92013-02-08 23:23:29 +00003699 break;
3700 }
anthonyebb73a22012-03-22 14:25:52 +00003701 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003702 }
3703 case 'c':
3704 {
cristy5f257b22012-03-07 00:27:29 +00003705 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003706 {
anthony92c93bd2012-03-19 14:02:47 +00003707 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003708 break;
3709 }
anthonyafa3dfc2012-03-03 11:31:30 +00003710 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003711 {
anthony805a2d42011-09-25 08:25:12 +00003712 Image
anthony31f1bf72012-01-30 12:37:22 +00003713 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003714
anthonyafa3dfc2012-03-03 11:31:30 +00003715 /* FUTURE - make this a compose option, and thus can be used
3716 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003717 _images.
cristy87c02f42012-02-24 00:19:10 +00003718 */
anthony92c93bd2012-03-19 14:02:47 +00003719 new_images=RemoveFirstImageFromList(&_images);
3720 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003721 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003722 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003723 break;
cristyf68c0be2015-04-28 22:48:37 +00003724 (void) ClutImage(new_images,clut_image,new_images->interpolate,
3725 _exception);
anthony805a2d42011-09-25 08:25:12 +00003726 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003727 break;
3728 }
anthonyafa3dfc2012-03-03 11:31:30 +00003729 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003730 {
anthony92c93bd2012-03-19 14:02:47 +00003731 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003732 break;
3733 }
anthonyafa3dfc2012-03-03 11:31:30 +00003734 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003735 {
cristy9a0e8ef2015-05-11 23:20:15 +00003736 parse=(ssize_t) _images->colorspace;
anthony5a4ff372013-05-01 04:48:57 +00003737 if ( IfPlusOp )
cristyf68c0be2015-04-28 22:48:37 +00003738 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
cristy8448a0d2013-02-15 18:20:53 +00003739 if (parse < 0)
3740 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3741 arg1);
cristy46f354c2012-07-04 13:31:29 +00003742 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003743 break;
3744 }
cristye863c052013-09-04 11:31:30 +00003745 if (LocaleCompare("compare",option+1) == 0)
3746 {
3747 double
3748 distortion;
3749
3750 Image
3751 *image,
3752 *reconstruct_image;
3753
3754 MetricType
3755 metric;
3756
3757 /*
3758 Mathematically and visually annotate the difference between an
3759 image and its reconstruction.
3760 */
3761 image=RemoveFirstImageFromList(&_images);
3762 reconstruct_image=RemoveFirstImageFromList(&_images);
3763 /* FUTURE - produce Exception, rather than silent fail */
3764 if (reconstruct_image == (Image *) NULL)
3765 break;
3766 metric=UndefinedErrorMetric;
3767 option=GetImageOption(_image_info,"metric");
3768 if (option != (const char *) NULL)
3769 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
3770 MagickFalse,option);
3771 new_images=CompareImages(image,reconstruct_image,metric,&distortion,
3772 _exception);
3773 (void) distortion;
3774 reconstruct_image=DestroyImage(reconstruct_image);
3775 image=DestroyImage(image);
3776 break;
3777 }
cristy790190d2013-10-04 00:51:51 +00003778 if (LocaleCompare("complex",option+1) == 0)
3779 {
3780 parse=ParseCommandOption(MagickComplexOptions,MagickFalse,arg1);
3781 if (parse < 0)
3782 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3783 option,arg1);
cristyb8f66bb2013-10-04 15:21:58 +00003784 new_images=ComplexImages(_images,(ComplexOperator) parse,_exception);
cristy790190d2013-10-04 00:51:51 +00003785 break;
3786 }
anthonyafa3dfc2012-03-03 11:31:30 +00003787 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003788 {
cristyfeb3e962012-03-29 17:25:55 +00003789 CompositeOperator
3790 compose;
3791
3792 const char*
3793 value;
3794
3795 MagickBooleanType
3796 clip_to_self;
3797
anthony805a2d42011-09-25 08:25:12 +00003798 Image
3799 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003800 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003801
3802 RectangleInfo
3803 geometry;
3804
anthony7bcfe7f2012-03-30 14:01:22 +00003805 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003806 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003807 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003808 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003809 else
3810 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3811 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003812
anthony7bcfe7f2012-03-30 14:01:22 +00003813 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003814 value=GetImageOption(_image_info,"compose:clip-to-self");
3815 if (value == (const char *) NULL)
3816 clip_to_self=MagickTrue;
3817 else
3818 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3819 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003820 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003821 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003822 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003823 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003824 }
3825
anthony92c93bd2012-03-19 14:02:47 +00003826 new_images=RemoveFirstImageFromList(&_images);
3827 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003828 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003829 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003830
anthony31f1bf72012-01-30 12:37:22 +00003831 /* FUTURE - this should not be here! - should be part of -geometry */
3832 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003833 source_image->geometry,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003834 SetGeometry(source_image,&geometry);
3835 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3836 GravityAdjustGeometry(new_images->columns,new_images->rows,
cristyfe831852013-02-12 14:56:07 +00003837 new_images->gravity, &geometry);
anthony92c93bd2012-03-19 14:02:47 +00003838 mask_image=RemoveFirstImageFromList(&_images);
cristy052d1f72015-01-04 21:10:37 +00003839 if (mask_image == (Image *) NULL)
3840 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
3841 geometry.x,geometry.y,_exception);
3842 else
cristyfe831852013-02-12 14:56:07 +00003843 {
cristy052d1f72015-01-04 21:10:37 +00003844 if ((compose == DisplaceCompositeOp) ||
3845 (compose == DistortCompositeOp))
3846 {
3847 status&=CompositeImage(source_image,mask_image,
3848 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3849 status&=CompositeImage(new_images,source_image,compose,
3850 clip_to_self,geometry.x,geometry.y,_exception);
3851 }
cristyfae52a22014-11-27 21:49:03 +00003852 else
cristy052d1f72015-01-04 21:10:37 +00003853 {
3854 Image
3855 *clone_image;
3856
3857 clone_image=CloneImage(new_images,0,0,MagickTrue,_exception);
3858 if (clone_image == (Image *) NULL)
3859 break;
3860 status&=CompositeImage(new_images,source_image,compose,
3861 clip_to_self,geometry.x,geometry.y,_exception);
3862 status&=CompositeImage(new_images,mask_image,
3863 CopyAlphaCompositeOp,MagickTrue,0,0,_exception);
3864 status&=CompositeImage(clone_image,new_images,OverCompositeOp,
3865 clip_to_self,geometry.x,geometry.y,_exception);
3866 new_images=DestroyImage(new_images);
3867 new_images=clone_image;
3868 }
cristyfe831852013-02-12 14:56:07 +00003869 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003870 }
anthony31f1bf72012-01-30 12:37:22 +00003871 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003872 break;
3873 }
cristy8c4c1c42015-06-22 23:51:22 +00003874 if (LocaleCompare("copy",option+1) == 0)
3875 {
3876 Image
3877 *source_image;
3878
3879 OffsetInfo
3880 offset;
3881
3882 RectangleInfo
3883 geometry;
3884
3885 /*
3886 Copy image pixels.
3887 */
3888 if (IfMagickFalse(IsGeometry(arg1)))
3889 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3890 if (IfMagickFalse(IsGeometry(arg2)))
3891 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3892 (void) ParsePageGeometry(_images,arg2,&geometry,_exception);
3893 offset.x=geometry.x;
3894 offset.y=geometry.y;
cristy8c4c1c42015-06-22 23:51:22 +00003895 source_image=_images;
3896 if (source_image->next != (Image *) NULL)
3897 source_image=source_image->next;
cristy923019b2015-06-23 01:13:00 +00003898 (void) ParsePageGeometry(source_image,arg1,&geometry,_exception);
cristy8c4c1c42015-06-22 23:51:22 +00003899 (void) CopyImagePixels(_images,source_image,&geometry,&offset,
3900 _exception);
3901 break;
3902 }
anthonyebb73a22012-03-22 14:25:52 +00003903 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003904 }
3905 case 'd':
3906 {
anthonyafa3dfc2012-03-03 11:31:30 +00003907 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003908 {
anthony464f1c42012-04-22 08:51:01 +00003909 CLIWandWarnReplaced("-layer CompareAny");
cristy52b632a2014-11-08 00:31:34 +00003910 (void) CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003911 break;
3912 }
anthonyafa3dfc2012-03-03 11:31:30 +00003913 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003914 {
anthonyafa3dfc2012-03-03 11:31:30 +00003915 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003916 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003917 else
anthony92c93bd2012-03-19 14:02:47 +00003918 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003919 break;
3920 }
anthonyafa3dfc2012-03-03 11:31:30 +00003921 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003922 {
anthonyafa3dfc2012-03-03 11:31:30 +00003923 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003924 {
3925 const char
3926 *p;
3927
3928 size_t
3929 number_duplicates;
3930
anthony7bcfe7f2012-03-30 14:01:22 +00003931 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003932 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3933 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003934 number_duplicates=(size_t) StringToLong(arg1);
3935 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003936 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003937 new_images=DuplicateImages(_images,number_duplicates,"-1",
3938 _exception);
anthony805a2d42011-09-25 08:25:12 +00003939 else
anthony92c93bd2012-03-19 14:02:47 +00003940 new_images=DuplicateImages(_images,number_duplicates,p,
3941 _exception);
anthony805a2d42011-09-25 08:25:12 +00003942 }
anthonyafa3dfc2012-03-03 11:31:30 +00003943 else
anthony92c93bd2012-03-19 14:02:47 +00003944 new_images=DuplicateImages(_images,1,"-1",_exception);
3945 AppendImageToList(&_images, new_images);
cristyf432c632014-12-07 15:11:28 +00003946 new_images=(Image *) NULL;
anthony805a2d42011-09-25 08:25:12 +00003947 break;
3948 }
anthonyebb73a22012-03-22 14:25:52 +00003949 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003950 }
3951 case 'e':
3952 {
anthonyafa3dfc2012-03-03 11:31:30 +00003953 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003954 {
cristy790190d2013-10-04 00:51:51 +00003955 parse=ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3956 if (parse < 0)
anthony2a0ec8c2012-03-24 04:35:56 +00003957 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
cristy790190d2013-10-04 00:51:51 +00003958 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00003959 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
cristy790190d2013-10-04 00:51:51 +00003960 _exception);
anthony805a2d42011-09-25 08:25:12 +00003961 break;
3962 }
anthonyebb73a22012-03-22 14:25:52 +00003963 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003964 }
3965 case 'f':
3966 {
anthonyafa3dfc2012-03-03 11:31:30 +00003967 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003968 {
cristyf68c0be2015-04-28 22:48:37 +00003969 new_images=ForwardFourierTransformImage(_images,IsNormalOp,
3970 _exception);
anthony805a2d42011-09-25 08:25:12 +00003971 break;
3972 }
anthonyafa3dfc2012-03-03 11:31:30 +00003973 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003974 {
anthony319dac62012-03-06 04:12:44 +00003975 /* REDIRECTED to use -layers flatten instead */
cristy52b632a2014-11-08 00:31:34 +00003976 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003977 break;
3978 }
anthonyafa3dfc2012-03-03 11:31:30 +00003979 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003980 {
anthony92c93bd2012-03-19 14:02:47 +00003981 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003982 break;
3983 }
anthonyebb73a22012-03-22 14:25:52 +00003984 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003985 }
3986 case 'h':
3987 {
anthonyafa3dfc2012-03-03 11:31:30 +00003988 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003989 {
anthony31f1bf72012-01-30 12:37:22 +00003990 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003991 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003992 */
anthony805a2d42011-09-25 08:25:12 +00003993 Image
anthony31f1bf72012-01-30 12:37:22 +00003994 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003995
anthony92c93bd2012-03-19 14:02:47 +00003996 new_images=RemoveFirstImageFromList(&_images);
3997 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003998 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003999 break;
anthony92c93bd2012-03-19 14:02:47 +00004000 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00004001 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00004002 break;
4003 }
anthonyebb73a22012-03-22 14:25:52 +00004004 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004005 }
4006 case 'i':
4007 {
anthonyafa3dfc2012-03-03 11:31:30 +00004008 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004009 {
4010 Image
anthony805a2d42011-09-25 08:25:12 +00004011 *magnitude_image,
4012 *phase_image;
4013
anthony92c93bd2012-03-19 14:02:47 +00004014 magnitude_image=RemoveFirstImageFromList(&_images);
4015 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00004016 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00004017 if (phase_image == (Image *) NULL)
4018 break;
4019 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
cristyf68c0be2015-04-28 22:48:37 +00004020 IsNormalOp,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004021 magnitude_image=DestroyImage(magnitude_image);
4022 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00004023 break;
4024 }
anthonyafa3dfc2012-03-03 11:31:30 +00004025 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004026 {
4027 Image
anthony31f1bf72012-01-30 12:37:22 +00004028 *insert_image,
4029 *index_image;
4030
4031 ssize_t
4032 index;
anthony805a2d42011-09-25 08:25:12 +00004033
anthony7bcfe7f2012-03-30 14:01:22 +00004034 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00004035 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004036 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004037 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004038 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004039 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004040 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004041 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004042 PrependImageToList(&_images,insert_image);
4043 else if (index == (ssize_t) GetImageListLength(_images))
4044 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004045 else
anthony43f425d2012-02-26 12:58:58 +00004046 {
anthony92c93bd2012-03-19 14:02:47 +00004047 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004048 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004049 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004050 InsertImageInList(&index_image,insert_image);
4051 }
anthony92c93bd2012-03-19 14:02:47 +00004052 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004053 break;
4054 }
anthonyebb73a22012-03-22 14:25:52 +00004055 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004056 }
4057 case 'l':
4058 {
anthonyafa3dfc2012-03-03 11:31:30 +00004059 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004060 {
anthonyfe1aa782012-03-24 13:43:04 +00004061 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4062 if ( parse < 0 )
4063 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4064 option,arg1);
cristya0417062012-09-02 23:34:56 +00004065 switch ((LayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004066 {
4067 case CoalesceLayer:
4068 {
anthony92c93bd2012-03-19 14:02:47 +00004069 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004070 break;
4071 }
4072 case CompareAnyLayer:
4073 case CompareClearLayer:
4074 case CompareOverlayLayer:
4075 default:
4076 {
cristya0417062012-09-02 23:34:56 +00004077 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00004078 _exception);
anthony805a2d42011-09-25 08:25:12 +00004079 break;
4080 }
4081 case MergeLayer:
4082 case FlattenLayer:
4083 case MosaicLayer:
4084 case TrimBoundsLayer:
4085 {
cristya0417062012-09-02 23:34:56 +00004086 new_images=MergeImageLayers(_images,(LayerMethod) parse,
cristyf68c0be2015-04-28 22:48:37 +00004087 _exception);
anthony805a2d42011-09-25 08:25:12 +00004088 break;
4089 }
4090 case DisposeLayer:
4091 {
anthony92c93bd2012-03-19 14:02:47 +00004092 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004093 break;
4094 }
4095 case OptimizeImageLayer:
4096 {
anthony92c93bd2012-03-19 14:02:47 +00004097 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004098 break;
4099 }
4100 case OptimizePlusLayer:
4101 {
anthony92c93bd2012-03-19 14:02:47 +00004102 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004103 break;
4104 }
4105 case OptimizeTransLayer:
4106 {
anthony92c93bd2012-03-19 14:02:47 +00004107 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004108 break;
4109 }
4110 case RemoveDupsLayer:
4111 {
anthony92c93bd2012-03-19 14:02:47 +00004112 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004113 break;
4114 }
4115 case RemoveZeroLayer:
4116 {
anthony92c93bd2012-03-19 14:02:47 +00004117 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004118 break;
4119 }
4120 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004121 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004122 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004123 if (new_images == (Image *) NULL)
4124 break;
anthony92c93bd2012-03-19 14:02:47 +00004125 _images=DestroyImageList(_images);
4126 _images=OptimizeImageLayers(new_images,_exception);
4127 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004128 break;
4129 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004130 OptimizeImageTransparency(_images,_exception);
4131 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4132 _exception);
anthony805a2d42011-09-25 08:25:12 +00004133 break;
4134 }
4135 case CompositeLayer:
4136 {
anthony805a2d42011-09-25 08:25:12 +00004137 Image
4138 *source;
4139
4140 RectangleInfo
4141 geometry;
4142
anthony31f1bf72012-01-30 12:37:22 +00004143 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004144 compose;
4145
4146 const char*
4147 value;
4148
anthony92c93bd2012-03-19 14:02:47 +00004149 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004150 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004151 if (value != (const char *) NULL)
4152 compose=(CompositeOperator) ParseCommandOption(
4153 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004154
anthony31f1bf72012-01-30 12:37:22 +00004155 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004156 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004157 while (source != (Image *) NULL)
4158 {
4159 source=GetNextImageInList(source);
4160 if ((source != (Image *) NULL) &&
4161 (LocaleCompare(source->magick,"NULL") == 0))
4162 break;
4163 }
4164 if (source != (Image *) NULL)
4165 {
4166 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4167 (GetNextImageInList(source) == (Image *) NULL))
4168 source=(Image *) NULL;
4169 else
anthony31f1bf72012-01-30 12:37:22 +00004170 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004171 source=SplitImageList(source->previous);
4172 DeleteImageFromList(&source);
4173 }
4174 }
4175 if (source == (Image *) NULL)
4176 {
anthony92c93bd2012-03-19 14:02:47 +00004177 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004178 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004179 break;
4180 }
anthony31f1bf72012-01-30 12:37:22 +00004181 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004182 SetGeometry(_images,&geometry);
4183 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004184 geometry.width=source->page.width != 0 ?
4185 source->page.width : source->columns;
4186 geometry.height=source->page.height != 0 ?
4187 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004188 GravityAdjustGeometry(_images->page.width != 0 ?
4189 _images->page.width : _images->columns,
4190 _images->page.height != 0 ? _images->page.height :
4191 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004192
anthony31f1bf72012-01-30 12:37:22 +00004193 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004194 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4195 _exception);
anthony805a2d42011-09-25 08:25:12 +00004196 source=DestroyImageList(source);
4197 break;
4198 }
4199 }
anthony805a2d42011-09-25 08:25:12 +00004200 break;
4201 }
anthonyebb73a22012-03-22 14:25:52 +00004202 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004203 }
4204 case 'm':
4205 {
anthonyafa3dfc2012-03-03 11:31:30 +00004206 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004207 {
anthony464f1c42012-04-22 08:51:01 +00004208 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004209 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004210 break;
4211 }
cristye863c052013-09-04 11:31:30 +00004212 if (LocaleCompare("metric",option+1) == 0)
4213 break;
anthonyafa3dfc2012-03-03 11:31:30 +00004214 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004215 {
4216 Image
4217 *morph_image;
4218
anthony7bcfe7f2012-03-30 14:01:22 +00004219 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004220 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004221 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4222 _exception);
anthony805a2d42011-09-25 08:25:12 +00004223 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004224 break;
anthony92c93bd2012-03-19 14:02:47 +00004225 _images=DestroyImageList(_images);
4226 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004227 break;
4228 }
anthonyafa3dfc2012-03-03 11:31:30 +00004229 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004230 {
anthony319dac62012-03-06 04:12:44 +00004231 /* REDIRECTED to use -layers mosaic instead */
cristy52b632a2014-11-08 00:31:34 +00004232 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004233 break;
4234 }
anthonyebb73a22012-03-22 14:25:52 +00004235 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004236 }
4237 case 'p':
4238 {
cristy02016cf2012-11-13 01:14:41 +00004239 if (LocaleCompare("poly",option+1) == 0)
4240 {
4241 double
4242 *args;
4243
4244 ssize_t
4245 count;
4246
4247 /* convert argument string into an array of doubles */
cristyace09c62015-01-21 12:54:30 +00004248 args = StringToArrayOfDoubles(arg1,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00004249 if (args == (double *) NULL )
cristyace09c62015-01-21 12:54:30 +00004250 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg1);
cristyf68c0be2015-04-28 22:48:37 +00004251 new_images=PolynomialImage(_images,(size_t) (count >> 1),args,
4252 _exception);
cristy02016cf2012-11-13 01:14:41 +00004253 args=(double *) RelinquishMagickMemory(args);
4254 break;
4255 }
anthonyafa3dfc2012-03-03 11:31:30 +00004256 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004257 {
anthonyb1d483a2012-04-14 12:53:56 +00004258 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004259 char
4260 **arguments;
4261
4262 int
4263 j,
4264 number_arguments;
4265
anthony31f1bf72012-01-30 12:37:22 +00004266 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004267 if (arguments == (char **) NULL)
4268 break;
anthony31f1bf72012-01-30 12:37:22 +00004269 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004270 {
4271 char
4272 breaker,
4273 quote,
4274 *token;
4275
4276 const char
4277 *arguments;
4278
4279 int
4280 next,
4281 status;
4282
4283 size_t
4284 length;
4285
4286 TokenInfo
4287 *token_info;
4288
4289 /*
anthony24aa8822012-03-11 00:56:06 +00004290 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004291 */
cristy4bc3dac2014-01-18 15:17:26 +00004292 assert(arg1 != (const char *) NULL);
anthony31f1bf72012-01-30 12:37:22 +00004293 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004294 token=(char *) NULL;
cristy151b66d2015-04-15 10:50:31 +00004295 if (~length >= (MagickPathExtent-1))
4296 token=(char *) AcquireQuantumMemory(length+MagickPathExtent,
anthony805a2d42011-09-25 08:25:12 +00004297 sizeof(*token));
4298 if (token == (char *) NULL)
4299 break;
4300 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004301 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004302 token_info=AcquireTokenInfo();
4303 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4304 "\"",'\0',&breaker,&next,&quote);
4305 token_info=DestroyTokenInfo(token_info);
4306 if (status == 0)
4307 {
4308 const char
4309 *argv;
4310
4311 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004312 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4313 _exception);
anthony805a2d42011-09-25 08:25:12 +00004314 }
4315 token=DestroyString(token);
4316 break;
4317 }
4318 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004319 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4320 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004321 for (j=0; j < number_arguments; j++)
4322 arguments[j]=DestroyString(arguments[j]);
4323 arguments=(char **) RelinquishMagickMemory(arguments);
4324 break;
4325 }
anthonyebb73a22012-03-22 14:25:52 +00004326 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004327 }
4328 case 'r':
4329 {
anthonyafa3dfc2012-03-03 11:31:30 +00004330 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004331 {
anthony92c93bd2012-03-19 14:02:47 +00004332 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004333 break;
4334 }
anthonyafa3dfc2012-03-03 11:31:30 +00004335 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004336 {
anthony92c93bd2012-03-19 14:02:47 +00004337 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004338 break;
4339 }
anthonyebb73a22012-03-22 14:25:52 +00004340 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004341 }
4342 case 's':
4343 {
anthonyafa3dfc2012-03-03 11:31:30 +00004344 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004345 {
anthonycd358fc2012-04-16 13:59:03 +00004346 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004347 ssize_t
4348 offset;
4349
anthony7bcfe7f2012-03-30 14:01:22 +00004350 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004351 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004352 offset=(ssize_t) StringToLong(arg1);
anthonya322a832013-04-27 06:28:03 +00004353 new_images=SmushImages(_images,IsNormalOp,offset,_exception);
anthonycd358fc2012-04-16 13:59:03 +00004354 break;
4355 }
4356 if (LocaleCompare("subimage",option+1) == 0)
4357 {
4358 Image
4359 *base_image,
4360 *compare_image;
4361
cristyf68c0be2015-04-28 22:48:37 +00004362 const char
4363 *value;
anthonycd358fc2012-04-16 13:59:03 +00004364
4365 MetricType
4366 metric;
4367
4368 double
4369 similarity;
4370
4371 RectangleInfo
4372 offset;
4373
4374 base_image=GetImageFromList(_images,0);
4375 compare_image=GetImageFromList(_images,1);
4376
4377 /* Comparision Metric */
cristy08163292013-07-11 00:00:37 +00004378 metric=UndefinedErrorMetric;
anthonycd358fc2012-04-16 13:59:03 +00004379 value=GetImageOption(_image_info,"metric");
4380 if (value != (const char *) NULL)
4381 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4382 MagickFalse,value);
4383
cristy99fcec42013-03-15 21:37:59 +00004384 new_images=SimilarityImage(base_image,compare_image,metric,0.0,
cristyf68c0be2015-04-28 22:48:37 +00004385 &offset,&similarity,_exception);
anthonycd358fc2012-04-16 13:59:03 +00004386
cristye0246372015-06-28 12:38:15 +00004387 if (new_images != (Image *) NULL)
4388 {
4389 char
4390 result[MagickPathExtent];
anthonycd358fc2012-04-16 13:59:03 +00004391
cristye0246372015-06-28 12:38:15 +00004392 (void) FormatLocaleString(result,MagickPathExtent,"%lf",
4393 similarity);
4394 (void) SetImageProperty(new_images,"subimage:similarity",result,
4395 _exception);
4396 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4397 offset.x);
4398 (void) SetImageProperty(new_images,"subimage:x",result,
4399 _exception);
4400 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4401 offset.y);
4402 (void) SetImageProperty(new_images,"subimage:y",result,
4403 _exception);
4404 (void) FormatLocaleString(result,MagickPathExtent,
4405 "%lux%lu%+ld%+ld",(unsigned long) offset.width,(unsigned long)
4406 offset.height,(long) offset.x,(long) offset.y);
4407 (void) SetImageProperty(new_images,"subimage:offset",result,
4408 _exception);
4409 }
anthony805a2d42011-09-25 08:25:12 +00004410 break;
4411 }
cristyf68c0be2015-04-28 22:48:37 +00004412 if (LocaleCompare("swap",option+1) == 0)
4413 {
anthony0ea037a2012-04-03 12:14:39 +00004414 Image
4415 *p,
4416 *q,
4417 *swap;
anthony805a2d42011-09-25 08:25:12 +00004418
anthony0ea037a2012-04-03 12:14:39 +00004419 ssize_t
4420 index,
4421 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004422
cristy6b36c942013-02-17 00:36:24 +00004423 index=(-1);
4424 swap_index=(-2);
anthony0ea037a2012-04-03 12:14:39 +00004425 if (IfNormalOp) {
4426 GeometryInfo
4427 geometry_info;
4428
4429 MagickStatusType
4430 flags;
4431
4432 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004433 flags=ParseGeometry(arg1,&geometry_info);
cristy90fbd1c2013-02-17 00:35:35 +00004434 if ((flags & RhoValue) == 0)
anthonyb1e21ed2012-04-20 12:43:12 +00004435 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004436 index=(ssize_t) geometry_info.rho;
4437 if ((flags & SigmaValue) != 0)
4438 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004439 }
anthony0ea037a2012-04-03 12:14:39 +00004440 p=GetImageFromList(_images,index);
4441 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004442 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4443 if (IfNormalOp)
4444 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4445 else
4446 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4447 }
anthony0ea037a2012-04-03 12:14:39 +00004448 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004449 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004450 swap=CloneImage(p,0,0,MagickTrue,_exception);
4451 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4452 ReplaceImageInList(&q,swap);
4453 _images=GetFirstImageInList(q);
4454 break;
4455 }
anthonyebb73a22012-03-22 14:25:52 +00004456 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004457 }
anthony805a2d42011-09-25 08:25:12 +00004458 default:
anthonyebb73a22012-03-22 14:25:52 +00004459 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004460 }
anthony964d28e2012-05-17 23:39:46 +00004461
4462 /* clean up percent escape interpreted strings */
4463 if (arg1 != arg1n )
4464 arg1=DestroyString((char *)arg1);
4465 if (arg2 != arg2n )
4466 arg2=DestroyString((char *)arg2);
4467
4468 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004469 if (new_images == (Image *) NULL)
cristy6398ec72013-11-28 02:00:27 +00004470 return(status == 0 ? MagickFalse : MagickTrue);
anthony964d28e2012-05-17 23:39:46 +00004471 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004472 _images=GetFirstImageInList(new_images);
cristy6398ec72013-11-28 02:00:27 +00004473 return(status == 0 ? MagickFalse : MagickTrue);
anthony31f1bf72012-01-30 12:37:22 +00004474
anthony92c93bd2012-03-19 14:02:47 +00004475#undef _image_info
4476#undef _images
4477#undef _exception
4478#undef _draw_info
4479#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004480#undef IfNormalOp
4481#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00004482#undef IsNormalOp
anthony805a2d42011-09-25 08:25:12 +00004483}
anthony43f425d2012-02-26 12:58:58 +00004484
4485/*
4486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4487% %
4488% %
4489% %
anthony964d28e2012-05-17 23:39:46 +00004490+ 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 +00004491% %
4492% %
4493% %
4494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4495%
anthony464f1c42012-04-22 08:51:01 +00004496% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004497% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004498%
anthony4837ac22012-05-18 23:39:48 +00004499% The classic operators of this type is "-read", which actually creates
4500% images even when no images are present. Or image stack operators, which
4501% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004502%
anthony4837ac22012-05-18 23:39:48 +00004503% Note that these operators may involve other special 'option' prefix
4504% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004505%
anthony464f1c42012-04-22 08:51:01 +00004506% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004507%
anthony464f1c42012-04-22 08:51:01 +00004508% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4509% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004510%
4511% A description of each parameter follows:
4512%
anthonyc7994672012-11-17 05:33:27 +00004513% o cli_wand: the main CLI Wand to use. (sometimes not required)
anthony43f425d2012-02-26 12:58:58 +00004514%
4515% o option: The special option (with any switch char) to process
4516%
anthony464f1c42012-04-22 08:51:01 +00004517% o arg1 & arg2: Argument for option, if required
4518% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004519%
4520*/
cristyfe831852013-02-12 14:56:07 +00004521WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
anthonya322a832013-04-27 06:28:03 +00004522 const char *option,const char *arg1n,const char *arg2n)
anthony43f425d2012-02-26 12:58:58 +00004523{
anthonya322a832013-04-27 06:28:03 +00004524 const char /* percent escaped versions of the args */
anthony4837ac22012-05-18 23:39:48 +00004525 *arg1,
4526 *arg2;
anthony4837ac22012-05-18 23:39:48 +00004527
anthony8226e722012-04-05 14:25:46 +00004528#define _image_info (cli_wand->wand.image_info)
4529#define _images (cli_wand->wand.images)
4530#define _exception (cli_wand->wand.exception)
anthonya322a832013-04-27 06:28:03 +00004531#define _process_flags (cli_wand->process_flags)
4532#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthony8226e722012-04-05 14:25:46 +00004533#define IfNormalOp (*option=='-')
4534#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004535
4536 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004537 assert(cli_wand->signature == MagickWandSignature);
4538 assert(cli_wand->wand.signature == MagickWandSignature);
anthonya322a832013-04-27 06:28:03 +00004539
anthony7bcfe7f2012-03-30 14:01:22 +00004540 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00004541 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
cristye1f6cfe2015-06-27 15:50:30 +00004542 "- NoImage Operator: %s \"%s\" \"%s\"", option,
4543 arg1n != (char *) NULL ? arg1n : "",
4544 arg2n != (char *) NULL ? arg2n : "");
anthony43f425d2012-02-26 12:58:58 +00004545
anthony4837ac22012-05-18 23:39:48 +00004546 arg1 = arg1n;
4547 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00004548
4549 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +00004550 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4551 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4552 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4553 /* Interpret Percent escapes in argument 1 */
4554 if (arg1n != (char *) NULL) {
4555 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4556 if (arg1 == (char *) NULL) {
4557 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4558 arg1=arg1n; /* use the given argument as is */
4559 }
4560 }
4561 if (arg2n != (char *) NULL) {
4562 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4563 if (arg2 == (char *) NULL) {
4564 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4565 arg2=arg2n; /* use the given argument as is */
4566 }
4567 }
4568 }
4569#undef _process_flags
4570#undef _option_type
anthony4837ac22012-05-18 23:39:48 +00004571
4572 do { /* break to exit code */
4573 /*
4574 No-op options (ignore these)
4575 */
anthonyc7994672012-11-17 05:33:27 +00004576 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
anthony4837ac22012-05-18 23:39:48 +00004577 break;
4578 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4579 break;
anthonyc7994672012-11-17 05:33:27 +00004580 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4581 break;
4582 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
anthony4837ac22012-05-18 23:39:48 +00004583 break;
4584 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4585 break;
4586 /*
4587 Image Reading
4588 */
4589 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4590 ( LocaleCompare("--",option) == 0 ) ) {
4591 /* Do Glob filename Expansion for 'arg1' then read all images.
4592 *
4593 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4594 * (but attaching to the filenames in the generated argument list) any
4595 * [...] read modifiers that may be present.
4596 *
4597 * For example: It will expand '*.gif[20x20]' into a list such as
4598 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4599 *
4600 * NOTE: In IMv6 this was done globally across all images. This
4601 * meant you could include IM options in '@filename' lists, but you
4602 * could not include comments. Doing it only for image read makes
4603 * it far more secure.
4604 *
4605 * Note: arguments do not have percent escapes expanded for security
4606 * reasons.
4607 */
4608 int argc;
4609 char **argv;
4610 ssize_t i;
4611
4612 argc = 1;
4613 argv = (char **) &arg1;
4614
4615 /* Expand 'glob' expressions in the given filename.
4616 Expansion handles any 'coder:' prefix, or read modifiers attached
4617 to the filename, including them in the resulting expanded list.
4618 */
4619 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4620 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4621 option,GetExceptionMessage(errno));
4622
4623 /* loop over expanded filename list, and read then all in */
cristy52b632a2014-11-08 00:31:34 +00004624 for (i=0; i < (ssize_t) argc; i++) {
anthony4837ac22012-05-18 23:39:48 +00004625 Image *
4626 new_images;
4627 if (IfMagickTrue(_image_info->ping))
4628 new_images=PingImages(_image_info,argv[i],_exception);
4629 else
4630 new_images=ReadImages(_image_info,argv[i],_exception);
4631 AppendImageToList(&_images, new_images);
4632 }
4633 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4634 break;
4635 }
4636 /*
4637 Image Writing
4638 Note: Writing a empty image list is valid in specific cases
4639 */
4640 if (LocaleCompare("write",option+1) == 0) {
4641 /* Note: arguments do not have percent escapes expanded */
4642 char
cristy151b66d2015-04-15 10:50:31 +00004643 key[MagickPathExtent];
anthony4837ac22012-05-18 23:39:48 +00004644
4645 Image
4646 *write_images;
4647
4648 ImageInfo
4649 *write_info;
4650
4651 /* Need images, unless a "null:" output coder is used */
anthonya322a832013-04-27 06:28:03 +00004652 if ( _images == (Image *) NULL ) {
anthony4837ac22012-05-18 23:39:48 +00004653 if ( LocaleCompare(arg1,"null:") == 0 )
4654 break;
4655 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4656 }
4657
cristy151b66d2015-04-15 10:50:31 +00004658 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",arg1);
anthony4837ac22012-05-18 23:39:48 +00004659 (void) DeleteImageRegistry(key);
4660 write_images=_images;
4661 if (IfPlusOp)
4662 write_images=CloneImageList(_images,_exception);
4663 write_info=CloneImageInfo(_image_info);
4664 (void) WriteImages(write_info,write_images,arg1,_exception);
4665 write_info=DestroyImageInfo(write_info);
4666 if (IfPlusOp)
4667 write_images=DestroyImageList(write_images);
4668 break;
4669 }
4670 /*
4671 Parenthesis and Brace operations
4672 */
4673 if (LocaleCompare("(",option) == 0) {
4674 /* stack 'push' images */
4675 Stack
4676 *node;
4677
4678 size_t
4679 size;
4680
4681 size=0;
4682 node=cli_wand->image_list_stack;
cristyf432c632014-12-07 15:11:28 +00004683 for ( ; node != (Stack *) NULL; node=node->next)
anthony4837ac22012-05-18 23:39:48 +00004684 size++;
4685 if ( size >= MAX_STACK_DEPTH )
4686 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4687 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4688 if (node == (Stack *) NULL)
4689 CLIWandExceptionBreak(ResourceLimitFatalError,
4690 "MemoryAllocationFailed",option);
4691 node->data = (void *)cli_wand->wand.images;
anthony4837ac22012-05-18 23:39:48 +00004692 node->next = cli_wand->image_list_stack;
4693 cli_wand->image_list_stack = node;
anthonya322a832013-04-27 06:28:03 +00004694 cli_wand->wand.images = NewImageList();
anthony4837ac22012-05-18 23:39:48 +00004695
4696 /* handle respect-parenthesis */
4697 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4698 "respect-parenthesis"))))
4699 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004700 else
anthony4837ac22012-05-18 23:39:48 +00004701 break;
anthonya322a832013-04-27 06:28:03 +00004702 /* fall thru to operation */
anthony52bef752012-03-27 13:54:47 +00004703 }
anthony4837ac22012-05-18 23:39:48 +00004704 if (LocaleCompare("{",option) == 0) {
4705 /* stack 'push' of image_info settings */
4706 Stack
4707 *node;
anthony8226e722012-04-05 14:25:46 +00004708
anthony4837ac22012-05-18 23:39:48 +00004709 size_t
4710 size;
anthony8226e722012-04-05 14:25:46 +00004711
anthony4837ac22012-05-18 23:39:48 +00004712 size=0;
4713 node=cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004714 for ( ; node != (Stack *) NULL; node=node->next)
anthony4837ac22012-05-18 23:39:48 +00004715 size++;
4716 if ( size >= MAX_STACK_DEPTH )
4717 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4718 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4719 if (node == (Stack *) NULL)
4720 CLIWandExceptionBreak(ResourceLimitFatalError,
4721 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004722
anthony4837ac22012-05-18 23:39:48 +00004723 node->data = (void *)cli_wand->wand.image_info;
anthonya322a832013-04-27 06:28:03 +00004724 node->next = cli_wand->image_info_stack;
4725
4726 cli_wand->image_info_stack = node;
anthony4837ac22012-05-18 23:39:48 +00004727 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
cristyf432c632014-12-07 15:11:28 +00004728 if (cli_wand->wand.image_info == (ImageInfo *) NULL) {
anthony4837ac22012-05-18 23:39:48 +00004729 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4730 option);
4731 cli_wand->wand.image_info = (ImageInfo *)node->data;
4732 node = (Stack *)RelinquishMagickMemory(node);
4733 break;
4734 }
4735
anthony4837ac22012-05-18 23:39:48 +00004736 break;
anthony8226e722012-04-05 14:25:46 +00004737 }
anthony4837ac22012-05-18 23:39:48 +00004738 if (LocaleCompare(")",option) == 0) {
4739 /* pop images from stack */
4740 Stack
4741 *node;
anthony8226e722012-04-05 14:25:46 +00004742
anthony4837ac22012-05-18 23:39:48 +00004743 node = (Stack *)cli_wand->image_list_stack;
cristyf432c632014-12-07 15:11:28 +00004744 if ( node == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004745 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4746 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004747
anthony4837ac22012-05-18 23:39:48 +00004748 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4749 cli_wand->wand.images= (Image *)node->data;
4750 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004751
anthony4837ac22012-05-18 23:39:48 +00004752 /* handle respect-parenthesis - of the previous 'pushed' settings */
4753 node = cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004754 if ( node != (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004755 {
4756 if (IfMagickTrue(IsStringTrue(GetImageOption(
4757 cli_wand->wand.image_info,"respect-parenthesis"))))
4758 option="}"; /* fall-thru so as to pop image settings too */
4759 else
4760 break;
4761 }
4762 else
4763 break;
4764 /* fall thru to next if */
4765 }
4766 if (LocaleCompare("}",option) == 0) {
4767 /* pop image_info settings from stack */
4768 Stack
4769 *node;
anthony43f425d2012-02-26 12:58:58 +00004770
anthony4837ac22012-05-18 23:39:48 +00004771 node = (Stack *)cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004772 if ( node == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004773 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4774 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004775
anthony4837ac22012-05-18 23:39:48 +00004776 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004777 cli_wand->wand.image_info = (ImageInfo *)node->data;
4778 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004779
4780 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4781 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4782 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4783
4784 break;
4785 }
anthonya322a832013-04-27 06:28:03 +00004786 if (LocaleCompare("print",option+1) == 0)
4787 {
4788 (void) FormatLocaleFile(stdout,"%s",arg1);
4789 break;
4790 }
anthonyc7994672012-11-17 05:33:27 +00004791 if (LocaleCompare("set",option+1) == 0)
4792 {
anthonya322a832013-04-27 06:28:03 +00004793 /* Settings are applied to each image in memory in turn (if any).
4794 While a option: only need to be applied once globally.
4795
4796 NOTE: rguments have not been automatically percent expaneded
anthonyc7994672012-11-17 05:33:27 +00004797 */
anthonya322a832013-04-27 06:28:03 +00004798
4799 /* escape the 'key' once only, using first image. */
4800 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4801 if (arg1 == (char *) NULL)
4802 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4803 option);
anthonyc7994672012-11-17 05:33:27 +00004804
4805 if (LocaleNCompare(arg1,"registry:",9) == 0)
4806 {
4807 if (IfPlusOp)
4808 {
4809 (void) DeleteImageRegistry(arg1+9);
anthonya322a832013-04-27 06:28:03 +00004810 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004811 break;
4812 }
anthonya322a832013-04-27 06:28:03 +00004813 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4814 if (arg2 == (char *) NULL) {
4815 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004816 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4817 option);
anthonya322a832013-04-27 06:28:03 +00004818 }
4819 (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
4820 arg1=DestroyString((char *)arg1);
4821 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004822 break;
4823 }
4824 if (LocaleNCompare(arg1,"option:",7) == 0)
4825 {
4826 /* delete equivelent artifact from all images (if any) */
cristyf432c632014-12-07 15:11:28 +00004827 if (_images != (Image *) NULL)
anthonya322a832013-04-27 06:28:03 +00004828 {
4829 MagickResetIterator(&cli_wand->wand);
4830 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4831 (void) DeleteImageArtifact(_images,arg1+7);
4832 MagickResetIterator(&cli_wand->wand);
4833 }
anthonyc7994672012-11-17 05:33:27 +00004834 /* now set/delete the global option as needed */
anthonya322a832013-04-27 06:28:03 +00004835 /* FUTURE: make escapes in a global 'option:' delayed */
cristyf432c632014-12-07 15:11:28 +00004836 arg2=(char *) NULL;
anthonya322a832013-04-27 06:28:03 +00004837 if (IfNormalOp)
4838 {
4839 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4840 if (arg2 == (char *) NULL)
4841 CLIWandExceptionBreak(OptionWarning,
4842 "InterpretPropertyFailure",option);
4843 }
4844 (void) SetImageOption(_image_info,arg1+7,arg2);
4845 arg1=DestroyString((char *)arg1);
4846 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004847 break;
4848 }
anthonya322a832013-04-27 06:28:03 +00004849 /* Set Artifacts/Properties/Attributes all images (required) */
4850 if ( _images == (Image *) NULL )
4851 CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
4852
anthonyc7994672012-11-17 05:33:27 +00004853 MagickResetIterator(&cli_wand->wand);
4854 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4855 {
cristyf432c632014-12-07 15:11:28 +00004856 arg2=(char *) NULL;
anthonya322a832013-04-27 06:28:03 +00004857 if (IfNormalOp)
4858 {
4859 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4860 if (arg2 == (char *) NULL)
4861 CLIWandExceptionBreak(OptionWarning,
4862 "InterpretPropertyFailure",option);
4863 }
4864 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4865 (void) SetImageArtifact(_images,arg1+9,arg2);
4866 else if (LocaleNCompare(arg1,"property:",9) == 0)
4867 (void) SetImageProperty(_images,arg1+9,arg2,_exception);
4868 else
4869 (void) SetImageProperty(_images,arg1,arg2,_exception);
4870 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004871 }
4872 MagickResetIterator(&cli_wand->wand);
anthonya322a832013-04-27 06:28:03 +00004873 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004874 break;
4875 }
anthony4837ac22012-05-18 23:39:48 +00004876 if (LocaleCompare("clone",option+1) == 0) {
4877 Image
4878 *new_images;
4879
4880 if (*option == '+')
cristy3677cc72014-11-14 23:22:55 +00004881 arg1=AcquireString("-1");
anthony4837ac22012-05-18 23:39:48 +00004882 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4883 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
cristyf432c632014-12-07 15:11:28 +00004884 if ( cli_wand->image_list_stack == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004885 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4886 new_images = (Image *)cli_wand->image_list_stack->data;
4887 if (new_images == (Image *) NULL)
4888 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4889 new_images=CloneImages(new_images,arg1,_exception);
4890 if (new_images == (Image *) NULL)
4891 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4892 AppendImageToList(&_images,new_images);
4893 break;
4894 }
4895 /*
cristy422d5502012-12-22 22:20:57 +00004896 Informational Operations.
anthony4837ac22012-05-18 23:39:48 +00004897
anthonyc7994672012-11-17 05:33:27 +00004898 Note that these do not require either a cli-wand or images!
4899 Though currently a cli-wand much be provided regardless.
anthony4837ac22012-05-18 23:39:48 +00004900 */
cristy422d5502012-12-22 22:20:57 +00004901 if (LocaleCompare("version",option+1) == 0)
4902 {
cristy4f7a6132012-12-23 00:35:19 +00004903 ListMagickVersion(stdout);
cristy422d5502012-12-22 22:20:57 +00004904 break;
4905 }
anthony4837ac22012-05-18 23:39:48 +00004906 if (LocaleCompare("list",option+1) == 0) {
4907 /*
anthonyc7994672012-11-17 05:33:27 +00004908 FUTURE: This 'switch' should really be part of MagickCore
anthony4837ac22012-05-18 23:39:48 +00004909 */
4910 ssize_t
4911 list;
4912
4913 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4914 if ( list < 0 ) {
4915 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4916 break;
4917 }
4918 switch (list)
4919 {
4920 case MagickCoderOptions:
4921 {
4922 (void) ListCoderInfo((FILE *) NULL,_exception);
4923 break;
4924 }
4925 case MagickColorOptions:
4926 {
4927 (void) ListColorInfo((FILE *) NULL,_exception);
4928 break;
4929 }
4930 case MagickConfigureOptions:
4931 {
4932 (void) ListConfigureInfo((FILE *) NULL,_exception);
4933 break;
4934 }
4935 case MagickDelegateOptions:
4936 {
4937 (void) ListDelegateInfo((FILE *) NULL,_exception);
4938 break;
4939 }
4940 case MagickFontOptions:
4941 {
4942 (void) ListTypeInfo((FILE *) NULL,_exception);
4943 break;
4944 }
4945 case MagickFormatOptions:
4946 (void) ListMagickInfo((FILE *) NULL,_exception);
4947 break;
4948 case MagickLocaleOptions:
4949 (void) ListLocaleInfo((FILE *) NULL,_exception);
4950 break;
4951 case MagickLogOptions:
4952 (void) ListLogInfo((FILE *) NULL,_exception);
4953 break;
4954 case MagickMagicOptions:
4955 (void) ListMagicInfo((FILE *) NULL,_exception);
4956 break;
4957 case MagickMimeOptions:
4958 (void) ListMimeInfo((FILE *) NULL,_exception);
4959 break;
4960 case MagickModuleOptions:
4961 (void) ListModuleInfo((FILE *) NULL,_exception);
4962 break;
4963 case MagickPolicyOptions:
4964 (void) ListPolicyInfo((FILE *) NULL,_exception);
4965 break;
4966 case MagickResourceOptions:
4967 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4968 break;
4969 case MagickThresholdOptions:
4970 (void) ListThresholdMaps((FILE *) NULL,_exception);
4971 break;
4972 default:
4973 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4974 _exception);
4975 break;
4976 }
4977 break;
anthony43f425d2012-02-26 12:58:58 +00004978 }
anthony8226e722012-04-05 14:25:46 +00004979
anthony4837ac22012-05-18 23:39:48 +00004980 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony8226e722012-04-05 14:25:46 +00004981
dirk93b02b72013-11-16 16:03:36 +00004982DisableMSCWarning(4127)
anthony4837ac22012-05-18 23:39:48 +00004983 } while (0); /* break to exit code. */
dirk93b02b72013-11-16 16:03:36 +00004984RestoreMSCWarning
anthony43f425d2012-02-26 12:58:58 +00004985
anthony4837ac22012-05-18 23:39:48 +00004986 /* clean up percent escape interpreted strings */
4987 if (arg1 != arg1n )
4988 arg1=DestroyString((char *)arg1);
4989 if (arg2 != arg2n )
4990 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00004991
anthony8226e722012-04-05 14:25:46 +00004992#undef _image_info
4993#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004994#undef _exception
anthony8226e722012-04-05 14:25:46 +00004995#undef IfNormalOp
4996#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004997}
anthony464f1c42012-04-22 08:51:01 +00004998
4999/*
5000%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5001% %
5002% %
5003% %
anthony964d28e2012-05-17 23:39:46 +00005004+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00005005% %
5006% %
5007% %
5008%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5009%
5010% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00005011% The option arguments can be variable in number, though at this time no more
5012% that two is actually used by any option (this may change). Excess options
5013% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00005014%
5015% If the cli_wand->command pointer is non-null, then it is assumed that the
5016% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00005017% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
5018% routine will do the lookup instead. The pointer is reset afterward.
5019%
5020% This action allows the caller to lookup and pre-handle any 'special'
5021% options, (such as implicit reads) before calling this general option
5022% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00005023%
5024% The format of the CLIOption method is:
5025%
5026% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
5027%
5028% A description of each parameter follows:
5029%
5030% o cli_wand: the main CLI Wand to use.
5031%
5032% o option: The special option (with any switch char) to process
5033%
anthony964d28e2012-05-17 23:39:46 +00005034% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00005035%
5036% Example Usage...
5037%
5038% CLIoption(cli_wand,"-read","rose:");
5039% CLIoption(cli_wand,"-virtual-pixel","transparent");
5040% CLIoption(cli_wand,"-distort","SRT:","30");
5041% CLIoption(cli_wand,"-write","rotated_rose.png");
5042%
5043*/
5044WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
5045{
anthonya322a832013-04-27 06:28:03 +00005046 const char /* extracted option args from args */
anthony464f1c42012-04-22 08:51:01 +00005047 *arg1,
5048 *arg2;
5049
5050 CommandOptionFlags
5051 option_type;
5052
5053 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00005054 assert(cli_wand->signature == MagickWandSignature);
5055 assert(cli_wand->wand.signature == MagickWandSignature);
anthony464f1c42012-04-22 08:51:01 +00005056
anthony964d28e2012-05-17 23:39:46 +00005057 do { /* Break Code Block for error handling */
5058
5059 /* get information about option */
5060 if ( cli_wand->command == (const OptionInfo *) NULL )
5061 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00005062#if 0
anthony964d28e2012-05-17 23:39:46 +00005063 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
5064 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00005065#endif
anthony964d28e2012-05-17 23:39:46 +00005066 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00005067
anthony964d28e2012-05-17 23:39:46 +00005068 if ( option_type == UndefinedOptionFlag )
5069 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00005070
anthony964d28e2012-05-17 23:39:46 +00005071 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00005072
dirkab5c7452014-10-11 19:14:52 +00005073 /* deprecated options */
anthony964d28e2012-05-17 23:39:46 +00005074 if ( (option_type & DeprecateOptionFlag) != 0 )
5075 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00005076
anthony964d28e2012-05-17 23:39:46 +00005077 /* options that this module does not handle */
5078 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
5079 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00005080
anthony964d28e2012-05-17 23:39:46 +00005081 /* Get argument strings from VarArgs
anthonya322a832013-04-27 06:28:03 +00005082 How can you determine if enough arguments was supplied?
5083 What happens if not enough arguments were supplied?
5084 */
anthony964d28e2012-05-17 23:39:46 +00005085 { size_t
cristy52b632a2014-11-08 00:31:34 +00005086 count = (size_t) cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00005087
anthony964d28e2012-05-17 23:39:46 +00005088 va_list
5089 operands;
anthony464f1c42012-04-22 08:51:01 +00005090
anthony964d28e2012-05-17 23:39:46 +00005091 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00005092
anthony964d28e2012-05-17 23:39:46 +00005093 arg1=arg2=NULL;
5094 if ( count >= 1 )
5095 arg1=(const char *) va_arg(operands, const char *);
5096 if ( count >= 2 )
5097 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00005098
anthony964d28e2012-05-17 23:39:46 +00005099 va_end(operands);
anthony52cb3df2012-04-24 03:29:32 +00005100#if 0
anthony964d28e2012-05-17 23:39:46 +00005101 (void) FormatLocaleFile(stderr,
5102 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
5103 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00005104#endif
anthony964d28e2012-05-17 23:39:46 +00005105 }
5106
5107 /*
5108 Call the appropriate option handler
5109 */
5110
5111 /* FUTURE: this is temporary - get 'settings' to handle distribution of
5112 settings to images attributes,proprieties,artifacts */
cristyf432c632014-12-07 15:11:28 +00005113 if ( cli_wand->wand.images != (Image *) NULL )
cristy52b632a2014-11-08 00:31:34 +00005114 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
5115 cli_wand->wand.exception);
anthony964d28e2012-05-17 23:39:46 +00005116
5117 if ( (option_type & SettingOptionFlags) != 0 ) {
5118 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
5119 // FUTURE: Sync Specific Settings into Image Properities (not global)
5120 }
5121
5122 /* Operators that do not need images - read, write, stack, clone */
cristye1f6cfe2015-06-27 15:50:30 +00005123 if ((option_type & NoImageOperatorFlag) != 0)
anthony964d28e2012-05-17 23:39:46 +00005124 CLINoImageOperator(cli_wand, option, arg1, arg2);
5125
5126 /* FUTURE: The not a setting part below is a temporary hack due to
5127 * some options being both a Setting and a Simple operator.
5128 * Specifically -monitor, -depth, and -colorspace */
cristyf432c632014-12-07 15:11:28 +00005129 if ( cli_wand->wand.images == (Image *) NULL )
anthony964d28e2012-05-17 23:39:46 +00005130 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
5131 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
5132 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
5133
anthonya322a832013-04-27 06:28:03 +00005134 /* Operators which loop of individual images, simply */
5135 if ( (option_type & SimpleOperatorFlag) != 0 &&
cristyf432c632014-12-07 15:11:28 +00005136 cli_wand->wand.images != (Image *) NULL) /* temp hack */
cristy2c57b742014-10-31 00:40:34 +00005137 {
5138 ExceptionInfo *exception=AcquireExceptionInfo();
cristy52b632a2014-11-08 00:31:34 +00005139 (void) CLISimpleOperatorImages(cli_wand, option, arg1, arg2,exception);
cristy2c57b742014-10-31 00:40:34 +00005140 exception=DestroyExceptionInfo(exception);
5141 }
anthony964d28e2012-05-17 23:39:46 +00005142
5143 /* Operators that work on the image list as a whole */
5144 if ( (option_type & ListOperatorFlag) != 0 )
cristy52b632a2014-11-08 00:31:34 +00005145 (void) CLIListOperatorImages(cli_wand, option, arg1, arg2);
anthony964d28e2012-05-17 23:39:46 +00005146
dirk93b02b72013-11-16 16:03:36 +00005147DisableMSCWarning(4127)
anthony964d28e2012-05-17 23:39:46 +00005148 } while (0); /* end Break code block */
dirk93b02b72013-11-16 16:03:36 +00005149RestoreMSCWarning
anthony464f1c42012-04-22 08:51:01 +00005150
5151 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00005152}