blob: a3bc47ec54bf6311d3587d39214db9682ed97416 [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);
202 assert(image->signature == MagickSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000203 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000204 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
205 assert(exception != (ExceptionInfo *) NULL);
206 assert(exception->signature == MagickSignature);
207 /*
anthonyb1d483a2012-04-14 12:53:56 +0000208 Limit channels according to image
209 add up number of values needed per color.
anthony805a2d42011-09-25 08:25:12 +0000210 */
211 number_colors=0;
212 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
213 number_colors++;
214 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
215 number_colors++;
216 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
217 number_colors++;
218 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
219 (image->colorspace == CMYKColorspace))
220 number_colors++;
221 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
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);
426 assert(cli_wand->signature == WandSignature);
427 assert(cli_wand->wand.signature == WandSignature);
anthony4837ac22012-05-18 23:39:48 +0000428
anthonya322a832013-04-27 06:28:03 +0000429 if (IfMagickTrue(cli_wand->wand.debug))
430 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
431 "- Setting Option: %s \"%s\" \"%s\"", option,arg1n,arg2n);
432
433 arg1 = arg1n,
434 arg2 = arg2n;
435
436#if 1
anthony4837ac22012-05-18 23:39:48 +0000437#define _process_flags (cli_wand->process_flags)
438#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
439 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +0000440 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
441 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
442 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
443 /* Interpret Percent escapes in argument 1 */
444 if (arg1n != (char *) NULL) {
445 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
446 if (arg1 == (char *) NULL) {
447 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
448 arg1=arg1n; /* use the given argument as is */
449 }
450 }
451 if (arg2n != (char *) NULL) {
452 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
453 if (arg2 == (char *) NULL) {
454 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
455 arg2=arg2n; /* use the given argument as is */
456 }
457 }
458 }
459#undef _process_flags
460#undef _option_type
461#endif
462
anthonyafa3dfc2012-03-03 11:31:30 +0000463 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000464 {
465 case 'a':
466 {
anthonyafa3dfc2012-03-03 11:31:30 +0000467 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000468 {
anthony92c93bd2012-03-19 14:02:47 +0000469 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000470 break;
471 }
anthonyafa3dfc2012-03-03 11:31:30 +0000472 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000473 {
anthony464f1c42012-04-22 08:51:01 +0000474 CLIWandWarnReplaced("-draw 'affine ...'");
anthony74b1cfc2011-10-06 12:44:16 +0000475 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000476 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000477 else
anthony92c93bd2012-03-19 14:02:47 +0000478 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000479 break;
480 }
anthonyafa3dfc2012-03-03 11:31:30 +0000481 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000482 {
anthony92c93bd2012-03-19 14:02:47 +0000483 _image_info->antialias =
484 _draw_info->stroke_antialias =
485 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000486 break;
487 }
anthony31f1bf72012-01-30 12:37:22 +0000488 if (LocaleCompare("attenuate",option+1) == 0)
489 {
anthony7bcfe7f2012-03-30 14:01:22 +0000490 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000491 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
492 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000493 break;
494 }
anthonyafa3dfc2012-03-03 11:31:30 +0000495 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000496 {
anthony92c93bd2012-03-19 14:02:47 +0000497 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000498 break;
499 }
anthonyebb73a22012-03-22 14:25:52 +0000500 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000501 }
502 case 'b':
503 {
anthonyafa3dfc2012-03-03 11:31:30 +0000504 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000505 {
anthony92c93bd2012-03-19 14:02:47 +0000506 /* FUTURE: both _image_info attribute & ImageOption in use!
507 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000508 SyncImageSettings() used to set per-image attribute.
509
anthony92c93bd2012-03-19 14:02:47 +0000510 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000511 we should fall back to per-image background_color
512
513 At this time -background will 'wipe out' the per-image
514 background color!
515
516 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000517 */
anthony92c93bd2012-03-19 14:02:47 +0000518 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
cristyd7df81d2014-01-18 18:42:05 +0000519 (void) QueryColorCompliance(ArgOption(MogrifyBackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000520 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000521 break;
522 }
anthonyafa3dfc2012-03-03 11:31:30 +0000523 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000524 {
anthony52bef752012-03-27 13:54:47 +0000525 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000526 as it is actually rarely used except in direct convolve operations
527 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000528
529 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000530 */
anthony7bcfe7f2012-03-30 14:01:22 +0000531 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000532 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000533 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000534 break;
535 }
anthonyafa3dfc2012-03-03 11:31:30 +0000536 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000537 {
anthony72feaa62012-01-17 06:46:23 +0000538 /* Used as a image chromaticity setting
539 SyncImageSettings() used to set per-image attribute.
540 */
anthony92c93bd2012-03-19 14:02:47 +0000541 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000542 break;
543 }
anthonyafa3dfc2012-03-03 11:31:30 +0000544 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000545 {
anthonyafbaed72011-10-26 12:05:04 +0000546 /* Image chromaticity X,Y NB: Y=X if Y not defined
547 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000548 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000549 */
anthonyf42014d2012-03-25 09:53:06 +0000550 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000551 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000552 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000553 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000554 break;
555 }
anthonyafa3dfc2012-03-03 11:31:30 +0000556 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000557 {
anthony92c93bd2012-03-19 14:02:47 +0000558 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000559 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000560 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000561 */
anthony74b1cfc2011-10-06 12:44:16 +0000562 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000563 {
anthony92c93bd2012-03-19 14:02:47 +0000564 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000565 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000566 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000567 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000568 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000569 break;
570 }
anthony92c93bd2012-03-19 14:02:47 +0000571 (void) DeleteImageOption(_image_info,option+1);
cristyd7df81d2014-01-18 18:42:05 +0000572 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000573 &_image_info->border_color,_exception);
cristyd7df81d2014-01-18 18:42:05 +0000574 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000575 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000576 break;
577 }
anthonyafa3dfc2012-03-03 11:31:30 +0000578 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000579 {
anthony464f1c42012-04-22 08:51:01 +0000580 CLIWandWarnReplaced("-undercolor");
anthony975a8d72012-04-12 13:54:36 +0000581 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
anthonyfd706f92012-01-19 04:22:02 +0000582 break;
anthony805a2d42011-09-25 08:25:12 +0000583 }
anthonyebb73a22012-03-22 14:25:52 +0000584 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000585 }
586 case 'c':
587 {
anthonyafa3dfc2012-03-03 11:31:30 +0000588 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000589 {
590 MagickSizeType
591 limit;
592
anthony7bcfe7f2012-03-30 14:01:22 +0000593 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000594 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000595 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000596 if (LocaleCompare("unlimited",arg1) != 0)
597 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000598 (void) SetMagickResourceLimit(MemoryResource,limit);
599 (void) SetMagickResourceLimit(MapResource,2*limit);
600 break;
601 }
anthonyafa3dfc2012-03-03 11:31:30 +0000602 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000603 {
anthony92c93bd2012-03-19 14:02:47 +0000604 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000605 break;
606 }
anthonyafa3dfc2012-03-03 11:31:30 +0000607 if (LocaleCompare("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);
1701 assert(cli_wand->signature == WandSignature);
1702 assert(cli_wand->wand.signature == WandSignature);
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 }
cristy3476df82015-06-22 18:43:46 +00002168 if (LocaleCompare("copy",option+1) == 0)
2169 {
2170 Image
2171 *source_image;
2172
2173 OffsetInfo
2174 offset;
2175
2176 /*
2177 Copy image pixels.
2178 */
2179 if (IfMagickFalse(IsGeometry(arg1)))
2180 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2181 if (IfMagickFalse(IsGeometry(arg2)))
2182 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2183 flags=ParsePageGeometry(_image,arg2,&geometry,exception);
2184 offset.x=geometry.x;
2185 offset.y=geometry.y;
2186 flags=ParsePageGeometry(_image,arg1,&geometry,exception);
2187 source_image=_image;
2188 if (_image->next != (Image *) NULL)
2189 source_image=_image->next;
2190 (void) CopyImagePixels(_image,source_image,&geometry,&offset,
2191 exception);
2192 break;
2193 }
anthonyafa3dfc2012-03-03 11:31:30 +00002194 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002195 {
anthony31f1bf72012-01-30 12:37:22 +00002196 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002197 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002199 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002200 break;
2201 }
anthonyafa3dfc2012-03-03 11:31:30 +00002202 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002203 {
anthony7bcfe7f2012-03-30 14:01:22 +00002204 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002205 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002206 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2207 _exception);
anthony805a2d42011-09-25 08:25:12 +00002208 break;
2209 }
anthonyebb73a22012-03-22 14:25:52 +00002210 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002211 }
2212 case 'd':
2213 {
anthonyafa3dfc2012-03-03 11:31:30 +00002214 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002215 {
anthony4837ac22012-05-18 23:39:48 +00002216 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002217 StringInfo
2218 *passkey;
2219
cristy3a5987c2013-11-07 14:18:46 +00002220 passkey=FileToStringInfo(arg1,~0UL,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002221 if (passkey == (StringInfo *) NULL)
2222 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2223
2224 (void) PasskeyDecipherImage(_image,passkey,_exception);
2225 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002226 break;
2227 }
anthonyafa3dfc2012-03-03 11:31:30 +00002228 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002229 {
anthony92c93bd2012-03-19 14:02:47 +00002230 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002231 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002232
anthonydcf510d2011-10-30 13:51:40 +00002233 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2234 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002235
anthonyfd706f92012-01-19 04:22:02 +00002236 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002237 */
anthony92c93bd2012-03-19 14:02:47 +00002238 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002239 break;
2240 }
anthonyafa3dfc2012-03-03 11:31:30 +00002241 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002242 {
2243 double
2244 threshold;
2245
anthonyebb73a22012-03-22 14:25:52 +00002246 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002247 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002248 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002249 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002250 }
anthonyafa3dfc2012-03-03 11:31:30 +00002251 else
2252 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002253 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002254 break;
2255 }
anthonyafa3dfc2012-03-03 11:31:30 +00002256 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002257 {
anthony92c93bd2012-03-19 14:02:47 +00002258 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002259 break;
2260 }
anthonyafa3dfc2012-03-03 11:31:30 +00002261 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002262 {
anthony805a2d42011-09-25 08:25:12 +00002263 double
anthonyb1d483a2012-04-14 12:53:56 +00002264 *args;
anthony805a2d42011-09-25 08:25:12 +00002265
anthonyb1d483a2012-04-14 12:53:56 +00002266 ssize_t
2267 count;
anthony805a2d42011-09-25 08:25:12 +00002268
anthony2a0ec8c2012-03-24 04:35:56 +00002269 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2270 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002271 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2272 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002273 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002274 {
anthony80c37752012-01-16 01:03:11 +00002275 double
2276 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002277 /* Special Case - Argument is actually a resize geometry!
2278 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002279 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002280 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002281 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002282 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2283 option,arg2);
2284 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002285 resize_args[0]=(double) geometry.width;
2286 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002287 new_image=DistortImage(_image,(DistortImageMethod) parse,
2288 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002289 break;
2290 }
anthonyb1d483a2012-04-14 12:53:56 +00002291 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002292 args = StringToArrayOfDoubles(arg2,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00002293 if (args == (double *) NULL )
anthonyb1d483a2012-04-14 12:53:56 +00002294 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2295
cristy52b632a2014-11-08 00:31:34 +00002296 new_image=DistortImage(_image,(DistortImageMethod) parse,(size_t)
2297 count,args,IsPlusOp,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002298 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002299 break;
2300 }
anthonyafa3dfc2012-03-03 11:31:30 +00002301 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002302 {
anthony92c93bd2012-03-19 14:02:47 +00002303 (void) CloneString(&_draw_info->primitive,arg1);
2304 (void) DrawImage(_image,_draw_info,_exception);
cristyf432c632014-12-07 15:11:28 +00002305 (void) CloneString(&_draw_info->primitive,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002306 break;
2307 }
anthonyebb73a22012-03-22 14:25:52 +00002308 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002309 }
2310 case 'e':
2311 {
anthonyafa3dfc2012-03-03 11:31:30 +00002312 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002313 {
anthonyfd706f92012-01-19 04:22:02 +00002314 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002315 if ((flags & (RhoValue|SigmaValue)) == 0)
2316 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy9dc4c512013-03-24 01:38:00 +00002317 new_image=EdgeImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002318 break;
2319 }
anthonyafa3dfc2012-03-03 11:31:30 +00002320 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002321 {
anthonyfd706f92012-01-19 04:22:02 +00002322 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002323 if ((flags & (RhoValue|SigmaValue)) == 0)
2324 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002325 if ((flags & SigmaValue) == 0)
2326 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002327 new_image=EmbossImage(_image,geometry_info.rho,
2328 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002329 break;
2330 }
anthonyafa3dfc2012-03-03 11:31:30 +00002331 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002332 {
anthony4837ac22012-05-18 23:39:48 +00002333 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002334 StringInfo
2335 *passkey;
2336
cristy3a5987c2013-11-07 14:18:46 +00002337 passkey=FileToStringInfo(arg1,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002338 if (passkey != (StringInfo *) NULL)
2339 {
anthony92c93bd2012-03-19 14:02:47 +00002340 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002341 passkey=DestroyStringInfo(passkey);
2342 }
2343 break;
2344 }
anthonyafa3dfc2012-03-03 11:31:30 +00002345 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002346 {
anthony92c93bd2012-03-19 14:02:47 +00002347 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002348 break;
2349 }
anthonyafa3dfc2012-03-03 11:31:30 +00002350 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002351 {
anthony92c93bd2012-03-19 14:02:47 +00002352 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002353 break;
2354 }
anthonyafa3dfc2012-03-03 11:31:30 +00002355 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002356 {
2357 double
2358 constant;
2359
anthony2a0ec8c2012-03-24 04:35:56 +00002360 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2361 if ( parse < 0 )
2362 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2363 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002364 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002365 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002366 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002367 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2368 _exception);
anthony805a2d42011-09-25 08:25:12 +00002369 break;
2370 }
anthonyafa3dfc2012-03-03 11:31:30 +00002371 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002372 {
anthony7bcfe7f2012-03-30 14:01:22 +00002373 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002374 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002375 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002376 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002377 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002378 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002379 geometry.height=_image->rows;
2380 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002381 break;
2382 }
anthonyebb73a22012-03-22 14:25:52 +00002383 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002384 }
2385 case 'f':
2386 {
anthonyafa3dfc2012-03-03 11:31:30 +00002387 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002388 {
anthony92c93bd2012-03-19 14:02:47 +00002389 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002390 break;
2391 }
anthonyafa3dfc2012-03-03 11:31:30 +00002392 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002393 {
anthony92c93bd2012-03-19 14:02:47 +00002394 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002395 break;
2396 }
anthonyafa3dfc2012-03-03 11:31:30 +00002397 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002398 {
2399 PixelInfo
2400 target;
2401
anthony7bcfe7f2012-03-30 14:01:22 +00002402 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002403 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002404 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2405 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2406 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
anthonya322a832013-04-27 06:28:03 +00002407 geometry.y,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002408 break;
2409 }
anthonyafa3dfc2012-03-03 11:31:30 +00002410 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002411 {
2412 FrameInfo
2413 frame_info;
2414
anthony31f1bf72012-01-30 12:37:22 +00002415 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002416 compose;
2417
2418 const char*
2419 value;
2420
anthony92c93bd2012-03-19 14:02:47 +00002421 value=GetImageOption(_image_info,"compose");
anthony92c93bd2012-03-19 14:02:47 +00002422 compose=OverCompositeOp; /* use Over not _image->compose */
cristy4b892612012-08-03 19:31:31 +00002423 if (value != (const char *) NULL)
2424 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2425 MagickFalse,value);
anthony7bcfe7f2012-03-30 14:01:22 +00002426 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002427 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002428 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002429 frame_info.width=geometry.width;
2430 frame_info.height=geometry.height;
anthony805a2d42011-09-25 08:25:12 +00002431 frame_info.outer_bevel=geometry.x;
2432 frame_info.inner_bevel=geometry.y;
2433 frame_info.x=(ssize_t) frame_info.width;
2434 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002435 frame_info.width=_image->columns+2*frame_info.width;
2436 frame_info.height=_image->rows+2*frame_info.height;
2437 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002438 break;
2439 }
anthonyafa3dfc2012-03-03 11:31:30 +00002440 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002441 {
anthony805a2d42011-09-25 08:25:12 +00002442 double
anthonyb1d483a2012-04-14 12:53:56 +00002443 *args;
anthony805a2d42011-09-25 08:25:12 +00002444
anthonyb1d483a2012-04-14 12:53:56 +00002445 ssize_t
2446 count;
anthony805a2d42011-09-25 08:25:12 +00002447
anthony2a0ec8c2012-03-24 04:35:56 +00002448 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2449 if ( parse < 0 )
2450 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2451 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002452 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002453 args = StringToArrayOfDoubles(arg2,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00002454 if (args == (double *) NULL )
anthonyb1d483a2012-04-14 12:53:56 +00002455 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2456
cristy52b632a2014-11-08 00:31:34 +00002457 (void) FunctionImage(_image,(MagickFunction)parse,(size_t) count,args,
anthonyb1d483a2012-04-14 12:53:56 +00002458 _exception);
2459 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002460 break;
2461 }
anthonyebb73a22012-03-22 14:25:52 +00002462 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002463 }
2464 case 'g':
2465 {
anthonyafa3dfc2012-03-03 11:31:30 +00002466 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002467 {
anthony7a4d6102012-07-01 09:48:25 +00002468 double
2469 constant;
2470
anthony7bcfe7f2012-03-30 14:01:22 +00002471 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002472 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony7a4d6102012-07-01 09:48:25 +00002473 constant=StringToDouble(arg1,(char **) NULL);
2474#if 0
2475 /* Using Gamma, via a cache */
2476 if (IfPlusOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002477 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002478 (void) GammaImage(_image,constant,_exception);
2479#else
2480 /* Using Evaluate POW, direct update of values - more accurite */
anthonyafa3dfc2012-03-03 11:31:30 +00002481 if (IfNormalOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002482 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002483 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
cristya4943882015-02-11 11:25:46 +00002484 _image->gamma*=StringToDouble(arg1,(char **) NULL);
anthony7a4d6102012-07-01 09:48:25 +00002485#endif
2486 /* Set gamma setting -- Old meaning of "+gamma"
2487 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2488 */
anthony805a2d42011-09-25 08:25:12 +00002489 break;
2490 }
anthony975a8d72012-04-12 13:54:36 +00002491 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002492 {
anthonyfd706f92012-01-19 04:22:02 +00002493 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002494 if ((flags & (RhoValue|SigmaValue)) == 0)
2495 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002496 if ((flags & SigmaValue) == 0)
2497 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002498 new_image=GaussianBlurImage(_image,geometry_info.rho,
2499 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002500 break;
2501 }
anthony975a8d72012-04-12 13:54:36 +00002502 if (LocaleCompare("gaussian",option+1) == 0)
2503 {
anthony464f1c42012-04-22 08:51:01 +00002504 CLIWandWarnReplaced("-gaussian-blur");
cristy52b632a2014-11-08 00:31:34 +00002505 (void) CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL,exception);
anthony975a8d72012-04-12 13:54:36 +00002506 }
anthonyafa3dfc2012-03-03 11:31:30 +00002507 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002508 {
anthonyfd706f92012-01-19 04:22:02 +00002509 /*
anthony31f1bf72012-01-30 12:37:22 +00002510 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002511 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002512 FUTURE: Why if no 'offset' does this resize ALL images?
2513 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002514 */
anthonyafa3dfc2012-03-03 11:31:30 +00002515 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002516 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002517 if (_image->geometry != (char *) NULL)
2518 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002519 break;
2520 }
anthony7bcfe7f2012-03-30 14:01:22 +00002521 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002522 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002523 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002524 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002525 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002526 else
anthony92c93bd2012-03-19 14:02:47 +00002527 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002528 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002529 break;
2530 }
cristyab943592013-03-29 16:47:23 +00002531 if (LocaleCompare("grayscale",option+1) == 0)
cristye0b9b8f2013-03-28 12:39:39 +00002532 {
cristyab943592013-03-29 16:47:23 +00002533 parse=ParseCommandOption(MagickPixelIntensityOptions,
cristye0b9b8f2013-03-28 12:39:39 +00002534 MagickFalse,arg1);
cristyab943592013-03-29 16:47:23 +00002535 if (parse < 0)
2536 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
2537 option,arg1);
2538 (void) GrayscaleImage(_image,(PixelIntensityMethod) parse,_exception);
cristye0b9b8f2013-03-28 12:39:39 +00002539 break;
2540 }
anthonyebb73a22012-03-22 14:25:52 +00002541 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002542 }
cristy2fc10e52014-04-26 14:13:53 +00002543 case 'h':
2544 {
2545 if (LocaleCompare("hough-lines",option+1) == 0)
2546 {
2547 flags=ParseGeometry(arg1,&geometry_info);
2548 if ((flags & (RhoValue|SigmaValue)) == 0)
2549 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2550 if ((flags & SigmaValue) == 0)
cristyd5b8d2a2014-04-27 17:43:33 +00002551 geometry_info.sigma=geometry_info.rho;
cristy2fc10e52014-04-26 14:13:53 +00002552 if ((flags & XiValue) == 0)
cristy20f90422014-04-27 13:34:21 +00002553 geometry_info.xi=40;
2554 new_image=HoughLineImage(_image,(size_t) geometry_info.rho,
2555 (size_t) geometry_info.sigma,(size_t) geometry_info.xi,_exception);
cristy2fc10e52014-04-26 14:13:53 +00002556 break;
2557 }
2558 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2559 }
anthony805a2d42011-09-25 08:25:12 +00002560 case 'i':
2561 {
anthonyafa3dfc2012-03-03 11:31:30 +00002562 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002563 {
anthony31f1bf72012-01-30 12:37:22 +00002564 const char
2565 *format,
anthony805a2d42011-09-25 08:25:12 +00002566 *text;
2567
anthony92c93bd2012-03-19 14:02:47 +00002568 format=GetImageOption(_image_info,"format");
cristyf9b9b662013-05-25 12:50:16 +00002569 if (format == (char *) NULL)
2570 {
2571 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2572 _exception);
2573 break;
2574 }
anthony92c93bd2012-03-19 14:02:47 +00002575 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002576 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002577 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
cristyf9b9b662013-05-25 12:50:16 +00002578 option);
anthony805a2d42011-09-25 08:25:12 +00002579 (void) fputs(text,stdout);
anthony31f1bf72012-01-30 12:37:22 +00002580 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002581 break;
2582 }
anthonyafa3dfc2012-03-03 11:31:30 +00002583 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002584 {
anthonyb1e21ed2012-04-20 12:43:12 +00002585 flags=ParseGeometry(arg1,&geometry_info);
2586 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002588 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2589 _exception);
anthony805a2d42011-09-25 08:25:12 +00002590 break;
2591 }
anthonyafa3dfc2012-03-03 11:31:30 +00002592 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002593 {
anthonyfe1aa782012-03-24 13:43:04 +00002594 /* FUTURE: New to IMv7
2595 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002596 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002597 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002598 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2599 new_image=InterpolativeResizeImage(_image,geometry.width,
2600 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002601 break;
2602 }
anthonyebb73a22012-03-22 14:25:52 +00002603 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002604 }
cristy3b207f82014-09-27 14:21:20 +00002605 case 'k':
2606 {
2607 if (LocaleCompare("kuwahara",option+1) == 0)
2608 {
2609 /*
2610 Edge preserving blur.
2611 */
2612 flags=ParseGeometry(arg1,&geometry_info);
2613 if ((flags & (RhoValue|SigmaValue)) == 0)
2614 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2615 if ((flags & SigmaValue) == 0)
cristy25ea9362014-10-04 01:12:09 +00002616 geometry_info.sigma=geometry_info.rho-0.5;
cristy3b207f82014-09-27 14:21:20 +00002617 new_image=KuwaharaImage(_image,geometry_info.rho,geometry_info.sigma,
2618 _exception);
2619 break;
2620 }
2621 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2622 }
anthony805a2d42011-09-25 08:25:12 +00002623 case 'l':
2624 {
anthonyafa3dfc2012-03-03 11:31:30 +00002625 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002626 {
anthonyfd706f92012-01-19 04:22:02 +00002627 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002628 if ((flags & (RhoValue|SigmaValue)) == 0)
2629 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyb5c691e2012-09-14 17:12:40 +00002630 if ((flags & SigmaValue) == 0)
2631 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00002632 if ((flags & PercentValue) != 0)
2633 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002634 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002635 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002636 _exception);
anthony805a2d42011-09-25 08:25:12 +00002637 break;
2638 }
anthonyafa3dfc2012-03-03 11:31:30 +00002639 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002640 {
cristya19f1d72012-08-07 18:24:38 +00002641 double
anthony805a2d42011-09-25 08:25:12 +00002642 black_point,
2643 gamma,
2644 white_point;
2645
2646 MagickStatusType
2647 flags;
2648
anthonyfd706f92012-01-19 04:22:02 +00002649 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002650 if ((flags & RhoValue) == 0)
2651 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002652 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002653 white_point=(double) QuantumRange;
anthony805a2d42011-09-25 08:25:12 +00002654 if ((flags & SigmaValue) != 0)
2655 white_point=geometry_info.sigma;
2656 gamma=1.0;
2657 if ((flags & XiValue) != 0)
2658 gamma=geometry_info.xi;
2659 if ((flags & PercentValue) != 0)
2660 {
cristya19f1d72012-08-07 18:24:38 +00002661 black_point*=(double) (QuantumRange/100.0);
2662 white_point*=(double) (QuantumRange/100.0);
anthony805a2d42011-09-25 08:25:12 +00002663 }
2664 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002665 white_point=(double) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002666 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002667 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002668 else
anthony92c93bd2012-03-19 14:02:47 +00002669 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002670 break;
2671 }
anthonyafa3dfc2012-03-03 11:31:30 +00002672 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002673 {
2674 char
cristy151b66d2015-04-15 10:50:31 +00002675 token[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00002676
2677 const char
2678 *p;
2679
2680 PixelInfo
2681 black_point,
2682 white_point;
2683
anthonyfd706f92012-01-19 04:22:02 +00002684 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002685 GetMagickToken(p,&p,token); /* get black point color */
2686 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002687 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002688 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002689 else
cristy269c9412011-10-13 23:41:15 +00002690 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002691 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002692 if (isalpha((int) token[0]) || (token[0] == '#'))
2693 GetMagickToken(p,&p,token);
2694 if (*token == '\0')
2695 white_point=black_point; /* set everything to that color */
2696 else
2697 {
2698 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2699 GetMagickToken(p,&p,token); /* Get white point color. */
2700 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002701 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002702 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002703 else
cristy269c9412011-10-13 23:41:15 +00002704 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002705 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002706 }
anthony92c93bd2012-03-19 14:02:47 +00002707 (void) LevelImageColors(_image,&black_point,&white_point,
anthonya322a832013-04-27 06:28:03 +00002708 IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002709 break;
2710 }
anthonyafa3dfc2012-03-03 11:31:30 +00002711 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002712 {
2713 double
2714 black_point,
2715 white_point;
2716
2717 MagickStatusType
2718 flags;
2719
anthonyfd706f92012-01-19 04:22:02 +00002720 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002721 if ((flags & RhoValue) == 0)
2722 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002723 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002724 white_point=(double) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002725 if ((flags & SigmaValue) != 0)
2726 white_point=geometry_info.sigma;
2727 if ((flags & PercentValue) != 0)
2728 {
anthony92c93bd2012-03-19 14:02:47 +00002729 black_point*=(double) _image->columns*_image->rows/100.0;
2730 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002731 }
2732 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002733 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002734 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002735 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002736 break;
2737 }
anthonyafa3dfc2012-03-03 11:31:30 +00002738 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002739 {
anthonyfe1aa782012-03-24 13:43:04 +00002740 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002741 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002742 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002743 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002744 if ((flags & XValue) == 0)
2745 geometry.x=1;
2746 if ((flags & YValue) == 0)
2747 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002748 new_image=LiquidRescaleImage(_image,geometry.width,
2749 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002750 break;
2751 }
anthonyebb73a22012-03-22 14:25:52 +00002752 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002753 }
2754 case 'm':
2755 {
cristy7220ee42013-04-14 01:30:34 +00002756 if (LocaleCompare("magnify",option+1) == 0)
2757 {
2758 new_image=MagnifyImage(_image,_exception);
2759 break;
2760 }
anthonyafa3dfc2012-03-03 11:31:30 +00002761 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002762 {
anthony464f1c42012-04-22 08:51:01 +00002763 CLIWandWarnReplaced("-remap");
cristy52b632a2014-11-08 00:31:34 +00002764 (void) CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002765 break;
2766 }
anthonyafa3dfc2012-03-03 11:31:30 +00002767 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002768 {
anthony4837ac22012-05-18 23:39:48 +00002769 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002770 Image
2771 *mask;
2772
anthonyafa3dfc2012-03-03 11:31:30 +00002773 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002774 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002775 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002776 break;
2777 }
anthony5330ae02012-03-20 14:17:01 +00002778 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002779 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002780 if (mask == (Image *) NULL)
2781 break;
anthony92c93bd2012-03-19 14:02:47 +00002782 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002783 mask=DestroyImage(mask);
2784 break;
2785 }
cristy52ad9e92013-02-08 23:23:29 +00002786 if (LocaleCompare("matte",option+1) == 0)
2787 {
2788 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2789 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
cristy1309fc32014-04-26 18:48:37 +00002790 DeactivateAlphaChannel, _exception);
cristy52ad9e92013-02-08 23:23:29 +00002791 break;
2792 }
cristy2fc10e52014-04-26 14:13:53 +00002793 if (LocaleCompare("mean-shift",option+1) == 0)
2794 {
2795 flags=ParseGeometry(arg1,&geometry_info);
2796 if ((flags & (RhoValue|SigmaValue)) == 0)
2797 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2798 if ((flags & SigmaValue) == 0)
2799 geometry_info.sigma=1.0;
2800 if ((flags & XiValue) == 0)
cristy1309fc32014-04-26 18:48:37 +00002801 geometry_info.xi=0.10*QuantumRange;
2802 if ((flags & PercentValue) != 0)
2803 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2804 new_image=MeanShiftImage(_image,(size_t) geometry_info.rho,
2805 (size_t) geometry_info.sigma,geometry_info.xi,_exception);
cristy2fc10e52014-04-26 14:13:53 +00002806 break;
2807 }
cristy52ad9e92013-02-08 23:23:29 +00002808 if (LocaleCompare("median",option+1) == 0)
2809 {
2810 CLIWandWarnReplaced("-statistic Median");
cristy52b632a2014-11-08 00:31:34 +00002811 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1,exception);
cristy52ad9e92013-02-08 23:23:29 +00002812 break;
2813 }
2814 if (LocaleCompare("mode",option+1) == 0)
2815 {
2816 /* FUTURE: note this is also a special "montage" option */
2817 CLIWandWarnReplaced("-statistic Mode");
cristy52b632a2014-11-08 00:31:34 +00002818 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1,exception);
cristy52ad9e92013-02-08 23:23:29 +00002819 break;
2820 }
anthonyafa3dfc2012-03-03 11:31:30 +00002821 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002822 {
anthony7bcfe7f2012-03-30 14:01:22 +00002823 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002824 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002825 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002826 break;
2827 }
anthonyafa3dfc2012-03-03 11:31:30 +00002828 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002829 {
anthony92c93bd2012-03-19 14:02:47 +00002830 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002831 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002832 break;
2833 }
anthonyafa3dfc2012-03-03 11:31:30 +00002834 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002835 {
anthony92c93bd2012-03-19 14:02:47 +00002836 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002837 break;
2838 }
anthonyafa3dfc2012-03-03 11:31:30 +00002839 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002840 {
2841 char
cristy151b66d2015-04-15 10:50:31 +00002842 token[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00002843
2844 const char
2845 *p;
2846
2847 KernelInfo
2848 *kernel;
2849
anthony805a2d42011-09-25 08:25:12 +00002850 ssize_t
2851 iterations;
2852
anthonyfd706f92012-01-19 04:22:02 +00002853 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002854 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002855 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2856 if ( parse < 0 )
cristy2c57b742014-10-31 00:40:34 +00002857 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",option,
2858 arg1);
anthony805a2d42011-09-25 08:25:12 +00002859 iterations=1L;
2860 GetMagickToken(p,&p,token);
2861 if ((*p == ':') || (*p == ','))
2862 GetMagickToken(p,&p,token);
2863 if ((*p != '\0'))
2864 iterations=(ssize_t) StringToLong(p);
cristy2c57b742014-10-31 00:40:34 +00002865 kernel=AcquireKernelInfo(arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00002866 if (kernel == (KernelInfo *) NULL)
cristy2c57b742014-10-31 00:40:34 +00002867 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",option,arg2);
2868 new_image=MorphologyImage(_image,(MorphologyMethod)parse,iterations,
2869 kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002870 kernel=DestroyKernelInfo(kernel);
2871 break;
2872 }
anthonyafa3dfc2012-03-03 11:31:30 +00002873 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002874 {
anthonyfd706f92012-01-19 04:22:02 +00002875 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002876 if ((flags & (RhoValue|SigmaValue)) == 0)
2877 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002878 if ((flags & SigmaValue) == 0)
2879 geometry_info.sigma=1.0;
cristy2c57b742014-10-31 00:40:34 +00002880 new_image=MotionBlurImage(_image,geometry_info.rho,geometry_info.sigma,
2881 geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002882 break;
2883 }
anthonyebb73a22012-03-22 14:25:52 +00002884 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002885 }
2886 case 'n':
2887 {
anthonyafa3dfc2012-03-03 11:31:30 +00002888 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002889 {
anthonya322a832013-04-27 06:28:03 +00002890 (void) NegateImage(_image, IsPlusOp, _exception);
anthony805a2d42011-09-25 08:25:12 +00002891 break;
2892 }
anthonyafa3dfc2012-03-03 11:31:30 +00002893 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002894 {
anthony975a8d72012-04-12 13:54:36 +00002895 double
2896 attenuate;
2897
2898 const char*
2899 value;
2900
anthonyafa3dfc2012-03-03 11:31:30 +00002901 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002902 {
anthony464f1c42012-04-22 08:51:01 +00002903 CLIWandWarnReplaced("-statistic NonPeak");
cristy52b632a2014-11-08 00:31:34 +00002904 (void) CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1,exception);
anthony975a8d72012-04-12 13:54:36 +00002905 break;
anthony805a2d42011-09-25 08:25:12 +00002906 }
anthony975a8d72012-04-12 13:54:36 +00002907 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2908 if ( parse < 0 )
2909 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2910 option,arg1);
2911 attenuate=1.0;
2912 value=GetImageOption(_image_info,"attenuate");
2913 if (value != (const char *) NULL)
2914 attenuate=StringToDouble(value,(char **) NULL);
2915 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2916 _exception);
anthony805a2d42011-09-25 08:25:12 +00002917 break;
2918 }
anthonyafa3dfc2012-03-03 11:31:30 +00002919 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002920 {
anthony92c93bd2012-03-19 14:02:47 +00002921 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002922 break;
2923 }
anthonyebb73a22012-03-22 14:25:52 +00002924 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002925 }
2926 case 'o':
2927 {
anthonyafa3dfc2012-03-03 11:31:30 +00002928 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002929 {
2930 PixelInfo
2931 target;
2932
anthony92c93bd2012-03-19 14:02:47 +00002933 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
anthonya322a832013-04-27 06:28:03 +00002934 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,IsPlusOp,
anthony92c93bd2012-03-19 14:02:47 +00002935 _exception);
anthony805a2d42011-09-25 08:25:12 +00002936 break;
2937 }
anthonyafa3dfc2012-03-03 11:31:30 +00002938 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002939 {
anthony92c93bd2012-03-19 14:02:47 +00002940 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002941 break;
2942 }
anthonyebb73a22012-03-22 14:25:52 +00002943 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002944 }
2945 case 'p':
2946 {
anthonyafa3dfc2012-03-03 11:31:30 +00002947 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002948 {
anthony22de2722012-04-19 14:43:00 +00002949 flags=ParseGeometry(arg1,&geometry_info);
2950 if ((flags & (RhoValue|SigmaValue)) == 0)
2951 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002952 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2953 _exception);
anthony805a2d42011-09-25 08:25:12 +00002954 break;
2955 }
cristy7884a932012-11-04 14:33:51 +00002956 if (LocaleCompare("perceptible",option+1) == 0)
2957 {
2958 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2959 _exception);
2960 break;
2961 }
anthonyafa3dfc2012-03-03 11:31:30 +00002962 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002963 {
cristye9e3d382011-12-14 01:50:13 +00002964 const char
2965 *caption;
2966
anthony805a2d42011-09-25 08:25:12 +00002967 double
2968 angle;
2969
anthony7bc87992012-03-25 02:32:51 +00002970 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002971 RandomInfo
cristy2c57b742014-10-31 00:40:34 +00002972 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002973
anthonyf42014d2012-03-25 09:53:06 +00002974 random_info=AcquireRandomInfo();
2975 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2976 random_info=DestroyRandomInfo(random_info);
2977 }
anthony7bc87992012-03-25 02:32:51 +00002978 else {
anthonyf42014d2012-03-25 09:53:06 +00002979 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002980 if ((flags & RhoValue) == 0)
2981 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002982 angle=geometry_info.rho;
2983 }
anthony92c93bd2012-03-19 14:02:47 +00002984 caption=GetImageProperty(_image,"caption",_exception);
2985 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2986 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002987 break;
2988 }
anthonyafa3dfc2012-03-03 11:31:30 +00002989 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002990 {
anthony22de2722012-04-19 14:43:00 +00002991 flags=ParseGeometry(arg1,&geometry_info);
2992 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002993 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002994 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002995 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002996 break;
2997 }
anthonyafa3dfc2012-03-03 11:31:30 +00002998 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002999 {
anthony31f1bf72012-01-30 12:37:22 +00003000 /* FUTURE: should be a 'Genesis' option?
3001 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00003002 Why???
cristy947cb4c2011-10-20 18:41:46 +00003003 */
anthony7bc87992012-03-25 02:32:51 +00003004 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
3005 if ( parse < 0 )
3006 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
3007 option,arg1);
3008 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003009 break;
3010 }
anthonyafa3dfc2012-03-03 11:31:30 +00003011 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003012 {
anthony4837ac22012-05-18 23:39:48 +00003013 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00003014 const char
3015 *name;
3016
3017 const StringInfo
3018 *profile;
3019
3020 Image
3021 *profile_image;
3022
3023 ImageInfo
3024 *profile_info;
3025
anthonyafa3dfc2012-03-03 11:31:30 +00003026 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003027 { /* Remove a profile from the _image. */
3028 (void) ProfileImage(_image,arg1,(const unsigned char *)
3029 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003030 break;
3031 }
anthony92c93bd2012-03-19 14:02:47 +00003032 /* Associate a profile with the _image. */
3033 profile_info=CloneImageInfo(_image_info);
3034 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003035 if (profile != (StringInfo *) NULL)
3036 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003037 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003038 profile_info=DestroyImageInfo(profile_info);
3039 if (profile_image == (Image *) NULL)
3040 {
3041 StringInfo
3042 *profile;
3043
anthony92c93bd2012-03-19 14:02:47 +00003044 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003045 (void) CopyMagickString(profile_info->filename,arg1,
cristy151b66d2015-04-15 10:50:31 +00003046 MagickPathExtent);
anthony92c93bd2012-03-19 14:02:47 +00003047 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003048 if (profile != (StringInfo *) NULL)
3049 {
anthony92c93bd2012-03-19 14:02:47 +00003050 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003051 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003052 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003053 profile=DestroyStringInfo(profile);
3054 }
3055 profile_info=DestroyImageInfo(profile_info);
3056 break;
3057 }
3058 ResetImageProfileIterator(profile_image);
3059 name=GetNextImageProfile(profile_image);
3060 while (name != (const char *) NULL)
3061 {
3062 profile=GetImageProfile(profile_image,name);
3063 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003064 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3065 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003066 name=GetNextImageProfile(profile_image);
3067 }
3068 profile_image=DestroyImage(profile_image);
3069 break;
3070 }
anthonyebb73a22012-03-22 14:25:52 +00003071 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003072 }
anthony805a2d42011-09-25 08:25:12 +00003073 case 'r':
3074 {
dirk6d612cf2014-03-13 21:17:23 +00003075 if (LocaleCompare("rotational-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003076 {
anthonyfd706f92012-01-19 04:22:02 +00003077 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003078 if ((flags & RhoValue) == 0)
3079 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
dirk6d612cf2014-03-13 21:17:23 +00003080 new_image=RotationalBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003081 break;
3082 }
anthonyafa3dfc2012-03-03 11:31:30 +00003083 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003084 {
anthony7bcfe7f2012-03-30 14:01:22 +00003085 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003086 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003087 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthonya322a832013-04-27 06:28:03 +00003088 (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003089 break;
3090 }
anthonyafa3dfc2012-03-03 11:31:30 +00003091 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003092 {
anthony7bcfe7f2012-03-30 14:01:22 +00003093 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003094 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003095 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003096 break;
3097 }
anthony975a8d72012-04-12 13:54:36 +00003098 if (LocaleCompare("recolor",option+1) == 0)
3099 {
anthony464f1c42012-04-22 08:51:01 +00003100 CLIWandWarnReplaced("-color-matrix");
cristy52b632a2014-11-08 00:31:34 +00003101 (void) CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL,exception);
anthony975a8d72012-04-12 13:54:36 +00003102 }
anthonyafa3dfc2012-03-03 11:31:30 +00003103 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003104 {
anthony4837ac22012-05-18 23:39:48 +00003105 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00003106 Image
3107 *remap_image;
3108
anthony92c93bd2012-03-19 14:02:47 +00003109 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003110 if (remap_image == (Image *) NULL)
3111 break;
anthony92c93bd2012-03-19 14:02:47 +00003112 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003113 remap_image=DestroyImage(remap_image);
3114 break;
3115 }
anthonyafa3dfc2012-03-03 11:31:30 +00003116 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003117 {
anthonyafa3dfc2012-03-03 11:31:30 +00003118 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003119 {
anthony7bcfe7f2012-03-30 14:01:22 +00003120 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00003121 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3122 arg1);
3123 (void) ResetImagePage(_image,arg1);
3124 }
anthony31f1bf72012-01-30 12:37:22 +00003125 else
anthony92c93bd2012-03-19 14:02:47 +00003126 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003127 break;
3128 }
anthonyafa3dfc2012-03-03 11:31:30 +00003129 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003130 {
anthonyf46d4262012-03-26 03:30:34 +00003131 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00003132 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003133 if ((flags & (RhoValue|SigmaValue)) == 0)
3134 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003135 if ((flags & SigmaValue) == 0)
3136 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003137 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003138 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003139 break;
3140 }
anthonyafa3dfc2012-03-03 11:31:30 +00003141 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003142 {
anthony7bcfe7f2012-03-30 14:01:22 +00003143 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003144 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003145 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3146 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003147 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003148 break;
3149 }
anthonyafa3dfc2012-03-03 11:31:30 +00003150 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003151 {
anthony7bcfe7f2012-03-30 14:01:22 +00003152 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003153 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003154 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3155 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003156 break;
3157 }
anthonyafa3dfc2012-03-03 11:31:30 +00003158 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003159 {
anthony22de2722012-04-19 14:43:00 +00003160 flags=ParseGeometry(arg1,&geometry_info);
3161 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003162 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003163 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003164 break;
3165 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3166 break;
anthony92c93bd2012-03-19 14:02:47 +00003167 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003168 break;
3169 }
anthonyebb73a22012-03-22 14:25:52 +00003170 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003171 }
3172 case 's':
3173 {
anthonyafa3dfc2012-03-03 11:31:30 +00003174 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003175 {
anthonyfe1aa782012-03-24 13:43:04 +00003176 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003177 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003178 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003179 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3180 new_image=SampleImage(_image,geometry.width,geometry.height,
3181 _exception);
anthony805a2d42011-09-25 08:25:12 +00003182 break;
3183 }
anthonyafa3dfc2012-03-03 11:31:30 +00003184 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003185 {
anthonyfe1aa782012-03-24 13:43:04 +00003186 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003187 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003188 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003189 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3190 new_image=ScaleImage(_image,geometry.width,geometry.height,
3191 _exception);
anthony805a2d42011-09-25 08:25:12 +00003192 break;
3193 }
anthonyf42014d2012-03-25 09:53:06 +00003194 if (LocaleCompare("segment",option+1) == 0)
3195 {
anthonyf42014d2012-03-25 09:53:06 +00003196 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003197 if ((flags & (RhoValue|SigmaValue)) == 0)
3198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003199 if ((flags & SigmaValue) == 0)
3200 geometry_info.sigma=1.0;
3201 (void) SegmentImage(_image,_image->colorspace,
3202 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3203 _exception);
3204 break;
3205 }
anthonyafa3dfc2012-03-03 11:31:30 +00003206 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003207 {
anthonyfd706f92012-01-19 04:22:02 +00003208 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003209 if ((flags & (RhoValue|SigmaValue)) == 0)
3210 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3211 if ((flags & SigmaValue) == 0)
3212 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003213 if ((flags & PercentValue) != 0)
3214 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003215 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003216 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003217 break;
3218 }
anthonyafa3dfc2012-03-03 11:31:30 +00003219 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003220 {
anthony31f1bf72012-01-30 12:37:22 +00003221 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003222 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003223 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003224 break;
3225 }
anthonyafa3dfc2012-03-03 11:31:30 +00003226 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003227 {
anthony7bcfe7f2012-03-30 14:01:22 +00003228 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003229 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3230 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3231 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003232 break;
3233 }
anthonyafa3dfc2012-03-03 11:31:30 +00003234 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003235 {
anthonyfd706f92012-01-19 04:22:02 +00003236 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003237 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3238 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya322a832013-04-27 06:28:03 +00003239 new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
anthony92c93bd2012-03-19 14:02:47 +00003240 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003241 break;
3242 }
anthonyafa3dfc2012-03-03 11:31:30 +00003243 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003244 {
anthonyfd706f92012-01-19 04:22:02 +00003245 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003246 if ((flags & (RhoValue|SigmaValue)) == 0)
3247 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003248 if ((flags & SigmaValue) == 0)
3249 geometry_info.sigma=1.0;
3250 if ((flags & XiValue) == 0)
3251 geometry_info.xi=4.0;
3252 if ((flags & PsiValue) == 0)
3253 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003254 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3255 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3256 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003257 break;
3258 }
anthonyafa3dfc2012-03-03 11:31:30 +00003259 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003260 {
anthonyfd706f92012-01-19 04:22:02 +00003261 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003262 if ((flags & (RhoValue|SigmaValue)) == 0)
3263 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003264 if ((flags & SigmaValue) == 0)
3265 geometry_info.sigma=1.0;
3266 if ((flags & XiValue) == 0)
3267 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003268 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3269 _exception);
anthony805a2d42011-09-25 08:25:12 +00003270 break;
3271 }
anthonyafa3dfc2012-03-03 11:31:30 +00003272 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003273 {
anthony7bcfe7f2012-03-30 14:01:22 +00003274 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003275 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003276 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3277 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003278 break;
3279 }
anthonyafa3dfc2012-03-03 11:31:30 +00003280 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003281 {
anthonyfd706f92012-01-19 04:22:02 +00003282 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003283 if ((flags & RhoValue) == 0)
3284 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003285 if ((flags & SigmaValue) == 0)
3286 geometry_info.sigma=geometry_info.rho;
cristy4b892612012-08-03 19:31:31 +00003287 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3288 _exception);
anthony805a2d42011-09-25 08:25:12 +00003289 break;
3290 }
anthonyafa3dfc2012-03-03 11:31:30 +00003291 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003292 {
anthonyfd706f92012-01-19 04:22:02 +00003293 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003294 if ((flags & RhoValue) == 0)
3295 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003296 if ((flags & SigmaValue) == 0)
3297 geometry_info.sigma=(double) QuantumRange/2.0;
3298 if ((flags & PercentValue) != 0)
3299 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3300 100.0;
anthonya322a832013-04-27 06:28:03 +00003301 (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003302 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003303 break;
3304 }
anthonyafa3dfc2012-03-03 11:31:30 +00003305 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003306 {
anthonyfd706f92012-01-19 04:22:02 +00003307 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003308 if ((flags & (RhoValue|SigmaValue)) == 0)
3309 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003310 if ((flags & SigmaValue) == 0)
3311 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003312 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003313 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003314 break;
3315 }
anthonyafa3dfc2012-03-03 11:31:30 +00003316 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003317 {
anthony7bcfe7f2012-03-30 14:01:22 +00003318 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003319 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003320 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3321 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003322 break;
3323 }
anthonyafa3dfc2012-03-03 11:31:30 +00003324 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003325 {
anthonyf42014d2012-03-25 09:53:06 +00003326 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3327 if ( parse < 0 )
3328 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3329 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003330 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3331 _exception);
anthony805a2d42011-09-25 08:25:12 +00003332 break;
3333 }
anthonyafa3dfc2012-03-03 11:31:30 +00003334 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003335 {
anthony7bcfe7f2012-03-30 14:01:22 +00003336 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003337 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003338 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003339 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003340 break;
3341 }
anthonyafa3dfc2012-03-03 11:31:30 +00003342 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003343 {
anthonyb1e21ed2012-04-20 12:43:12 +00003344 flags=ParseGeometry(arg1,&geometry_info);
3345 if ((flags & RhoValue) == 0)
3346 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003347 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3348 _exception);
anthony805a2d42011-09-25 08:25:12 +00003349 break;
3350 }
anthonyafa3dfc2012-03-03 11:31:30 +00003351 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003352 {
anthony7bc87992012-03-25 02:32:51 +00003353 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3354 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003355 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003356 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003357 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003358 if ((flags & RhoValue) == 0)
3359 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003360 if ((flags & SigmaValue) == 0)
3361 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003362 new_image=StatisticImage(_image,(StatisticType)parse,
3363 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3364 _exception);
anthony805a2d42011-09-25 08:25:12 +00003365 break;
3366 }
anthonyafa3dfc2012-03-03 11:31:30 +00003367 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003368 {
anthony92c93bd2012-03-19 14:02:47 +00003369 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003370 break;
3371 }
anthonyafa3dfc2012-03-03 11:31:30 +00003372 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003373 {
cristy898c6042012-06-24 00:36:34 +00003374 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00003375 if ((flags & RhoValue) == 0)
cristy898c6042012-06-24 00:36:34 +00003376 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003377 new_image=SwirlImage(_image,geometry_info.rho,
3378 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003379 break;
3380 }
anthonyebb73a22012-03-22 14:25:52 +00003381 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003382 }
3383 case 't':
3384 {
anthonyafa3dfc2012-03-03 11:31:30 +00003385 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003386 {
3387 double
3388 threshold;
3389
anthony52bef752012-03-27 13:54:47 +00003390 threshold=(double) QuantumRange/2;
anthonya322a832013-04-27 06:28:03 +00003391 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00003392 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003393 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003394 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003395 }
anthony92c93bd2012-03-19 14:02:47 +00003396 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003397 break;
3398 }
anthonyafa3dfc2012-03-03 11:31:30 +00003399 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003400 {
anthony7bcfe7f2012-03-30 14:01:22 +00003401 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003402 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003403 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3404 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3405 _exception);
anthony805a2d42011-09-25 08:25:12 +00003406 break;
3407 }
anthonyafa3dfc2012-03-03 11:31:30 +00003408 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003409 {
anthony7bcfe7f2012-03-30 14:01:22 +00003410 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003411 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003412 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003413 break;
3414 }
anthonyafa3dfc2012-03-03 11:31:30 +00003415 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003416 {
anthony464f1c42012-04-22 08:51:01 +00003417 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003418 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003419 break;
3420 }
anthonyafa3dfc2012-03-03 11:31:30 +00003421 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003422 {
3423 PixelInfo
3424 target;
3425
anthony92c93bd2012-03-19 14:02:47 +00003426 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3427 (void) TransparentPaintImage(_image,&target,(Quantum)
anthonya322a832013-04-27 06:28:03 +00003428 TransparentAlpha,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003429 break;
3430 }
anthonyafa3dfc2012-03-03 11:31:30 +00003431 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003432 {
anthony92c93bd2012-03-19 14:02:47 +00003433 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003434 break;
3435 }
anthonyafa3dfc2012-03-03 11:31:30 +00003436 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003437 {
anthony92c93bd2012-03-19 14:02:47 +00003438 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003439 break;
3440 }
anthonyafa3dfc2012-03-03 11:31:30 +00003441 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003442 {
anthony92c93bd2012-03-19 14:02:47 +00003443 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003444 break;
3445 }
anthonyafa3dfc2012-03-03 11:31:30 +00003446 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003447 {
anthonyab3a50c2011-10-27 11:48:57 +00003448 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003449 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003450 break;
3451 }
anthonyebb73a22012-03-22 14:25:52 +00003452 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003453 }
3454 case 'u':
3455 {
anthonyafa3dfc2012-03-03 11:31:30 +00003456 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003457 {
anthony52bef752012-03-27 13:54:47 +00003458 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3459 Option is not documented, bt appears to be for "identify".
3460 We may need a identify specific verbose!
3461 */
anthonya322a832013-04-27 06:28:03 +00003462 if (IsPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00003463 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003464 break;
3465 }
anthony92c93bd2012-03-19 14:02:47 +00003466 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3467 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003468 break;
3469 }
anthonyafa3dfc2012-03-03 11:31:30 +00003470 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003471 {
anthony92c93bd2012-03-19 14:02:47 +00003472 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003473 break;
3474 }
anthonyafa3dfc2012-03-03 11:31:30 +00003475 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003476 {
anthonyfd706f92012-01-19 04:22:02 +00003477 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003478 if ((flags & (RhoValue|SigmaValue)) == 0)
3479 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003480 if ((flags & SigmaValue) == 0)
3481 geometry_info.sigma=1.0;
3482 if ((flags & XiValue) == 0)
3483 geometry_info.xi=1.0;
3484 if ((flags & PsiValue) == 0)
3485 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003486 new_image=UnsharpMaskImage(_image,geometry_info.rho,
cristy3afd4012013-03-25 11:30:44 +00003487 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003488 break;
3489 }
anthonyebb73a22012-03-22 14:25:52 +00003490 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003491 }
3492 case 'v':
3493 {
anthonyafa3dfc2012-03-03 11:31:30 +00003494 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003495 {
anthonyafa3dfc2012-03-03 11:31:30 +00003496 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003497 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003498 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003499 */
anthony92c93bd2012-03-19 14:02:47 +00003500 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003501 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003502 break;
3503 }
anthonyafa3dfc2012-03-03 11:31:30 +00003504 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003505 {
anthonyfd706f92012-01-19 04:22:02 +00003506 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003507 if ((flags & (RhoValue|SigmaValue)) == 0)
3508 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003509 if ((flags & SigmaValue) == 0)
3510 geometry_info.sigma=1.0;
3511 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003512 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003513 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003514 geometry_info.psi=0.1*_image->rows;
cristy8e2392e2013-11-11 17:58:38 +00003515 if ((flags & PercentValue) != 0)
3516 {
cristy720d7562013-11-14 19:18:11 +00003517 geometry_info.xi*=(double) _image->columns/100.0;
3518 geometry_info.psi*=(double) _image->rows/100.0;
cristy8e2392e2013-11-11 17:58:38 +00003519 }
anthony92c93bd2012-03-19 14:02:47 +00003520 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003521 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3522 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003523 break;
3524 }
anthonyebb73a22012-03-22 14:25:52 +00003525 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003526 }
3527 case 'w':
3528 {
anthonyafa3dfc2012-03-03 11:31:30 +00003529 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003530 {
anthonyfd706f92012-01-19 04:22:02 +00003531 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003532 if ((flags & (RhoValue|SigmaValue)) == 0)
3533 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003534 if ((flags & SigmaValue) == 0)
3535 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003536 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3537 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003538 break;
3539 }
anthonyafa3dfc2012-03-03 11:31:30 +00003540 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003541 {
anthony7bcfe7f2012-03-30 14:01:22 +00003542 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003543 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003544 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003545 break;
3546 }
anthonyebb73a22012-03-22 14:25:52 +00003547 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003548 }
3549 default:
anthonyebb73a22012-03-22 14:25:52 +00003550 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003551 }
anthony964d28e2012-05-17 23:39:46 +00003552 /* clean up percent escape interpreted strings */
3553 if (arg1 != arg1n )
3554 arg1=DestroyString((char *)arg1);
3555 if (arg2 != arg2n )
3556 arg2=DestroyString((char *)arg2);
3557
3558 /* Replace current image with any image that was generated
3559 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003560 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003561 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003562
cristyfe831852013-02-12 14:56:07 +00003563 return(MagickTrue);
anthony92c93bd2012-03-19 14:02:47 +00003564#undef _image_info
3565#undef _draw_info
3566#undef _quantize_info
3567#undef _image
3568#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003569#undef IfNormalOp
3570#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00003571#undef IsNormalOp
3572#undef IsPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003573}
anthonyfd706f92012-01-19 04:22:02 +00003574
cristyfe831852013-02-12 14:56:07 +00003575WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
cristy2c57b742014-10-31 00:40:34 +00003576 const char *option,const char *arg1,const char *arg2,ExceptionInfo *exception)
anthony31f1bf72012-01-30 12:37:22 +00003577{
anthonyc7994672012-11-17 05:33:27 +00003578#if !USE_WAND_METHODS
anthony31f1bf72012-01-30 12:37:22 +00003579 size_t
anthony43f425d2012-02-26 12:58:58 +00003580 n,
anthony31f1bf72012-01-30 12:37:22 +00003581 i;
anthonyc7994672012-11-17 05:33:27 +00003582#endif
anthony31f1bf72012-01-30 12:37:22 +00003583
anthony43f425d2012-02-26 12:58:58 +00003584 assert(cli_wand != (MagickCLI *) NULL);
3585 assert(cli_wand->signature == WandSignature);
3586 assert(cli_wand->wand.signature == WandSignature);
3587 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthonya322a832013-04-27 06:28:03 +00003588
anthony7bcfe7f2012-03-30 14:01:22 +00003589 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00003590 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3591 "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
anthony31f1bf72012-01-30 12:37:22 +00003592
anthonyafa3dfc2012-03-03 11:31:30 +00003593#if !USE_WAND_METHODS
3594 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003595 i=0;
anthony43f425d2012-02-26 12:58:58 +00003596 n=GetImageListLength(cli_wand->wand.images);
3597 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003598 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003599 i++;
cristy2c57b742014-10-31 00:40:34 +00003600 CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
anthony43f425d2012-02-26 12:58:58 +00003601 if ( cli_wand->wand.images->next == (Image *) NULL )
3602 break;
3603 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003604 }
anthony43f425d2012-02-26 12:58:58 +00003605 assert( i == n );
3606 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003607#else
3608 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003609 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
cristy52b632a2014-11-08 00:31:34 +00003610 (void) CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003611 MagickResetIterator(&cli_wand->wand);
3612#endif
cristyfe831852013-02-12 14:56:07 +00003613 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003614}
3615
3616/*
3617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3618% %
3619% %
3620% %
anthony43f425d2012-02-26 12:58:58 +00003621+ 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 +00003622% %
3623% %
3624% %
3625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3626%
anthony43f425d2012-02-26 12:58:58 +00003627% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003628% entire image list as a whole. The result is often a complete replacment
anthonyc7994672012-11-17 05:33:27 +00003629% of the image list with a completely new list, or with just a single image
3630% result.
anthony805a2d42011-09-25 08:25:12 +00003631%
3632% The format of the MogrifyImage method is:
3633%
cristyfe831852013-02-12 14:56:07 +00003634% MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3635% const char *option,const char *arg1,const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003636%
3637% A description of each parameter follows:
3638%
anthony43f425d2012-02-26 12:58:58 +00003639% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003640%
anthony36a8c2c2012-02-10 00:08:44 +00003641% o option: The option string for the operation
3642%
anthony31f1bf72012-01-30 12:37:22 +00003643% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003644% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003645%
anthony805a2d42011-09-25 08:25:12 +00003646*/
cristyfe831852013-02-12 14:56:07 +00003647WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3648 const char *option,const char *arg1n,const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003649{
anthonya322a832013-04-27 06:28:03 +00003650 const char /* percent escaped versions of the args */
cristya30f8e62013-02-19 15:03:45 +00003651 *arg1,
3652 *arg2;
anthony2a0ec8c2012-03-24 04:35:56 +00003653
anthony31f1bf72012-01-30 12:37:22 +00003654 Image
3655 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003656
cristya30f8e62013-02-19 15:03:45 +00003657 MagickStatusType
3658 status;
3659
3660 ssize_t
3661 parse;
anthony964d28e2012-05-17 23:39:46 +00003662
anthony2e4501b2012-03-30 04:41:54 +00003663#define _image_info (cli_wand->wand.image_info)
3664#define _images (cli_wand->wand.images)
3665#define _exception (cli_wand->wand.exception)
3666#define _draw_info (cli_wand->draw_info)
3667#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003668#define _process_flags (cli_wand->process_flags)
3669#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003670#define IfNormalOp (*option=='-')
3671#define IfPlusOp (*option!='-')
anthonya322a832013-04-27 06:28:03 +00003672#define IsNormalOp IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003673
anthony43f425d2012-02-26 12:58:58 +00003674 assert(cli_wand != (MagickCLI *) NULL);
3675 assert(cli_wand->signature == WandSignature);
3676 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003677 assert(_images != (Image *) NULL); /* _images must be present */
anthony31f1bf72012-01-30 12:37:22 +00003678
anthonya322a832013-04-27 06:28:03 +00003679 if (IfMagickTrue(cli_wand->wand.debug))
3680 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3681 "- List Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
3682
anthony964d28e2012-05-17 23:39:46 +00003683 arg1 = arg1n;
3684 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00003685
3686 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00003687 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3688 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3689 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3690 /* Interpret Percent escapes in argument 1 */
3691 if (arg1n != (char *) NULL) {
3692 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3693 if (arg1 == (char *) NULL) {
3694 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3695 arg1=arg1n; /* use the given argument as is */
3696 }
3697 }
3698 if (arg2n != (char *) NULL) {
3699 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3700 if (arg2 == (char *) NULL) {
3701 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3702 arg2=arg2n; /* use the given argument as is */
3703 }
3704 }
3705 }
anthony4837ac22012-05-18 23:39:48 +00003706#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003707#undef _option_type
3708
cristyfe831852013-02-12 14:56:07 +00003709 status=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00003710 new_images=NewImageList();
3711
anthonyafa3dfc2012-03-03 11:31:30 +00003712 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003713 {
3714 case 'a':
3715 {
anthonyafa3dfc2012-03-03 11:31:30 +00003716 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003717 {
anthonya322a832013-04-27 06:28:03 +00003718 new_images=AppendImages(_images,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003719 break;
3720 }
cristy52ad9e92013-02-08 23:23:29 +00003721 if (LocaleCompare("average",option+1) == 0)
3722 {
3723 CLIWandWarnReplaced("-evaluate-sequence Mean");
cristy52b632a2014-11-08 00:31:34 +00003724 (void) CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
cristy52ad9e92013-02-08 23:23:29 +00003725 break;
3726 }
anthonyebb73a22012-03-22 14:25:52 +00003727 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003728 }
3729 case 'c':
3730 {
cristy5f257b22012-03-07 00:27:29 +00003731 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003732 {
anthony92c93bd2012-03-19 14:02:47 +00003733 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003734 break;
3735 }
anthonyafa3dfc2012-03-03 11:31:30 +00003736 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003737 {
anthony805a2d42011-09-25 08:25:12 +00003738 Image
anthony31f1bf72012-01-30 12:37:22 +00003739 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003740
anthonyafa3dfc2012-03-03 11:31:30 +00003741 /* FUTURE - make this a compose option, and thus can be used
3742 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003743 _images.
cristy87c02f42012-02-24 00:19:10 +00003744 */
anthony92c93bd2012-03-19 14:02:47 +00003745 new_images=RemoveFirstImageFromList(&_images);
3746 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003747 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003748 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003749 break;
cristyf68c0be2015-04-28 22:48:37 +00003750 (void) ClutImage(new_images,clut_image,new_images->interpolate,
3751 _exception);
anthony805a2d42011-09-25 08:25:12 +00003752 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003753 break;
3754 }
anthonyafa3dfc2012-03-03 11:31:30 +00003755 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003756 {
anthony92c93bd2012-03-19 14:02:47 +00003757 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003758 break;
3759 }
anthonyafa3dfc2012-03-03 11:31:30 +00003760 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003761 {
cristy9a0e8ef2015-05-11 23:20:15 +00003762 parse=(ssize_t) _images->colorspace;
anthony5a4ff372013-05-01 04:48:57 +00003763 if ( IfPlusOp )
cristyf68c0be2015-04-28 22:48:37 +00003764 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
cristy8448a0d2013-02-15 18:20:53 +00003765 if (parse < 0)
3766 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3767 arg1);
cristy46f354c2012-07-04 13:31:29 +00003768 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003769 break;
3770 }
cristye863c052013-09-04 11:31:30 +00003771 if (LocaleCompare("compare",option+1) == 0)
3772 {
3773 double
3774 distortion;
3775
3776 Image
3777 *image,
3778 *reconstruct_image;
3779
3780 MetricType
3781 metric;
3782
3783 /*
3784 Mathematically and visually annotate the difference between an
3785 image and its reconstruction.
3786 */
3787 image=RemoveFirstImageFromList(&_images);
3788 reconstruct_image=RemoveFirstImageFromList(&_images);
3789 /* FUTURE - produce Exception, rather than silent fail */
3790 if (reconstruct_image == (Image *) NULL)
3791 break;
3792 metric=UndefinedErrorMetric;
3793 option=GetImageOption(_image_info,"metric");
3794 if (option != (const char *) NULL)
3795 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
3796 MagickFalse,option);
3797 new_images=CompareImages(image,reconstruct_image,metric,&distortion,
3798 _exception);
3799 (void) distortion;
3800 reconstruct_image=DestroyImage(reconstruct_image);
3801 image=DestroyImage(image);
3802 break;
3803 }
cristy790190d2013-10-04 00:51:51 +00003804 if (LocaleCompare("complex",option+1) == 0)
3805 {
3806 parse=ParseCommandOption(MagickComplexOptions,MagickFalse,arg1);
3807 if (parse < 0)
3808 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3809 option,arg1);
cristyb8f66bb2013-10-04 15:21:58 +00003810 new_images=ComplexImages(_images,(ComplexOperator) parse,_exception);
cristy790190d2013-10-04 00:51:51 +00003811 break;
3812 }
anthonyafa3dfc2012-03-03 11:31:30 +00003813 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003814 {
cristyfeb3e962012-03-29 17:25:55 +00003815 CompositeOperator
3816 compose;
3817
3818 const char*
3819 value;
3820
3821 MagickBooleanType
3822 clip_to_self;
3823
anthony805a2d42011-09-25 08:25:12 +00003824 Image
3825 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003826 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003827
3828 RectangleInfo
3829 geometry;
3830
anthony7bcfe7f2012-03-30 14:01:22 +00003831 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003832 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003833 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003834 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003835 else
3836 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3837 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003838
anthony7bcfe7f2012-03-30 14:01:22 +00003839 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003840 value=GetImageOption(_image_info,"compose:clip-to-self");
3841 if (value == (const char *) NULL)
3842 clip_to_self=MagickTrue;
3843 else
3844 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3845 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003846 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003847 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003848 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003849 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003850 }
3851
anthony92c93bd2012-03-19 14:02:47 +00003852 new_images=RemoveFirstImageFromList(&_images);
3853 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003854 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003855 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003856
anthony31f1bf72012-01-30 12:37:22 +00003857 /* FUTURE - this should not be here! - should be part of -geometry */
3858 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003859 source_image->geometry,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003860 SetGeometry(source_image,&geometry);
3861 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3862 GravityAdjustGeometry(new_images->columns,new_images->rows,
cristyfe831852013-02-12 14:56:07 +00003863 new_images->gravity, &geometry);
anthony92c93bd2012-03-19 14:02:47 +00003864 mask_image=RemoveFirstImageFromList(&_images);
cristy052d1f72015-01-04 21:10:37 +00003865 if (mask_image == (Image *) NULL)
3866 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
3867 geometry.x,geometry.y,_exception);
3868 else
cristyfe831852013-02-12 14:56:07 +00003869 {
cristy052d1f72015-01-04 21:10:37 +00003870 if ((compose == DisplaceCompositeOp) ||
3871 (compose == DistortCompositeOp))
3872 {
3873 status&=CompositeImage(source_image,mask_image,
3874 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3875 status&=CompositeImage(new_images,source_image,compose,
3876 clip_to_self,geometry.x,geometry.y,_exception);
3877 }
cristyfae52a22014-11-27 21:49:03 +00003878 else
cristy052d1f72015-01-04 21:10:37 +00003879 {
3880 Image
3881 *clone_image;
3882
3883 clone_image=CloneImage(new_images,0,0,MagickTrue,_exception);
3884 if (clone_image == (Image *) NULL)
3885 break;
3886 status&=CompositeImage(new_images,source_image,compose,
3887 clip_to_self,geometry.x,geometry.y,_exception);
3888 status&=CompositeImage(new_images,mask_image,
3889 CopyAlphaCompositeOp,MagickTrue,0,0,_exception);
3890 status&=CompositeImage(clone_image,new_images,OverCompositeOp,
3891 clip_to_self,geometry.x,geometry.y,_exception);
3892 new_images=DestroyImage(new_images);
3893 new_images=clone_image;
3894 }
cristyfe831852013-02-12 14:56:07 +00003895 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003896 }
anthony31f1bf72012-01-30 12:37:22 +00003897 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003898 break;
3899 }
anthonyebb73a22012-03-22 14:25:52 +00003900 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003901 }
3902 case 'd':
3903 {
anthonyafa3dfc2012-03-03 11:31:30 +00003904 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003905 {
anthony464f1c42012-04-22 08:51:01 +00003906 CLIWandWarnReplaced("-layer CompareAny");
cristy52b632a2014-11-08 00:31:34 +00003907 (void) CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003908 break;
3909 }
anthonyafa3dfc2012-03-03 11:31:30 +00003910 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003911 {
anthonyafa3dfc2012-03-03 11:31:30 +00003912 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003913 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003914 else
anthony92c93bd2012-03-19 14:02:47 +00003915 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003916 break;
3917 }
anthonyafa3dfc2012-03-03 11:31:30 +00003918 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003919 {
anthonyafa3dfc2012-03-03 11:31:30 +00003920 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003921 {
3922 const char
3923 *p;
3924
3925 size_t
3926 number_duplicates;
3927
anthony7bcfe7f2012-03-30 14:01:22 +00003928 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003929 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3930 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003931 number_duplicates=(size_t) StringToLong(arg1);
3932 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003933 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003934 new_images=DuplicateImages(_images,number_duplicates,"-1",
3935 _exception);
anthony805a2d42011-09-25 08:25:12 +00003936 else
anthony92c93bd2012-03-19 14:02:47 +00003937 new_images=DuplicateImages(_images,number_duplicates,p,
3938 _exception);
anthony805a2d42011-09-25 08:25:12 +00003939 }
anthonyafa3dfc2012-03-03 11:31:30 +00003940 else
anthony92c93bd2012-03-19 14:02:47 +00003941 new_images=DuplicateImages(_images,1,"-1",_exception);
3942 AppendImageToList(&_images, new_images);
cristyf432c632014-12-07 15:11:28 +00003943 new_images=(Image *) NULL;
anthony805a2d42011-09-25 08:25:12 +00003944 break;
3945 }
anthonyebb73a22012-03-22 14:25:52 +00003946 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003947 }
3948 case 'e':
3949 {
anthonyafa3dfc2012-03-03 11:31:30 +00003950 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003951 {
cristy790190d2013-10-04 00:51:51 +00003952 parse=ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3953 if (parse < 0)
anthony2a0ec8c2012-03-24 04:35:56 +00003954 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
cristy790190d2013-10-04 00:51:51 +00003955 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00003956 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
cristy790190d2013-10-04 00:51:51 +00003957 _exception);
anthony805a2d42011-09-25 08:25:12 +00003958 break;
3959 }
anthonyebb73a22012-03-22 14:25:52 +00003960 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003961 }
3962 case 'f':
3963 {
anthonyafa3dfc2012-03-03 11:31:30 +00003964 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003965 {
cristyf68c0be2015-04-28 22:48:37 +00003966 new_images=ForwardFourierTransformImage(_images,IsNormalOp,
3967 _exception);
anthony805a2d42011-09-25 08:25:12 +00003968 break;
3969 }
anthonyafa3dfc2012-03-03 11:31:30 +00003970 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003971 {
anthony319dac62012-03-06 04:12:44 +00003972 /* REDIRECTED to use -layers flatten instead */
cristy52b632a2014-11-08 00:31:34 +00003973 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003974 break;
3975 }
anthonyafa3dfc2012-03-03 11:31:30 +00003976 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003977 {
anthony92c93bd2012-03-19 14:02:47 +00003978 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003979 break;
3980 }
anthonyebb73a22012-03-22 14:25:52 +00003981 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003982 }
3983 case 'h':
3984 {
anthonyafa3dfc2012-03-03 11:31:30 +00003985 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003986 {
anthony31f1bf72012-01-30 12:37:22 +00003987 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003988 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003989 */
anthony805a2d42011-09-25 08:25:12 +00003990 Image
anthony31f1bf72012-01-30 12:37:22 +00003991 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003992
anthony92c93bd2012-03-19 14:02:47 +00003993 new_images=RemoveFirstImageFromList(&_images);
3994 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003995 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003996 break;
anthony92c93bd2012-03-19 14:02:47 +00003997 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003998 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003999 break;
4000 }
anthonyebb73a22012-03-22 14:25:52 +00004001 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004002 }
4003 case 'i':
4004 {
anthonyafa3dfc2012-03-03 11:31:30 +00004005 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004006 {
4007 Image
anthony805a2d42011-09-25 08:25:12 +00004008 *magnitude_image,
4009 *phase_image;
4010
anthony92c93bd2012-03-19 14:02:47 +00004011 magnitude_image=RemoveFirstImageFromList(&_images);
4012 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00004013 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00004014 if (phase_image == (Image *) NULL)
4015 break;
4016 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
cristyf68c0be2015-04-28 22:48:37 +00004017 IsNormalOp,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004018 magnitude_image=DestroyImage(magnitude_image);
4019 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00004020 break;
4021 }
anthonyafa3dfc2012-03-03 11:31:30 +00004022 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004023 {
4024 Image
anthony31f1bf72012-01-30 12:37:22 +00004025 *insert_image,
4026 *index_image;
4027
4028 ssize_t
4029 index;
anthony805a2d42011-09-25 08:25:12 +00004030
anthony7bcfe7f2012-03-30 14:01:22 +00004031 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00004032 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004033 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004034 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004035 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004036 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004037 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004038 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004039 PrependImageToList(&_images,insert_image);
4040 else if (index == (ssize_t) GetImageListLength(_images))
4041 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004042 else
anthony43f425d2012-02-26 12:58:58 +00004043 {
anthony92c93bd2012-03-19 14:02:47 +00004044 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004045 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004046 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004047 InsertImageInList(&index_image,insert_image);
4048 }
anthony92c93bd2012-03-19 14:02:47 +00004049 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004050 break;
4051 }
anthonyebb73a22012-03-22 14:25:52 +00004052 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004053 }
4054 case 'l':
4055 {
anthonyafa3dfc2012-03-03 11:31:30 +00004056 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004057 {
anthonyfe1aa782012-03-24 13:43:04 +00004058 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4059 if ( parse < 0 )
4060 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4061 option,arg1);
cristya0417062012-09-02 23:34:56 +00004062 switch ((LayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004063 {
4064 case CoalesceLayer:
4065 {
anthony92c93bd2012-03-19 14:02:47 +00004066 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004067 break;
4068 }
4069 case CompareAnyLayer:
4070 case CompareClearLayer:
4071 case CompareOverlayLayer:
4072 default:
4073 {
cristya0417062012-09-02 23:34:56 +00004074 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00004075 _exception);
anthony805a2d42011-09-25 08:25:12 +00004076 break;
4077 }
4078 case MergeLayer:
4079 case FlattenLayer:
4080 case MosaicLayer:
4081 case TrimBoundsLayer:
4082 {
cristya0417062012-09-02 23:34:56 +00004083 new_images=MergeImageLayers(_images,(LayerMethod) parse,
cristyf68c0be2015-04-28 22:48:37 +00004084 _exception);
anthony805a2d42011-09-25 08:25:12 +00004085 break;
4086 }
4087 case DisposeLayer:
4088 {
anthony92c93bd2012-03-19 14:02:47 +00004089 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004090 break;
4091 }
4092 case OptimizeImageLayer:
4093 {
anthony92c93bd2012-03-19 14:02:47 +00004094 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004095 break;
4096 }
4097 case OptimizePlusLayer:
4098 {
anthony92c93bd2012-03-19 14:02:47 +00004099 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004100 break;
4101 }
4102 case OptimizeTransLayer:
4103 {
anthony92c93bd2012-03-19 14:02:47 +00004104 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004105 break;
4106 }
4107 case RemoveDupsLayer:
4108 {
anthony92c93bd2012-03-19 14:02:47 +00004109 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004110 break;
4111 }
4112 case RemoveZeroLayer:
4113 {
anthony92c93bd2012-03-19 14:02:47 +00004114 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004115 break;
4116 }
4117 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004118 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004119 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004120 if (new_images == (Image *) NULL)
4121 break;
anthony92c93bd2012-03-19 14:02:47 +00004122 _images=DestroyImageList(_images);
4123 _images=OptimizeImageLayers(new_images,_exception);
4124 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004125 break;
4126 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004127 OptimizeImageTransparency(_images,_exception);
4128 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4129 _exception);
anthony805a2d42011-09-25 08:25:12 +00004130 break;
4131 }
4132 case CompositeLayer:
4133 {
anthony805a2d42011-09-25 08:25:12 +00004134 Image
4135 *source;
4136
4137 RectangleInfo
4138 geometry;
4139
anthony31f1bf72012-01-30 12:37:22 +00004140 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004141 compose;
4142
4143 const char*
4144 value;
4145
anthony92c93bd2012-03-19 14:02:47 +00004146 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004147 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004148 if (value != (const char *) NULL)
4149 compose=(CompositeOperator) ParseCommandOption(
4150 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004151
anthony31f1bf72012-01-30 12:37:22 +00004152 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004153 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004154 while (source != (Image *) NULL)
4155 {
4156 source=GetNextImageInList(source);
4157 if ((source != (Image *) NULL) &&
4158 (LocaleCompare(source->magick,"NULL") == 0))
4159 break;
4160 }
4161 if (source != (Image *) NULL)
4162 {
4163 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4164 (GetNextImageInList(source) == (Image *) NULL))
4165 source=(Image *) NULL;
4166 else
anthony31f1bf72012-01-30 12:37:22 +00004167 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004168 source=SplitImageList(source->previous);
4169 DeleteImageFromList(&source);
4170 }
4171 }
4172 if (source == (Image *) NULL)
4173 {
anthony92c93bd2012-03-19 14:02:47 +00004174 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004175 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004176 break;
4177 }
anthony31f1bf72012-01-30 12:37:22 +00004178 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004179 SetGeometry(_images,&geometry);
4180 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004181 geometry.width=source->page.width != 0 ?
4182 source->page.width : source->columns;
4183 geometry.height=source->page.height != 0 ?
4184 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004185 GravityAdjustGeometry(_images->page.width != 0 ?
4186 _images->page.width : _images->columns,
4187 _images->page.height != 0 ? _images->page.height :
4188 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004189
anthony31f1bf72012-01-30 12:37:22 +00004190 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004191 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4192 _exception);
anthony805a2d42011-09-25 08:25:12 +00004193 source=DestroyImageList(source);
4194 break;
4195 }
4196 }
anthony805a2d42011-09-25 08:25:12 +00004197 break;
4198 }
anthonyebb73a22012-03-22 14:25:52 +00004199 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004200 }
4201 case 'm':
4202 {
anthonyafa3dfc2012-03-03 11:31:30 +00004203 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004204 {
anthony464f1c42012-04-22 08:51:01 +00004205 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004206 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004207 break;
4208 }
cristye863c052013-09-04 11:31:30 +00004209 if (LocaleCompare("metric",option+1) == 0)
4210 break;
anthonyafa3dfc2012-03-03 11:31:30 +00004211 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004212 {
4213 Image
4214 *morph_image;
4215
anthony7bcfe7f2012-03-30 14:01:22 +00004216 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004217 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004218 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4219 _exception);
anthony805a2d42011-09-25 08:25:12 +00004220 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004221 break;
anthony92c93bd2012-03-19 14:02:47 +00004222 _images=DestroyImageList(_images);
4223 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004224 break;
4225 }
anthonyafa3dfc2012-03-03 11:31:30 +00004226 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004227 {
anthony319dac62012-03-06 04:12:44 +00004228 /* REDIRECTED to use -layers mosaic instead */
cristy52b632a2014-11-08 00:31:34 +00004229 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004230 break;
4231 }
anthonyebb73a22012-03-22 14:25:52 +00004232 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004233 }
4234 case 'p':
4235 {
cristy02016cf2012-11-13 01:14:41 +00004236 if (LocaleCompare("poly",option+1) == 0)
4237 {
4238 double
4239 *args;
4240
4241 ssize_t
4242 count;
4243
4244 /* convert argument string into an array of doubles */
cristyace09c62015-01-21 12:54:30 +00004245 args = StringToArrayOfDoubles(arg1,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00004246 if (args == (double *) NULL )
cristyace09c62015-01-21 12:54:30 +00004247 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg1);
cristyf68c0be2015-04-28 22:48:37 +00004248 new_images=PolynomialImage(_images,(size_t) (count >> 1),args,
4249 _exception);
cristy02016cf2012-11-13 01:14:41 +00004250 args=(double *) RelinquishMagickMemory(args);
4251 break;
4252 }
anthonyafa3dfc2012-03-03 11:31:30 +00004253 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004254 {
anthonyb1d483a2012-04-14 12:53:56 +00004255 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004256 char
4257 **arguments;
4258
4259 int
4260 j,
4261 number_arguments;
4262
anthony31f1bf72012-01-30 12:37:22 +00004263 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004264 if (arguments == (char **) NULL)
4265 break;
anthony31f1bf72012-01-30 12:37:22 +00004266 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004267 {
4268 char
4269 breaker,
4270 quote,
4271 *token;
4272
4273 const char
4274 *arguments;
4275
4276 int
4277 next,
4278 status;
4279
4280 size_t
4281 length;
4282
4283 TokenInfo
4284 *token_info;
4285
4286 /*
anthony24aa8822012-03-11 00:56:06 +00004287 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004288 */
cristy4bc3dac2014-01-18 15:17:26 +00004289 assert(arg1 != (const char *) NULL);
anthony31f1bf72012-01-30 12:37:22 +00004290 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004291 token=(char *) NULL;
cristy151b66d2015-04-15 10:50:31 +00004292 if (~length >= (MagickPathExtent-1))
4293 token=(char *) AcquireQuantumMemory(length+MagickPathExtent,
anthony805a2d42011-09-25 08:25:12 +00004294 sizeof(*token));
4295 if (token == (char *) NULL)
4296 break;
4297 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004298 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004299 token_info=AcquireTokenInfo();
4300 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4301 "\"",'\0',&breaker,&next,&quote);
4302 token_info=DestroyTokenInfo(token_info);
4303 if (status == 0)
4304 {
4305 const char
4306 *argv;
4307
4308 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004309 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4310 _exception);
anthony805a2d42011-09-25 08:25:12 +00004311 }
4312 token=DestroyString(token);
4313 break;
4314 }
4315 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004316 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4317 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004318 for (j=0; j < number_arguments; j++)
4319 arguments[j]=DestroyString(arguments[j]);
4320 arguments=(char **) RelinquishMagickMemory(arguments);
4321 break;
4322 }
anthonyebb73a22012-03-22 14:25:52 +00004323 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004324 }
4325 case 'r':
4326 {
anthonyafa3dfc2012-03-03 11:31:30 +00004327 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004328 {
anthony92c93bd2012-03-19 14:02:47 +00004329 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004330 break;
4331 }
anthonyafa3dfc2012-03-03 11:31:30 +00004332 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004333 {
anthony92c93bd2012-03-19 14:02:47 +00004334 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004335 break;
4336 }
anthonyebb73a22012-03-22 14:25:52 +00004337 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004338 }
4339 case 's':
4340 {
anthonyafa3dfc2012-03-03 11:31:30 +00004341 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004342 {
anthonycd358fc2012-04-16 13:59:03 +00004343 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004344 ssize_t
4345 offset;
4346
anthony7bcfe7f2012-03-30 14:01:22 +00004347 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004348 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004349 offset=(ssize_t) StringToLong(arg1);
anthonya322a832013-04-27 06:28:03 +00004350 new_images=SmushImages(_images,IsNormalOp,offset,_exception);
anthonycd358fc2012-04-16 13:59:03 +00004351 break;
4352 }
4353 if (LocaleCompare("subimage",option+1) == 0)
4354 {
4355 Image
4356 *base_image,
4357 *compare_image;
4358
cristyf68c0be2015-04-28 22:48:37 +00004359 const char
4360 *value;
anthonycd358fc2012-04-16 13:59:03 +00004361
4362 MetricType
4363 metric;
4364
4365 double
4366 similarity;
4367
4368 RectangleInfo
4369 offset;
4370
4371 base_image=GetImageFromList(_images,0);
4372 compare_image=GetImageFromList(_images,1);
4373
4374 /* Comparision Metric */
cristy08163292013-07-11 00:00:37 +00004375 metric=UndefinedErrorMetric;
anthonycd358fc2012-04-16 13:59:03 +00004376 value=GetImageOption(_image_info,"metric");
4377 if (value != (const char *) NULL)
4378 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4379 MagickFalse,value);
4380
cristy99fcec42013-03-15 21:37:59 +00004381 new_images=SimilarityImage(base_image,compare_image,metric,0.0,
cristyf68c0be2015-04-28 22:48:37 +00004382 &offset,&similarity,_exception);
anthonycd358fc2012-04-16 13:59:03 +00004383
cristyf432c632014-12-07 15:11:28 +00004384 if ( new_images != (Image *) NULL ) {
anthonycd358fc2012-04-16 13:59:03 +00004385 char
cristy151b66d2015-04-15 10:50:31 +00004386 result[MagickPathExtent];
anthonycd358fc2012-04-16 13:59:03 +00004387
cristy151b66d2015-04-15 10:50:31 +00004388 (void) FormatLocaleString(result,MagickPathExtent,"%lf",similarity);
anthonycd358fc2012-04-16 13:59:03 +00004389 (void) SetImageProperty(new_images,"subimage:similarity",result,
4390 _exception);
cristy151b66d2015-04-15 10:50:31 +00004391 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",
anthonycd358fc2012-04-16 13:59:03 +00004392 (long) offset.x);
4393 (void) SetImageProperty(new_images,"subimage:x",result,
4394 _exception);
cristy151b66d2015-04-15 10:50:31 +00004395 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",
anthonycd358fc2012-04-16 13:59:03 +00004396 (long) offset.y);
4397 (void) SetImageProperty(new_images,"subimage:y",result,
4398 _exception);
cristy151b66d2015-04-15 10:50:31 +00004399 (void) FormatLocaleString(result,MagickPathExtent,"%lux%lu%+ld%+ld",
anthonycd358fc2012-04-16 13:59:03 +00004400 (unsigned long) offset.width,(unsigned long) offset.height,
4401 (long) offset.x,(long) offset.y);
4402 (void) SetImageProperty(new_images,"subimage:offset",result,
4403 _exception);
4404 }
anthony805a2d42011-09-25 08:25:12 +00004405 break;
4406 }
cristyf68c0be2015-04-28 22:48:37 +00004407 if (LocaleCompare("swap",option+1) == 0)
4408 {
anthony0ea037a2012-04-03 12:14:39 +00004409 Image
4410 *p,
4411 *q,
4412 *swap;
anthony805a2d42011-09-25 08:25:12 +00004413
anthony0ea037a2012-04-03 12:14:39 +00004414 ssize_t
4415 index,
4416 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004417
cristy6b36c942013-02-17 00:36:24 +00004418 index=(-1);
4419 swap_index=(-2);
anthony0ea037a2012-04-03 12:14:39 +00004420 if (IfNormalOp) {
4421 GeometryInfo
4422 geometry_info;
4423
4424 MagickStatusType
4425 flags;
4426
4427 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004428 flags=ParseGeometry(arg1,&geometry_info);
cristy90fbd1c2013-02-17 00:35:35 +00004429 if ((flags & RhoValue) == 0)
anthonyb1e21ed2012-04-20 12:43:12 +00004430 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004431 index=(ssize_t) geometry_info.rho;
4432 if ((flags & SigmaValue) != 0)
4433 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004434 }
anthony0ea037a2012-04-03 12:14:39 +00004435 p=GetImageFromList(_images,index);
4436 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004437 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4438 if (IfNormalOp)
4439 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4440 else
4441 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4442 }
anthony0ea037a2012-04-03 12:14:39 +00004443 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004444 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004445 swap=CloneImage(p,0,0,MagickTrue,_exception);
4446 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4447 ReplaceImageInList(&q,swap);
4448 _images=GetFirstImageInList(q);
4449 break;
4450 }
anthonyebb73a22012-03-22 14:25:52 +00004451 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004452 }
anthony805a2d42011-09-25 08:25:12 +00004453 default:
anthonyebb73a22012-03-22 14:25:52 +00004454 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004455 }
anthony964d28e2012-05-17 23:39:46 +00004456
4457 /* clean up percent escape interpreted strings */
4458 if (arg1 != arg1n )
4459 arg1=DestroyString((char *)arg1);
4460 if (arg2 != arg2n )
4461 arg2=DestroyString((char *)arg2);
4462
4463 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004464 if (new_images == (Image *) NULL)
cristy6398ec72013-11-28 02:00:27 +00004465 return(status == 0 ? MagickFalse : MagickTrue);
anthony964d28e2012-05-17 23:39:46 +00004466 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004467 _images=GetFirstImageInList(new_images);
cristy6398ec72013-11-28 02:00:27 +00004468 return(status == 0 ? MagickFalse : MagickTrue);
anthony31f1bf72012-01-30 12:37:22 +00004469
anthony92c93bd2012-03-19 14:02:47 +00004470#undef _image_info
4471#undef _images
4472#undef _exception
4473#undef _draw_info
4474#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004475#undef IfNormalOp
4476#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00004477#undef IsNormalOp
anthony805a2d42011-09-25 08:25:12 +00004478}
anthony43f425d2012-02-26 12:58:58 +00004479
4480/*
4481%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4482% %
4483% %
4484% %
anthony964d28e2012-05-17 23:39:46 +00004485+ 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 +00004486% %
4487% %
4488% %
4489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4490%
anthony464f1c42012-04-22 08:51:01 +00004491% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004492% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004493%
anthony4837ac22012-05-18 23:39:48 +00004494% The classic operators of this type is "-read", which actually creates
4495% images even when no images are present. Or image stack operators, which
4496% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004497%
anthony4837ac22012-05-18 23:39:48 +00004498% Note that these operators may involve other special 'option' prefix
4499% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004500%
anthony464f1c42012-04-22 08:51:01 +00004501% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004502%
anthony464f1c42012-04-22 08:51:01 +00004503% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4504% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004505%
4506% A description of each parameter follows:
4507%
anthonyc7994672012-11-17 05:33:27 +00004508% o cli_wand: the main CLI Wand to use. (sometimes not required)
anthony43f425d2012-02-26 12:58:58 +00004509%
4510% o option: The special option (with any switch char) to process
4511%
anthony464f1c42012-04-22 08:51:01 +00004512% o arg1 & arg2: Argument for option, if required
4513% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004514%
4515*/
cristyfe831852013-02-12 14:56:07 +00004516WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
anthonya322a832013-04-27 06:28:03 +00004517 const char *option,const char *arg1n,const char *arg2n)
anthony43f425d2012-02-26 12:58:58 +00004518{
anthonya322a832013-04-27 06:28:03 +00004519 const char /* percent escaped versions of the args */
anthony4837ac22012-05-18 23:39:48 +00004520 *arg1,
4521 *arg2;
anthony4837ac22012-05-18 23:39:48 +00004522
anthony8226e722012-04-05 14:25:46 +00004523#define _image_info (cli_wand->wand.image_info)
4524#define _images (cli_wand->wand.images)
4525#define _exception (cli_wand->wand.exception)
anthonya322a832013-04-27 06:28:03 +00004526#define _process_flags (cli_wand->process_flags)
4527#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthony8226e722012-04-05 14:25:46 +00004528#define IfNormalOp (*option=='-')
4529#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004530
4531 assert(cli_wand != (MagickCLI *) NULL);
4532 assert(cli_wand->signature == WandSignature);
4533 assert(cli_wand->wand.signature == WandSignature);
anthonya322a832013-04-27 06:28:03 +00004534
anthony7bcfe7f2012-03-30 14:01:22 +00004535 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00004536 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
4537 "- NoImage Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
anthony43f425d2012-02-26 12:58:58 +00004538
anthony4837ac22012-05-18 23:39:48 +00004539 arg1 = arg1n;
4540 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00004541
4542 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +00004543 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4544 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4545 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4546 /* Interpret Percent escapes in argument 1 */
4547 if (arg1n != (char *) NULL) {
4548 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4549 if (arg1 == (char *) NULL) {
4550 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4551 arg1=arg1n; /* use the given argument as is */
4552 }
4553 }
4554 if (arg2n != (char *) NULL) {
4555 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4556 if (arg2 == (char *) NULL) {
4557 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4558 arg2=arg2n; /* use the given argument as is */
4559 }
4560 }
4561 }
4562#undef _process_flags
4563#undef _option_type
anthony4837ac22012-05-18 23:39:48 +00004564
4565 do { /* break to exit code */
4566 /*
4567 No-op options (ignore these)
4568 */
anthonyc7994672012-11-17 05:33:27 +00004569 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
anthony4837ac22012-05-18 23:39:48 +00004570 break;
4571 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4572 break;
anthonyc7994672012-11-17 05:33:27 +00004573 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4574 break;
4575 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
anthony4837ac22012-05-18 23:39:48 +00004576 break;
4577 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4578 break;
4579 /*
4580 Image Reading
4581 */
4582 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4583 ( LocaleCompare("--",option) == 0 ) ) {
4584 /* Do Glob filename Expansion for 'arg1' then read all images.
4585 *
4586 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4587 * (but attaching to the filenames in the generated argument list) any
4588 * [...] read modifiers that may be present.
4589 *
4590 * For example: It will expand '*.gif[20x20]' into a list such as
4591 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4592 *
4593 * NOTE: In IMv6 this was done globally across all images. This
4594 * meant you could include IM options in '@filename' lists, but you
4595 * could not include comments. Doing it only for image read makes
4596 * it far more secure.
4597 *
4598 * Note: arguments do not have percent escapes expanded for security
4599 * reasons.
4600 */
4601 int argc;
4602 char **argv;
4603 ssize_t i;
4604
4605 argc = 1;
4606 argv = (char **) &arg1;
4607
4608 /* Expand 'glob' expressions in the given filename.
4609 Expansion handles any 'coder:' prefix, or read modifiers attached
4610 to the filename, including them in the resulting expanded list.
4611 */
4612 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4613 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4614 option,GetExceptionMessage(errno));
4615
4616 /* loop over expanded filename list, and read then all in */
cristy52b632a2014-11-08 00:31:34 +00004617 for (i=0; i < (ssize_t) argc; i++) {
anthony4837ac22012-05-18 23:39:48 +00004618 Image *
4619 new_images;
4620 if (IfMagickTrue(_image_info->ping))
4621 new_images=PingImages(_image_info,argv[i],_exception);
4622 else
4623 new_images=ReadImages(_image_info,argv[i],_exception);
4624 AppendImageToList(&_images, new_images);
4625 }
4626 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4627 break;
4628 }
4629 /*
4630 Image Writing
4631 Note: Writing a empty image list is valid in specific cases
4632 */
4633 if (LocaleCompare("write",option+1) == 0) {
4634 /* Note: arguments do not have percent escapes expanded */
4635 char
cristy151b66d2015-04-15 10:50:31 +00004636 key[MagickPathExtent];
anthony4837ac22012-05-18 23:39:48 +00004637
4638 Image
4639 *write_images;
4640
4641 ImageInfo
4642 *write_info;
4643
4644 /* Need images, unless a "null:" output coder is used */
anthonya322a832013-04-27 06:28:03 +00004645 if ( _images == (Image *) NULL ) {
anthony4837ac22012-05-18 23:39:48 +00004646 if ( LocaleCompare(arg1,"null:") == 0 )
4647 break;
4648 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4649 }
4650
cristy151b66d2015-04-15 10:50:31 +00004651 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",arg1);
anthony4837ac22012-05-18 23:39:48 +00004652 (void) DeleteImageRegistry(key);
4653 write_images=_images;
4654 if (IfPlusOp)
4655 write_images=CloneImageList(_images,_exception);
4656 write_info=CloneImageInfo(_image_info);
4657 (void) WriteImages(write_info,write_images,arg1,_exception);
4658 write_info=DestroyImageInfo(write_info);
4659 if (IfPlusOp)
4660 write_images=DestroyImageList(write_images);
4661 break;
4662 }
4663 /*
4664 Parenthesis and Brace operations
4665 */
4666 if (LocaleCompare("(",option) == 0) {
4667 /* stack 'push' images */
4668 Stack
4669 *node;
4670
4671 size_t
4672 size;
4673
4674 size=0;
4675 node=cli_wand->image_list_stack;
cristyf432c632014-12-07 15:11:28 +00004676 for ( ; node != (Stack *) NULL; node=node->next)
anthony4837ac22012-05-18 23:39:48 +00004677 size++;
4678 if ( size >= MAX_STACK_DEPTH )
4679 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4680 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4681 if (node == (Stack *) NULL)
4682 CLIWandExceptionBreak(ResourceLimitFatalError,
4683 "MemoryAllocationFailed",option);
4684 node->data = (void *)cli_wand->wand.images;
anthony4837ac22012-05-18 23:39:48 +00004685 node->next = cli_wand->image_list_stack;
4686 cli_wand->image_list_stack = node;
anthonya322a832013-04-27 06:28:03 +00004687 cli_wand->wand.images = NewImageList();
anthony4837ac22012-05-18 23:39:48 +00004688
4689 /* handle respect-parenthesis */
4690 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4691 "respect-parenthesis"))))
4692 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004693 else
anthony4837ac22012-05-18 23:39:48 +00004694 break;
anthonya322a832013-04-27 06:28:03 +00004695 /* fall thru to operation */
anthony52bef752012-03-27 13:54:47 +00004696 }
anthony4837ac22012-05-18 23:39:48 +00004697 if (LocaleCompare("{",option) == 0) {
4698 /* stack 'push' of image_info settings */
4699 Stack
4700 *node;
anthony8226e722012-04-05 14:25:46 +00004701
anthony4837ac22012-05-18 23:39:48 +00004702 size_t
4703 size;
anthony8226e722012-04-05 14:25:46 +00004704
anthony4837ac22012-05-18 23:39:48 +00004705 size=0;
4706 node=cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004707 for ( ; node != (Stack *) NULL; node=node->next)
anthony4837ac22012-05-18 23:39:48 +00004708 size++;
4709 if ( size >= MAX_STACK_DEPTH )
4710 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4711 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4712 if (node == (Stack *) NULL)
4713 CLIWandExceptionBreak(ResourceLimitFatalError,
4714 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004715
anthony4837ac22012-05-18 23:39:48 +00004716 node->data = (void *)cli_wand->wand.image_info;
anthonya322a832013-04-27 06:28:03 +00004717 node->next = cli_wand->image_info_stack;
4718
4719 cli_wand->image_info_stack = node;
anthony4837ac22012-05-18 23:39:48 +00004720 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
cristyf432c632014-12-07 15:11:28 +00004721 if (cli_wand->wand.image_info == (ImageInfo *) NULL) {
anthony4837ac22012-05-18 23:39:48 +00004722 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4723 option);
4724 cli_wand->wand.image_info = (ImageInfo *)node->data;
4725 node = (Stack *)RelinquishMagickMemory(node);
4726 break;
4727 }
4728
anthony4837ac22012-05-18 23:39:48 +00004729 break;
anthony8226e722012-04-05 14:25:46 +00004730 }
anthony4837ac22012-05-18 23:39:48 +00004731 if (LocaleCompare(")",option) == 0) {
4732 /* pop images from stack */
4733 Stack
4734 *node;
anthony8226e722012-04-05 14:25:46 +00004735
anthony4837ac22012-05-18 23:39:48 +00004736 node = (Stack *)cli_wand->image_list_stack;
cristyf432c632014-12-07 15:11:28 +00004737 if ( node == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004738 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4739 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004740
anthony4837ac22012-05-18 23:39:48 +00004741 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4742 cli_wand->wand.images= (Image *)node->data;
4743 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004744
anthony4837ac22012-05-18 23:39:48 +00004745 /* handle respect-parenthesis - of the previous 'pushed' settings */
4746 node = cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004747 if ( node != (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004748 {
4749 if (IfMagickTrue(IsStringTrue(GetImageOption(
4750 cli_wand->wand.image_info,"respect-parenthesis"))))
4751 option="}"; /* fall-thru so as to pop image settings too */
4752 else
4753 break;
4754 }
4755 else
4756 break;
4757 /* fall thru to next if */
4758 }
4759 if (LocaleCompare("}",option) == 0) {
4760 /* pop image_info settings from stack */
4761 Stack
4762 *node;
anthony43f425d2012-02-26 12:58:58 +00004763
anthony4837ac22012-05-18 23:39:48 +00004764 node = (Stack *)cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004765 if ( node == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004766 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4767 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004768
anthony4837ac22012-05-18 23:39:48 +00004769 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004770 cli_wand->wand.image_info = (ImageInfo *)node->data;
4771 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004772
4773 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4774 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4775 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4776
4777 break;
4778 }
anthonya322a832013-04-27 06:28:03 +00004779 if (LocaleCompare("print",option+1) == 0)
4780 {
4781 (void) FormatLocaleFile(stdout,"%s",arg1);
4782 break;
4783 }
anthonyc7994672012-11-17 05:33:27 +00004784 if (LocaleCompare("set",option+1) == 0)
4785 {
anthonya322a832013-04-27 06:28:03 +00004786 /* Settings are applied to each image in memory in turn (if any).
4787 While a option: only need to be applied once globally.
4788
4789 NOTE: rguments have not been automatically percent expaneded
anthonyc7994672012-11-17 05:33:27 +00004790 */
anthonya322a832013-04-27 06:28:03 +00004791
4792 /* escape the 'key' once only, using first image. */
4793 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4794 if (arg1 == (char *) NULL)
4795 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4796 option);
anthonyc7994672012-11-17 05:33:27 +00004797
4798 if (LocaleNCompare(arg1,"registry:",9) == 0)
4799 {
4800 if (IfPlusOp)
4801 {
4802 (void) DeleteImageRegistry(arg1+9);
anthonya322a832013-04-27 06:28:03 +00004803 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004804 break;
4805 }
anthonya322a832013-04-27 06:28:03 +00004806 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4807 if (arg2 == (char *) NULL) {
4808 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004809 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4810 option);
anthonya322a832013-04-27 06:28:03 +00004811 }
4812 (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
4813 arg1=DestroyString((char *)arg1);
4814 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004815 break;
4816 }
4817 if (LocaleNCompare(arg1,"option:",7) == 0)
4818 {
4819 /* delete equivelent artifact from all images (if any) */
cristyf432c632014-12-07 15:11:28 +00004820 if (_images != (Image *) NULL)
anthonya322a832013-04-27 06:28:03 +00004821 {
4822 MagickResetIterator(&cli_wand->wand);
4823 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4824 (void) DeleteImageArtifact(_images,arg1+7);
4825 MagickResetIterator(&cli_wand->wand);
4826 }
anthonyc7994672012-11-17 05:33:27 +00004827 /* now set/delete the global option as needed */
anthonya322a832013-04-27 06:28:03 +00004828 /* FUTURE: make escapes in a global 'option:' delayed */
cristyf432c632014-12-07 15:11:28 +00004829 arg2=(char *) NULL;
anthonya322a832013-04-27 06:28:03 +00004830 if (IfNormalOp)
4831 {
4832 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4833 if (arg2 == (char *) NULL)
4834 CLIWandExceptionBreak(OptionWarning,
4835 "InterpretPropertyFailure",option);
4836 }
4837 (void) SetImageOption(_image_info,arg1+7,arg2);
4838 arg1=DestroyString((char *)arg1);
4839 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004840 break;
4841 }
anthonya322a832013-04-27 06:28:03 +00004842 /* Set Artifacts/Properties/Attributes all images (required) */
4843 if ( _images == (Image *) NULL )
4844 CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
4845
anthonyc7994672012-11-17 05:33:27 +00004846 MagickResetIterator(&cli_wand->wand);
4847 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4848 {
cristyf432c632014-12-07 15:11:28 +00004849 arg2=(char *) NULL;
anthonya322a832013-04-27 06:28:03 +00004850 if (IfNormalOp)
4851 {
4852 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4853 if (arg2 == (char *) NULL)
4854 CLIWandExceptionBreak(OptionWarning,
4855 "InterpretPropertyFailure",option);
4856 }
4857 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4858 (void) SetImageArtifact(_images,arg1+9,arg2);
4859 else if (LocaleNCompare(arg1,"property:",9) == 0)
4860 (void) SetImageProperty(_images,arg1+9,arg2,_exception);
4861 else
4862 (void) SetImageProperty(_images,arg1,arg2,_exception);
4863 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004864 }
4865 MagickResetIterator(&cli_wand->wand);
anthonya322a832013-04-27 06:28:03 +00004866 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004867 break;
4868 }
anthony4837ac22012-05-18 23:39:48 +00004869 if (LocaleCompare("clone",option+1) == 0) {
4870 Image
4871 *new_images;
4872
4873 if (*option == '+')
cristy3677cc72014-11-14 23:22:55 +00004874 arg1=AcquireString("-1");
anthony4837ac22012-05-18 23:39:48 +00004875 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4876 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
cristyf432c632014-12-07 15:11:28 +00004877 if ( cli_wand->image_list_stack == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004878 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4879 new_images = (Image *)cli_wand->image_list_stack->data;
4880 if (new_images == (Image *) NULL)
4881 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4882 new_images=CloneImages(new_images,arg1,_exception);
4883 if (new_images == (Image *) NULL)
4884 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4885 AppendImageToList(&_images,new_images);
4886 break;
4887 }
4888 /*
cristy422d5502012-12-22 22:20:57 +00004889 Informational Operations.
anthony4837ac22012-05-18 23:39:48 +00004890
anthonyc7994672012-11-17 05:33:27 +00004891 Note that these do not require either a cli-wand or images!
4892 Though currently a cli-wand much be provided regardless.
anthony4837ac22012-05-18 23:39:48 +00004893 */
cristy422d5502012-12-22 22:20:57 +00004894 if (LocaleCompare("version",option+1) == 0)
4895 {
cristy4f7a6132012-12-23 00:35:19 +00004896 ListMagickVersion(stdout);
cristy422d5502012-12-22 22:20:57 +00004897 break;
4898 }
anthony4837ac22012-05-18 23:39:48 +00004899 if (LocaleCompare("list",option+1) == 0) {
4900 /*
anthonyc7994672012-11-17 05:33:27 +00004901 FUTURE: This 'switch' should really be part of MagickCore
anthony4837ac22012-05-18 23:39:48 +00004902 */
4903 ssize_t
4904 list;
4905
4906 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4907 if ( list < 0 ) {
4908 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4909 break;
4910 }
4911 switch (list)
4912 {
4913 case MagickCoderOptions:
4914 {
4915 (void) ListCoderInfo((FILE *) NULL,_exception);
4916 break;
4917 }
4918 case MagickColorOptions:
4919 {
4920 (void) ListColorInfo((FILE *) NULL,_exception);
4921 break;
4922 }
4923 case MagickConfigureOptions:
4924 {
4925 (void) ListConfigureInfo((FILE *) NULL,_exception);
4926 break;
4927 }
4928 case MagickDelegateOptions:
4929 {
4930 (void) ListDelegateInfo((FILE *) NULL,_exception);
4931 break;
4932 }
4933 case MagickFontOptions:
4934 {
4935 (void) ListTypeInfo((FILE *) NULL,_exception);
4936 break;
4937 }
4938 case MagickFormatOptions:
4939 (void) ListMagickInfo((FILE *) NULL,_exception);
4940 break;
4941 case MagickLocaleOptions:
4942 (void) ListLocaleInfo((FILE *) NULL,_exception);
4943 break;
4944 case MagickLogOptions:
4945 (void) ListLogInfo((FILE *) NULL,_exception);
4946 break;
4947 case MagickMagicOptions:
4948 (void) ListMagicInfo((FILE *) NULL,_exception);
4949 break;
4950 case MagickMimeOptions:
4951 (void) ListMimeInfo((FILE *) NULL,_exception);
4952 break;
4953 case MagickModuleOptions:
4954 (void) ListModuleInfo((FILE *) NULL,_exception);
4955 break;
4956 case MagickPolicyOptions:
4957 (void) ListPolicyInfo((FILE *) NULL,_exception);
4958 break;
4959 case MagickResourceOptions:
4960 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4961 break;
4962 case MagickThresholdOptions:
4963 (void) ListThresholdMaps((FILE *) NULL,_exception);
4964 break;
4965 default:
4966 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4967 _exception);
4968 break;
4969 }
4970 break;
anthony43f425d2012-02-26 12:58:58 +00004971 }
anthony8226e722012-04-05 14:25:46 +00004972
anthony4837ac22012-05-18 23:39:48 +00004973 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony8226e722012-04-05 14:25:46 +00004974
dirk93b02b72013-11-16 16:03:36 +00004975DisableMSCWarning(4127)
anthony4837ac22012-05-18 23:39:48 +00004976 } while (0); /* break to exit code. */
dirk93b02b72013-11-16 16:03:36 +00004977RestoreMSCWarning
anthony43f425d2012-02-26 12:58:58 +00004978
anthony4837ac22012-05-18 23:39:48 +00004979 /* clean up percent escape interpreted strings */
4980 if (arg1 != arg1n )
4981 arg1=DestroyString((char *)arg1);
4982 if (arg2 != arg2n )
4983 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00004984
anthony8226e722012-04-05 14:25:46 +00004985#undef _image_info
4986#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004987#undef _exception
anthony8226e722012-04-05 14:25:46 +00004988#undef IfNormalOp
4989#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004990}
anthony464f1c42012-04-22 08:51:01 +00004991
4992/*
4993%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4994% %
4995% %
4996% %
anthony964d28e2012-05-17 23:39:46 +00004997+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00004998% %
4999% %
5000% %
5001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5002%
5003% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00005004% The option arguments can be variable in number, though at this time no more
5005% that two is actually used by any option (this may change). Excess options
5006% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00005007%
5008% If the cli_wand->command pointer is non-null, then it is assumed that the
5009% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00005010% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
5011% routine will do the lookup instead. The pointer is reset afterward.
5012%
5013% This action allows the caller to lookup and pre-handle any 'special'
5014% options, (such as implicit reads) before calling this general option
5015% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00005016%
5017% The format of the CLIOption method is:
5018%
5019% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
5020%
5021% A description of each parameter follows:
5022%
5023% o cli_wand: the main CLI Wand to use.
5024%
5025% o option: The special option (with any switch char) to process
5026%
anthony964d28e2012-05-17 23:39:46 +00005027% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00005028%
5029% Example Usage...
5030%
5031% CLIoption(cli_wand,"-read","rose:");
5032% CLIoption(cli_wand,"-virtual-pixel","transparent");
5033% CLIoption(cli_wand,"-distort","SRT:","30");
5034% CLIoption(cli_wand,"-write","rotated_rose.png");
5035%
5036*/
5037WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
5038{
anthonya322a832013-04-27 06:28:03 +00005039 const char /* extracted option args from args */
anthony464f1c42012-04-22 08:51:01 +00005040 *arg1,
5041 *arg2;
5042
5043 CommandOptionFlags
5044 option_type;
5045
5046 assert(cli_wand != (MagickCLI *) NULL);
5047 assert(cli_wand->signature == WandSignature);
5048 assert(cli_wand->wand.signature == WandSignature);
anthony464f1c42012-04-22 08:51:01 +00005049
anthony964d28e2012-05-17 23:39:46 +00005050 do { /* Break Code Block for error handling */
5051
5052 /* get information about option */
5053 if ( cli_wand->command == (const OptionInfo *) NULL )
5054 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00005055#if 0
anthony964d28e2012-05-17 23:39:46 +00005056 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
5057 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00005058#endif
anthony964d28e2012-05-17 23:39:46 +00005059 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00005060
anthony964d28e2012-05-17 23:39:46 +00005061 if ( option_type == UndefinedOptionFlag )
5062 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00005063
anthony964d28e2012-05-17 23:39:46 +00005064 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00005065
dirkab5c7452014-10-11 19:14:52 +00005066 /* deprecated options */
anthony964d28e2012-05-17 23:39:46 +00005067 if ( (option_type & DeprecateOptionFlag) != 0 )
5068 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00005069
anthony964d28e2012-05-17 23:39:46 +00005070 /* options that this module does not handle */
5071 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
5072 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00005073
anthony964d28e2012-05-17 23:39:46 +00005074 /* Get argument strings from VarArgs
anthonya322a832013-04-27 06:28:03 +00005075 How can you determine if enough arguments was supplied?
5076 What happens if not enough arguments were supplied?
5077 */
anthony964d28e2012-05-17 23:39:46 +00005078 { size_t
cristy52b632a2014-11-08 00:31:34 +00005079 count = (size_t) cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00005080
anthony964d28e2012-05-17 23:39:46 +00005081 va_list
5082 operands;
anthony464f1c42012-04-22 08:51:01 +00005083
anthony964d28e2012-05-17 23:39:46 +00005084 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00005085
anthony964d28e2012-05-17 23:39:46 +00005086 arg1=arg2=NULL;
5087 if ( count >= 1 )
5088 arg1=(const char *) va_arg(operands, const char *);
5089 if ( count >= 2 )
5090 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00005091
anthony964d28e2012-05-17 23:39:46 +00005092 va_end(operands);
anthony52cb3df2012-04-24 03:29:32 +00005093#if 0
anthony964d28e2012-05-17 23:39:46 +00005094 (void) FormatLocaleFile(stderr,
5095 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
5096 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00005097#endif
anthony964d28e2012-05-17 23:39:46 +00005098 }
5099
5100 /*
5101 Call the appropriate option handler
5102 */
5103
5104 /* FUTURE: this is temporary - get 'settings' to handle distribution of
5105 settings to images attributes,proprieties,artifacts */
cristyf432c632014-12-07 15:11:28 +00005106 if ( cli_wand->wand.images != (Image *) NULL )
cristy52b632a2014-11-08 00:31:34 +00005107 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
5108 cli_wand->wand.exception);
anthony964d28e2012-05-17 23:39:46 +00005109
5110 if ( (option_type & SettingOptionFlags) != 0 ) {
5111 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
5112 // FUTURE: Sync Specific Settings into Image Properities (not global)
5113 }
5114
5115 /* Operators that do not need images - read, write, stack, clone */
5116 if ( (option_type & NoImageOperatorFlag) != 0)
5117 CLINoImageOperator(cli_wand, option, arg1, arg2);
5118
5119 /* FUTURE: The not a setting part below is a temporary hack due to
5120 * some options being both a Setting and a Simple operator.
5121 * Specifically -monitor, -depth, and -colorspace */
cristyf432c632014-12-07 15:11:28 +00005122 if ( cli_wand->wand.images == (Image *) NULL )
anthony964d28e2012-05-17 23:39:46 +00005123 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
5124 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
5125 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
5126
anthonya322a832013-04-27 06:28:03 +00005127 /* Operators which loop of individual images, simply */
5128 if ( (option_type & SimpleOperatorFlag) != 0 &&
cristyf432c632014-12-07 15:11:28 +00005129 cli_wand->wand.images != (Image *) NULL) /* temp hack */
cristy2c57b742014-10-31 00:40:34 +00005130 {
5131 ExceptionInfo *exception=AcquireExceptionInfo();
cristy52b632a2014-11-08 00:31:34 +00005132 (void) CLISimpleOperatorImages(cli_wand, option, arg1, arg2,exception);
cristy2c57b742014-10-31 00:40:34 +00005133 exception=DestroyExceptionInfo(exception);
5134 }
anthony964d28e2012-05-17 23:39:46 +00005135
5136 /* Operators that work on the image list as a whole */
5137 if ( (option_type & ListOperatorFlag) != 0 )
cristy52b632a2014-11-08 00:31:34 +00005138 (void) CLIListOperatorImages(cli_wand, option, arg1, arg2);
anthony964d28e2012-05-17 23:39:46 +00005139
dirk93b02b72013-11-16 16:03:36 +00005140DisableMSCWarning(4127)
anthony964d28e2012-05-17 23:39:46 +00005141 } while (0); /* end Break code block */
dirk93b02b72013-11-16 16:03:36 +00005142RestoreMSCWarning
anthony464f1c42012-04-22 08:51:01 +00005143
5144 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00005145}