blob: 417581cdad92abde58b612d71d535c4e77695124 [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% %
Cristy7ce65e72015-12-12 18:03:16 -050020% Copyright 1999-2016 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
Cristy5da20072015-09-02 10:06:14 -0400104 if ((extent <= 1) || (offset < 0) || (offset >= (MagickOffsetType) extent))
105 return(MagickTrue);
106 if ((offset != (MagickOffsetType) (extent-1)) && ((offset % 50) != 0))
anthony805a2d42011-09-25 08:25:12 +0000107 return(MagickTrue);
cristy151b66d2015-04-15 10:50:31 +0000108 (void) CopyMagickMemory(tag,text,MagickPathExtent);
anthony805a2d42011-09-25 08:25:12 +0000109 p=strrchr(tag,'/');
110 if (p != (char *) NULL)
111 *p='\0';
cristy151b66d2015-04-15 10:50:31 +0000112 (void) FormatLocaleString(message,MagickPathExtent,"Monitor/%s",tag);
anthony805a2d42011-09-25 08:25:12 +0000113 locale_message=GetLocaleMessage(message);
114 if (locale_message == message)
115 locale_message=tag;
116 if (p == (char *) NULL)
117 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
118 locale_message,(long) offset,(unsigned long) extent,(long)
119 (100L*offset/(extent-1)));
120 else
121 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
122 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
123 (100L*offset/(extent-1)));
124 if (offset == (MagickOffsetType) (extent-1))
125 (void) FormatLocaleFile(stderr,"\n");
126 (void) fflush(stderr);
127 return(MagickTrue);
128}
129
130/*
131** GetImageCache() will read an image into a image cache if not already
132** present then return the image that is in the cache under that filename.
133*/
134static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
135 ExceptionInfo *exception)
136{
137 char
cristy151b66d2015-04-15 10:50:31 +0000138 key[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +0000139
140 ExceptionInfo
141 *sans_exception;
142
143 Image
144 *image;
145
146 ImageInfo
147 *read_info;
148
cristy151b66d2015-04-15 10:50:31 +0000149 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",path);
anthony805a2d42011-09-25 08:25:12 +0000150 sans_exception=AcquireExceptionInfo();
151 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
152 sans_exception=DestroyExceptionInfo(sans_exception);
153 if (image != (Image *) NULL)
154 return(image);
155 read_info=CloneImageInfo(image_info);
cristy4d246fc2014-01-15 22:33:44 +0000156 if (path != (const char *) NULL)
cristy151b66d2015-04-15 10:50:31 +0000157 (void) CopyMagickString(read_info->filename,path,MagickPathExtent);
anthony805a2d42011-09-25 08:25:12 +0000158 image=ReadImage(read_info,exception);
159 read_info=DestroyImageInfo(read_info);
160 if (image != (Image *) NULL)
161 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
162 return(image);
163}
164
anthony756cd0d2012-04-08 12:41:44 +0000165/*
anthonya89dd172011-10-04 13:29:35 +0000166 SparseColorOption() parse the complex -sparse-color argument into an
167 an array of floating point values than call SparseColorImage().
168 Argument is a complex mix of floating-point pixel coodinates, and color
169 specifications (or direct floating point numbers). The number of floats
anthony4023b262013-06-03 07:43:50 +0000170 needed to represent a color varies depending on the current channel
anthonya89dd172011-10-04 13:29:35 +0000171 setting.
anthony43f425d2012-02-26 12:58:58 +0000172
173 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000174*/
175static Image *SparseColorOption(const Image *image,
cristyab943592013-03-29 16:47:23 +0000176 const SparseColorMethod method,const char *arguments,ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000177{
178 char
cristy151b66d2015-04-15 10:50:31 +0000179 token[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +0000180
181 const char
182 *p;
183
184 double
185 *sparse_arguments;
186
187 Image
188 *sparse_image;
189
190 PixelInfo
191 color;
192
193 MagickBooleanType
194 error;
195
196 register size_t
197 x;
198
199 size_t
200 number_arguments,
201 number_colors;
202
203 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000204 assert(image->signature == MagickCoreSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000205 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000206 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
207 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000208 assert(exception->signature == MagickCoreSignature);
anthony805a2d42011-09-25 08:25:12 +0000209 /*
anthonyb1d483a2012-04-14 12:53:56 +0000210 Limit channels according to image
211 add up number of values needed per color.
anthony805a2d42011-09-25 08:25:12 +0000212 */
213 number_colors=0;
214 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
215 number_colors++;
216 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
217 number_colors++;
218 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
219 number_colors++;
220 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
221 (image->colorspace == CMYKColorspace))
222 number_colors++;
223 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy7d6d3d82014-11-09 17:00:16 +0000224 image->alpha_trait != UndefinedPixelTrait)
anthony805a2d42011-09-25 08:25:12 +0000225 number_colors++;
226
227 /*
228 Read string, to determine number of arguments needed,
229 */
230 p=arguments;
231 x=0;
232 while( *p != '\0' )
233 {
234 GetMagickToken(p,&p,token);
235 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000236 if ( isalpha((int) token[0]) || token[0] == '#' )
237 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000238 else
anthony805a2d42011-09-25 08:25:12 +0000239 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000240 }
anthony31f1bf72012-01-30 12:37:22 +0000241 /* control points and color values */
dirkb9dbc292015-07-26 09:50:00 +0000242 if ((x % (2+number_colors)) != 0)
243 {
244 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
245 "InvalidArgument","'%s': %s", "sparse-color",
246 "Invalid number of Arguments");
247 return( (Image *) NULL);
248 }
249 error=MagickFalse;
anthony31f1bf72012-01-30 12:37:22 +0000250 number_arguments=x;
anthony805a2d42011-09-25 08:25:12 +0000251
252 /* Allocate and fill in the floating point arguments */
253 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
254 sizeof(*sparse_arguments));
255 if (sparse_arguments == (double *) NULL) {
256 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
257 "MemoryAllocationFailed","%s","SparseColorOption");
cristyf432c632014-12-07 15:11:28 +0000258 return( (Image *) NULL);
anthony805a2d42011-09-25 08:25:12 +0000259 }
260 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
261 sizeof(*sparse_arguments));
262 p=arguments;
263 x=0;
264 while( *p != '\0' && x < number_arguments ) {
265 /* X coordinate */
266 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
267 if ( token[0] == '\0' ) break;
268 if ( isalpha((int) token[0]) || token[0] == '#' ) {
269 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000270 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000271 "Color found, instead of X-coord");
dirkb9dbc292015-07-26 09:50:00 +0000272 error=MagickTrue;
anthony805a2d42011-09-25 08:25:12 +0000273 break;
274 }
cristydbdd0e32011-11-04 23:29:40 +0000275 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000276 /* Y coordinate */
277 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
278 if ( token[0] == '\0' ) break;
279 if ( isalpha((int) token[0]) || token[0] == '#' ) {
280 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000281 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000282 "Color found, instead of Y-coord");
dirkb9dbc292015-07-26 09:50:00 +0000283 error=MagickTrue;
anthony805a2d42011-09-25 08:25:12 +0000284 break;
285 }
cristydbdd0e32011-11-04 23:29:40 +0000286 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000287 /* color name or function given in string argument */
288 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
289 if ( token[0] == '\0' ) break;
290 if ( isalpha((int) token[0]) || token[0] == '#' ) {
291 /* Color string given */
292 (void) QueryColorCompliance(token,AllCompliance,&color,
293 exception);
294 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
295 sparse_arguments[x++] = QuantumScale*color.red;
296 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
297 sparse_arguments[x++] = QuantumScale*color.green;
298 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
299 sparse_arguments[x++] = QuantumScale*color.blue;
300 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
301 (image->colorspace == CMYKColorspace))
302 sparse_arguments[x++] = QuantumScale*color.black;
303 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy7d6d3d82014-11-09 17:00:16 +0000304 image->alpha_trait != UndefinedPixelTrait)
anthony31f1bf72012-01-30 12:37:22 +0000305 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000306 }
anthony31f1bf72012-01-30 12:37:22 +0000307 else {
308 /* Colors given as a set of floating point values - experimental */
309 /* NB: token contains the first floating point value to use! */
310 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
311 {
312 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
313 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
314 break;
315 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
316 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000317 }
anthony31f1bf72012-01-30 12:37:22 +0000318 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
319 {
320 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
321 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
322 break;
323 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
324 token[0] = ','; /* used this token - get another */
325 }
326 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
327 {
328 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
329 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
330 break;
331 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
332 token[0] = ','; /* used this token - get another */
333 }
334 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
335 (image->colorspace == CMYKColorspace))
336 {
337 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
338 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
339 break;
340 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
341 token[0] = ','; /* used this token - get another */
342 }
343 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy7d6d3d82014-11-09 17:00:16 +0000344 image->alpha_trait != UndefinedPixelTrait)
anthony31f1bf72012-01-30 12:37:22 +0000345 {
346 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
347 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
348 break;
349 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
350 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000351 }
352 }
353 }
dirkb9dbc292015-07-26 09:50:00 +0000354 if (error != MagickFalse)
355 {
356 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
357 return((Image *) NULL);
358 }
359 if (number_arguments != x)
360 {
361 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
362 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
363 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
364 return((Image *) NULL);
365 }
anthony31f1bf72012-01-30 12:37:22 +0000366 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000367 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
368 exception);
369 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
370 return( sparse_image );
371}
372
373/*
374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375% %
376% %
377% %
anthony464f1c42012-04-22 08:51:01 +0000378% 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 +0000379% %
380% %
381% %
382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383%
384% CLISettingOptionInfo() applies a single settings option into a CLI wand
385% holding the image_info, draw_info, quantize_info structures that will be
386% used when processing the images.
387%
388% These options do no require images to be present in the CLI wand for them
389% to be able to be set, in which case they will generally be applied to image
390% that are read in later
anthony80c37752012-01-16 01:03:11 +0000391%
392% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000393% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000394%
anthony2052d272012-02-28 12:48:29 +0000395% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000396%
anthonyafa3dfc2012-03-03 11:31:30 +0000397% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000398% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000399%
400% A description of each parameter follows:
401%
anthony43f425d2012-02-26 12:58:58 +0000402% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000403%
anthonydcf510d2011-10-30 13:51:40 +0000404% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000405%
anthonye5fcd362012-04-09 04:02:09 +0000406% o arg1, arg2: optional argument strings to the operation
407% arg2 is currently only used by "-limit"
anthonydcf510d2011-10-30 13:51:40 +0000408%
anthony805a2d42011-09-25 08:25:12 +0000409*/
cristyfe831852013-02-12 14:56:07 +0000410WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonya322a832013-04-27 06:28:03 +0000411 const char *option,const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +0000412{
anthony30b912a2012-03-22 01:20:28 +0000413 ssize_t
414 parse; /* option argument parsing (string to value table lookup) */
415
anthonya322a832013-04-27 06:28:03 +0000416 const char /* percent escaped versions of the args */
417 *arg1,
418 *arg2;
anthony1afdc7a2011-10-05 11:54:28 +0000419
anthony2e4501b2012-03-30 04:41:54 +0000420#define _image_info (cli_wand->wand.image_info)
anthonya322a832013-04-27 06:28:03 +0000421#define _image (cli_wand->wand.images)
anthony2e4501b2012-03-30 04:41:54 +0000422#define _exception (cli_wand->wand.exception)
423#define _draw_info (cli_wand->draw_info)
424#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000425#define IfSetOption (*option=='-')
dirkb9dbc292015-07-26 09:50:00 +0000426#define ArgBoolean IfSetOption ? MagickTrue : MagickFalse
427#define ArgBooleanNot IfSetOption ? MagickFalse : MagickTrue
anthony24aa8822012-03-11 00:56:06 +0000428#define ArgBooleanString (IfSetOption?"true":"false")
429#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000430
anthonya322a832013-04-27 06:28:03 +0000431 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000432 assert(cli_wand->signature == MagickWandSignature);
433 assert(cli_wand->wand.signature == MagickWandSignature);
anthony4837ac22012-05-18 23:39:48 +0000434
anthonya322a832013-04-27 06:28:03 +0000435 if (IfMagickTrue(cli_wand->wand.debug))
436 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
437 "- Setting Option: %s \"%s\" \"%s\"", option,arg1n,arg2n);
438
439 arg1 = arg1n,
440 arg2 = arg2n;
441
442#if 1
anthony4837ac22012-05-18 23:39:48 +0000443#define _process_flags (cli_wand->process_flags)
444#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
445 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +0000446 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
447 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
448 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
449 /* Interpret Percent escapes in argument 1 */
450 if (arg1n != (char *) NULL) {
451 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
452 if (arg1 == (char *) NULL) {
453 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
454 arg1=arg1n; /* use the given argument as is */
455 }
456 }
457 if (arg2n != (char *) NULL) {
458 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
459 if (arg2 == (char *) NULL) {
460 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
461 arg2=arg2n; /* use the given argument as is */
462 }
463 }
464 }
465#undef _process_flags
466#undef _option_type
467#endif
468
anthonyafa3dfc2012-03-03 11:31:30 +0000469 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000470 {
471 case 'a':
472 {
anthonyafa3dfc2012-03-03 11:31:30 +0000473 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000474 {
anthony92c93bd2012-03-19 14:02:47 +0000475 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000476 break;
477 }
anthonyafa3dfc2012-03-03 11:31:30 +0000478 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000479 {
anthony464f1c42012-04-22 08:51:01 +0000480 CLIWandWarnReplaced("-draw 'affine ...'");
anthony74b1cfc2011-10-06 12:44:16 +0000481 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000482 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000483 else
anthony92c93bd2012-03-19 14:02:47 +0000484 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000485 break;
486 }
anthonyafa3dfc2012-03-03 11:31:30 +0000487 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000488 {
anthony92c93bd2012-03-19 14:02:47 +0000489 _image_info->antialias =
490 _draw_info->stroke_antialias =
491 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000492 break;
493 }
anthony31f1bf72012-01-30 12:37:22 +0000494 if (LocaleCompare("attenuate",option+1) == 0)
495 {
anthony7bcfe7f2012-03-30 14:01:22 +0000496 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000497 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
498 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000499 break;
500 }
anthonyafa3dfc2012-03-03 11:31:30 +0000501 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000502 {
anthony92c93bd2012-03-19 14:02:47 +0000503 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000504 break;
505 }
anthonyebb73a22012-03-22 14:25:52 +0000506 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000507 }
508 case 'b':
509 {
anthonyafa3dfc2012-03-03 11:31:30 +0000510 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000511 {
anthony92c93bd2012-03-19 14:02:47 +0000512 /* FUTURE: both _image_info attribute & ImageOption in use!
513 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000514 SyncImageSettings() used to set per-image attribute.
515
anthony92c93bd2012-03-19 14:02:47 +0000516 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000517 we should fall back to per-image background_color
518
519 At this time -background will 'wipe out' the per-image
520 background color!
521
522 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000523 */
anthony92c93bd2012-03-19 14:02:47 +0000524 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
cristyd7df81d2014-01-18 18:42:05 +0000525 (void) QueryColorCompliance(ArgOption(MogrifyBackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000526 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000527 break;
528 }
anthonyafa3dfc2012-03-03 11:31:30 +0000529 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000530 {
anthony52bef752012-03-27 13:54:47 +0000531 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000532 as it is actually rarely used except in direct convolve operations
533 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000534
535 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000536 */
anthony7bcfe7f2012-03-30 14:01:22 +0000537 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000538 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000539 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000540 break;
541 }
anthonyafa3dfc2012-03-03 11:31:30 +0000542 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000543 {
anthony72feaa62012-01-17 06:46:23 +0000544 /* Used as a image chromaticity setting
545 SyncImageSettings() used to set per-image attribute.
546 */
anthony92c93bd2012-03-19 14:02:47 +0000547 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000548 break;
549 }
anthonyafa3dfc2012-03-03 11:31:30 +0000550 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000551 {
anthonyafbaed72011-10-26 12:05:04 +0000552 /* Image chromaticity X,Y NB: Y=X if Y not defined
553 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000554 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000555 */
anthonyf42014d2012-03-25 09:53:06 +0000556 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000557 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000558 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000559 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000560 break;
561 }
anthonyafa3dfc2012-03-03 11:31:30 +0000562 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000563 {
anthony92c93bd2012-03-19 14:02:47 +0000564 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000565 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000566 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000567 */
anthony74b1cfc2011-10-06 12:44:16 +0000568 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000569 {
anthony92c93bd2012-03-19 14:02:47 +0000570 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000571 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000572 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000573 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000574 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000575 break;
576 }
anthony92c93bd2012-03-19 14:02:47 +0000577 (void) DeleteImageOption(_image_info,option+1);
cristyd7df81d2014-01-18 18:42:05 +0000578 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000579 &_image_info->border_color,_exception);
cristyd7df81d2014-01-18 18:42:05 +0000580 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000581 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000582 break;
583 }
anthonyafa3dfc2012-03-03 11:31:30 +0000584 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000585 {
anthony464f1c42012-04-22 08:51:01 +0000586 CLIWandWarnReplaced("-undercolor");
anthony975a8d72012-04-12 13:54:36 +0000587 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
anthonyfd706f92012-01-19 04:22:02 +0000588 break;
anthony805a2d42011-09-25 08:25:12 +0000589 }
anthonyebb73a22012-03-22 14:25:52 +0000590 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000591 }
592 case 'c':
593 {
anthonyafa3dfc2012-03-03 11:31:30 +0000594 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000595 {
596 MagickSizeType
597 limit;
598
anthony7bcfe7f2012-03-30 14:01:22 +0000599 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000600 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000601 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000602 if (LocaleCompare("unlimited",arg1) != 0)
603 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000604 (void) SetMagickResourceLimit(MemoryResource,limit);
605 (void) SetMagickResourceLimit(MapResource,2*limit);
606 break;
607 }
anthonyafa3dfc2012-03-03 11:31:30 +0000608 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000609 {
anthony92c93bd2012-03-19 14:02:47 +0000610 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000611 break;
612 }
anthonyafa3dfc2012-03-03 11:31:30 +0000613 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000614 {
anthonyafbaed72011-10-26 12:05:04 +0000615 /* Setting used for new images via AquireImage()
616 But also used as a SimpleImageOperator
617 Undefined colorspace means don't modify images on
618 read or as a operation */
cristy17ada022014-11-07 22:12:23 +0000619 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
620 ArgOption("undefined"));
anthony30b912a2012-03-22 01:20:28 +0000621 if (parse < 0)
cristy17ada022014-11-07 22:12:23 +0000622 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
623 arg1);
anthony30b912a2012-03-22 01:20:28 +0000624 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000625 break;
626 }
anthonyafa3dfc2012-03-03 11:31:30 +0000627 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000628 {
anthony92c93bd2012-03-19 14:02:47 +0000629 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000630 break;
631 }
anthonyafa3dfc2012-03-03 11:31:30 +0000632 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000633 {
anthony92c93bd2012-03-19 14:02:47 +0000634 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000635 SyncImageSettings() used to set per-image attribute. - REMOVE
636
anthonyafbaed72011-10-26 12:05:04 +0000637 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000638 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000639 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000640 */
anthonyebb73a22012-03-22 14:25:52 +0000641 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
642 ArgOption("undefined"));
643 if (parse < 0)
644 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
645 option,arg1);
646 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000647 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000648 break;
649 }
anthonyafa3dfc2012-03-03 11:31:30 +0000650 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000651 {
anthony92c93bd2012-03-19 14:02:47 +0000652 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000653 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000654 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000655
anthony92c93bd2012-03-19 14:02:47 +0000656 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000657 however the image attribute (for save) is set from the
658 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000659
660 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000661 */
anthonyebb73a22012-03-22 14:25:52 +0000662 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
663 ArgOption("undefined"));
664 if (parse < 0)
665 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
666 option,arg1);
667 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000668 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000669 break;
670 }
anthonyebb73a22012-03-22 14:25:52 +0000671 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000672 }
673 case 'd':
674 {
anthonyafa3dfc2012-03-03 11:31:30 +0000675 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000676 {
anthony72feaa62012-01-17 06:46:23 +0000677 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000678 arg1=ArgOption("none");
679 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
680 if (parse < 0)
681 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
682 option,arg1);
683 (void) SetLogEventMask(arg1);
684 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000685 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000686 break;
687 }
anthonyafa3dfc2012-03-03 11:31:30 +0000688 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000689 {
anthony24aa8822012-03-11 00:56:06 +0000690 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000691 {
anthony5f867ae2011-10-09 10:28:34 +0000692 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000693 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000694 else
anthony24aa8822012-03-11 00:56:06 +0000695 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000696 break;
697 }
anthony24aa8822012-03-11 00:56:06 +0000698 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000699 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000700 (void) DefineImageOption(_image_info,arg1);
dirkb9dbc292015-07-26 09:50:00 +0000701 else if (DeleteImageOption(_image_info,arg1) == MagickFalse)
anthonyebb73a22012-03-22 14:25:52 +0000702 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000703 break;
704 }
anthonyafa3dfc2012-03-03 11:31:30 +0000705 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000706 {
anthonyafbaed72011-10-26 12:05:04 +0000707 /* Only used for new images via AcquireImage()
708 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000709 */
anthonyebb73a22012-03-22 14:25:52 +0000710 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000711 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000712 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
713 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000714 break;
715 }
anthonyafa3dfc2012-03-03 11:31:30 +0000716 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000717 {
anthony92c93bd2012-03-19 14:02:47 +0000718 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000719 Basically as density can be in a XxY form!
720
721 SyncImageSettings() used to set per-image attribute.
722 */
anthony7bcfe7f2012-03-30 14:01:22 +0000723 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000724 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000725 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
726 (void) CloneString(&_image_info->density,ArgOption(NULL));
727 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000728 break;
729 }
anthonyafa3dfc2012-03-03 11:31:30 +0000730 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000731 {
anthony72feaa62012-01-17 06:46:23 +0000732 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
733 SyncImageSettings() used to set per-image attribute.
734 */
anthony7bcfe7f2012-03-30 14:01:22 +0000735 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000736 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000737 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000738 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000739 break;
740 }
anthonyafa3dfc2012-03-03 11:31:30 +0000741 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000742 {
anthony92c93bd2012-03-19 14:02:47 +0000743 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000744 arg1=ArgOption("undefined");
745 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
746 if (parse < 0)
747 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
748 option,arg1);
749 _draw_info->direction=(DirectionType) parse;
750 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000751 break;
752 }
anthonyafa3dfc2012-03-03 11:31:30 +0000753 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000754 {
anthony92c93bd2012-03-19 14:02:47 +0000755 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
756 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000757 break;
758 }
anthonyafa3dfc2012-03-03 11:31:30 +0000759 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000760 {
anthony72feaa62012-01-17 06:46:23 +0000761 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000762 arg1=ArgOption("undefined");
763 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
764 if (parse < 0)
765 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
766 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000767 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000768 break;
769 }
anthonyb1d483a2012-04-14 12:53:56 +0000770 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
771 {
772 /* FUTURE: this is only used by CompareImages() which is used
773 only by the "compare" CLI program at this time. */
774 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
775 if (IfMagickFalse(IsGeometry(arg1)))
776 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
777 (void) SetImageOption(_image_info,option+1,arg1);
778 break;
779 }
anthonyafa3dfc2012-03-03 11:31:30 +0000780 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000781 {
anthony92c93bd2012-03-19 14:02:47 +0000782 /* _image_info attr (on/off), _quantize_info attr (on/off)
783 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000784 FUTURE: merge the duality of the dithering options
785 */
cristycbda6112012-05-27 20:57:16 +0000786 _image_info->dither = ArgBoolean;
anthony92c93bd2012-03-19 14:02:47 +0000787 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
788 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
cristycbda6112012-05-27 20:57:16 +0000789 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000790 if (_quantize_info->dither_method == NoDitherMethod)
cristycbda6112012-05-27 20:57:16 +0000791 _image_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000792 break;
793 }
anthonyebb73a22012-03-22 14:25:52 +0000794 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000795 }
796 case 'e':
797 {
anthonyafa3dfc2012-03-03 11:31:30 +0000798 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000799 {
anthony92c93bd2012-03-19 14:02:47 +0000800 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
801 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000802 break;
803 }
anthonyafa3dfc2012-03-03 11:31:30 +0000804 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000805 {
anthony92c93bd2012-03-19 14:02:47 +0000806 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000807 arg1 = ArgOption("undefined");
808 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
809 if (parse < 0)
810 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
811 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000812 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000813 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000814 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000815 break;
816 }
anthonyafa3dfc2012-03-03 11:31:30 +0000817 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000818 {
anthony92c93bd2012-03-19 14:02:47 +0000819 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000820 break;
821 }
anthonyebb73a22012-03-22 14:25:52 +0000822 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000823 }
824 case 'f':
825 {
anthonyafa3dfc2012-03-03 11:31:30 +0000826 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000827 {
anthony92c93bd2012-03-19 14:02:47 +0000828 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000829 break;
830 }
anthonya322a832013-04-27 06:28:03 +0000831 if (LocaleCompare("features",option+1) == 0)
832 {
833 (void) SetImageOption(_image_info,"identify:features",
cristyf9b9b662013-05-25 12:50:16 +0000834 ArgBooleanString);
anthonya322a832013-04-27 06:28:03 +0000835 if (IfSetOption)
836 (void) SetImageArtifact(_image,"verbose","true");
837 break;
838 }
anthonyafa3dfc2012-03-03 11:31:30 +0000839 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000840 {
anthony92c93bd2012-03-19 14:02:47 +0000841 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000842 The original fill color is preserved if a fill-pattern is given.
843 That way it does not effect other operations that directly using
844 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000845 */
anthony72feaa62012-01-17 06:46:23 +0000846 MagickBooleanType
847 status;
anthony6dc09cd2011-10-12 08:56:49 +0000848
849 ExceptionInfo
850 *sans;
851
anthonyfd706f92012-01-19 04:22:02 +0000852 PixelInfo
853 color;
854
anthony2a0ec8c2012-03-24 04:35:56 +0000855 arg1 = ArgOption("none"); /* +fill turns it off! */
856 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000857 if (_draw_info->fill_pattern != (Image *) NULL)
858 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000859
860 /* is it a color or a image? -- ignore exceptions */
861 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +0000862 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000863 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000864
anthony7bcfe7f2012-03-30 14:01:22 +0000865 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +0000866 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000867 else
anthony92c93bd2012-03-19 14:02:47 +0000868 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000869 break;
870 }
anthonyafa3dfc2012-03-03 11:31:30 +0000871 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000872 {
anthony72feaa62012-01-17 06:46:23 +0000873 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +0000874 arg1 = ArgOption("undefined");
875 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
876 if (parse < 0)
877 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
878 option,arg1);
879 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000880 break;
881 }
anthonyafa3dfc2012-03-03 11:31:30 +0000882 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000883 {
anthony92c93bd2012-03-19 14:02:47 +0000884 (void) CloneString(&_draw_info->font,ArgOption(NULL));
885 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000886 break;
887 }
anthonyafa3dfc2012-03-03 11:31:30 +0000888 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000889 {
anthonydcf510d2011-10-30 13:51:40 +0000890 /* FUTURE: why the ping test, you could set ping after this! */
891 /*
anthony805a2d42011-09-25 08:25:12 +0000892 register const char
893 *q;
894
anthony24aa8822012-03-11 00:56:06 +0000895 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000896 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000897 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000898 */
anthony92c93bd2012-03-19 14:02:47 +0000899 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000900 break;
901 }
anthonyafa3dfc2012-03-03 11:31:30 +0000902 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000903 {
anthony72feaa62012-01-17 06:46:23 +0000904 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000905 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000906 SyncImageSettings() used to set per-image attribute.
907
anthony2a0ec8c2012-03-24 04:35:56 +0000908 FUTURE: Can't find anything else using _image_info->fuzz directly!
anthonya322a832013-04-27 06:28:03 +0000909 convert structure attribute to 'option' string
anthony6613bf32011-10-15 07:24:44 +0000910 */
anthony2a0ec8c2012-03-24 04:35:56 +0000911 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000912 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +0000913 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
914 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +0000915 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +0000916 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000917 break;
918 }
anthonyebb73a22012-03-22 14:25:52 +0000919 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000920 }
921 case 'g':
922 {
anthonyafa3dfc2012-03-03 11:31:30 +0000923 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000924 {
anthony72feaa62012-01-17 06:46:23 +0000925 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000926 arg1 = ArgOption("none");
927 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
928 if (parse < 0)
929 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
930 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +0000931 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +0000932 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000933 break;
934 }
anthonyafa3dfc2012-03-03 11:31:30 +0000935 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000936 {
anthonydcf510d2011-10-30 13:51:40 +0000937 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000938 SyncImageSettings() used to set per-image attribute.
939 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000940 */
anthonyf42014d2012-03-25 09:53:06 +0000941 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000942 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000943 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000944 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000945 break;
946 }
anthonyebb73a22012-03-22 14:25:52 +0000947 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000948 }
anthonyb1d483a2012-04-14 12:53:56 +0000949 case 'h':
950 {
951 if (LocaleCompare("highlight-color",option+1) == 0)
952 {
953 /* FUTURE: this is only used by CompareImages() which is used
954 only by the "compare" CLI program at this time. */
955 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
956 break;
957 }
958 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
959 }
anthony805a2d42011-09-25 08:25:12 +0000960 case 'i':
961 {
cristy70e9f682013-03-12 22:31:22 +0000962 if (LocaleCompare("intensity",option+1) == 0)
963 {
964 arg1 = ArgOption("undefined");
cristy8f84fdd2013-03-28 17:52:55 +0000965 parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
966 arg1);
cristy70e9f682013-03-12 22:31:22 +0000967 if (parse < 0)
cristy8f84fdd2013-03-28 17:52:55 +0000968 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityType",
969 option,arg1);
cristy70e9f682013-03-12 22:31:22 +0000970 (void) SetImageOption(_image_info,option+1,arg1);
971 break;
972 }
anthonyafa3dfc2012-03-03 11:31:30 +0000973 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000974 {
anthony72feaa62012-01-17 06:46:23 +0000975 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000976 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000977 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000978 */
cristy70e9f682013-03-12 22:31:22 +0000979 arg1 = ArgOption("undefined");
anthonyfe1aa782012-03-24 13:43:04 +0000980 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
981 if (parse < 0)
982 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
983 option,arg1);
984 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000985 break;
986 }
anthonyafa3dfc2012-03-03 11:31:30 +0000987 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000988 {
anthony92c93bd2012-03-19 14:02:47 +0000989 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000990 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000991 */
anthonyfe1aa782012-03-24 13:43:04 +0000992 arg1 = ArgOption("undefined");
993 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
994 if (parse < 0)
995 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
996 option,arg1);
997 _image_info->interlace=(InterlaceType) parse;
998 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000999 break;
1000 }
anthonyafa3dfc2012-03-03 11:31:30 +00001001 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001002 {
anthony7bcfe7f2012-03-30 14:01:22 +00001003 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001004 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001005 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1006 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001007 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001008 break;
1009 }
anthonyafa3dfc2012-03-03 11:31:30 +00001010 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001011 {
anthonyfd706f92012-01-19 04:22:02 +00001012 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001013 arg1 = ArgOption("undefined");
1014 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1015 if (parse < 0)
1016 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1017 option,arg1);
1018 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001019 break;
1020 }
anthonyafa3dfc2012-03-03 11:31:30 +00001021 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001022 {
anthony7bcfe7f2012-03-30 14:01:22 +00001023 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001024 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001025 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1026 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001027 break;
1028 }
anthonyebb73a22012-03-22 14:25:52 +00001029 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001030 }
1031 case 'k':
1032 {
anthonyafa3dfc2012-03-03 11:31:30 +00001033 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001034 {
anthony7bcfe7f2012-03-30 14:01:22 +00001035 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001036 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001037 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1038 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001039 break;
1040 }
anthonyebb73a22012-03-22 14:25:52 +00001041 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001042 }
1043 case 'l':
1044 {
anthonyafa3dfc2012-03-03 11:31:30 +00001045 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001046 {
anthony72feaa62012-01-17 06:46:23 +00001047 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001048 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001049 break;
1050 }
anthony756cd0d2012-04-08 12:41:44 +00001051 if (LocaleCompare("limit",option+1) == 0)
1052 {
1053 MagickSizeType
1054 limit;
1055
1056 limit=MagickResourceInfinity;
1057 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1058 if ( parse < 0 )
1059 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1060 option,arg1);
1061 if (LocaleCompare("unlimited",arg2) != 0)
1062 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1063 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1064 break;
1065 }
anthonyafa3dfc2012-03-03 11:31:30 +00001066 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001067 {
anthonyfe1aa782012-03-24 13:43:04 +00001068 if (IfSetOption) {
1069 if ((strchr(arg1,'%') == (char *) NULL))
1070 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001071 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001072 }
anthony805a2d42011-09-25 08:25:12 +00001073 break;
1074 }
anthony975a8d72012-04-12 13:54:36 +00001075 if (LocaleCompare("lowlight-color",option+1) == 0)
1076 {
anthonyb1d483a2012-04-14 12:53:56 +00001077 /* FUTURE: this is only used by CompareImages() which is used
1078 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001079 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1080 break;
1081 }
anthonyafa3dfc2012-03-03 11:31:30 +00001082 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001083 {
anthony72feaa62012-01-17 06:46:23 +00001084 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001085 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001086 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001087 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1088 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001089 break;
1090 }
anthonyebb73a22012-03-22 14:25:52 +00001091 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001092 }
1093 case 'm':
1094 {
anthonyafa3dfc2012-03-03 11:31:30 +00001095 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001096 {
anthony72feaa62012-01-17 06:46:23 +00001097 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001098 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
cristyd7df81d2014-01-18 18:42:05 +00001099 (void) QueryColorCompliance(ArgOption(MogrifyMatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001100 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001101 break;
anthonycd358fc2012-04-16 13:59:03 +00001102 }
anthonyb1d483a2012-04-14 12:53:56 +00001103 if (LocaleCompare("metric",option+1) == 0)
1104 {
1105 /* FUTURE: this is only used by CompareImages() which is used
1106 only by the "compare" CLI program at this time. */
1107 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1108 if ( parse < 0 )
1109 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1110 option,arg1);
1111 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001112 break;
anthony805a2d42011-09-25 08:25:12 +00001113 }
cristybd4a3c22014-01-07 15:09:37 +00001114 if (LocaleCompare("moments",option+1) == 0)
1115 {
1116 (void) SetImageOption(_image_info,"identify:moments",
1117 ArgBooleanString);
1118 if (IfSetOption)
1119 (void) SetImageArtifact(_image,"verbose","true");
1120 break;
1121 }
anthonyafa3dfc2012-03-03 11:31:30 +00001122 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001123 {
anthony92c93bd2012-03-19 14:02:47 +00001124 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001125 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001126 break;
1127 }
anthonyafa3dfc2012-03-03 11:31:30 +00001128 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001129 {
anthony24aa8822012-03-11 00:56:06 +00001130 /* Setting (used by some input coders!) -- why?
1131 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001132 */
anthony92c93bd2012-03-19 14:02:47 +00001133 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001134 break;
1135 }
anthonyebb73a22012-03-22 14:25:52 +00001136 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001137 }
1138 case 'o':
1139 {
anthonyafa3dfc2012-03-03 11:31:30 +00001140 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001141 {
anthony72feaa62012-01-17 06:46:23 +00001142 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001143 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001144 FUTURE: make set meta-data operator instead.
1145 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001146 */
anthony7bc87992012-03-25 02:32:51 +00001147 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1148 ArgOption("undefined"));
1149 if (parse < 0)
1150 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1151 option,arg1);
1152 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001153 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001154 break;
1155 }
anthonyebb73a22012-03-22 14:25:52 +00001156 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001157 }
1158 case 'p':
1159 {
anthonyafa3dfc2012-03-03 11:31:30 +00001160 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001161 {
anthony7bc87992012-03-25 02:32:51 +00001162 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001163 SyncImageSettings() used to set per-image attribute. ?????
1164 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001165 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001166 */
anthony805a2d42011-09-25 08:25:12 +00001167 char
1168 *canonical_page,
cristy151b66d2015-04-15 10:50:31 +00001169 page[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00001170
1171 const char
1172 *image_option;
1173
1174 MagickStatusType
1175 flags;
1176
1177 RectangleInfo
1178 geometry;
1179
anthonydcf510d2011-10-30 13:51:40 +00001180 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001181 {
anthony92c93bd2012-03-19 14:02:47 +00001182 (void) DeleteImageOption(_image_info,option+1);
1183 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001184 break;
1185 }
1186 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001187 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001188 if (image_option != (const char *) NULL)
1189 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001190 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001191 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1192 canonical_page=DestroyString(canonical_page);
cristy151b66d2015-04-15 10:50:31 +00001193 (void) FormatLocaleString(page,MagickPathExtent,"%lux%lu",
anthony805a2d42011-09-25 08:25:12 +00001194 (unsigned long) geometry.width,(unsigned long) geometry.height);
1195 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
cristy151b66d2015-04-15 10:50:31 +00001196 (void) FormatLocaleString(page,MagickPathExtent,"%lux%lu%+ld%+ld",
anthony805a2d42011-09-25 08:25:12 +00001197 (unsigned long) geometry.width,(unsigned long) geometry.height,
1198 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001199 (void) SetImageOption(_image_info,option+1,page);
1200 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001201 break;
1202 }
anthonyafa3dfc2012-03-03 11:31:30 +00001203 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001204 {
anthony92c93bd2012-03-19 14:02:47 +00001205 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001206 break;
1207 }
anthonyafa3dfc2012-03-03 11:31:30 +00001208 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001209 {
anthonyf42014d2012-03-25 09:53:06 +00001210 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001211 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001212 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1213 _image_info->pointsize =
1214 _draw_info->pointsize =
1215 StringToDouble(arg1,(char **) NULL);
1216 }
1217 else {
1218 _image_info->pointsize=0.0; /* unset pointsize */
1219 _draw_info->pointsize=12.0;
1220 }
anthony805a2d42011-09-25 08:25:12 +00001221 break;
1222 }
anthonyafa3dfc2012-03-03 11:31:30 +00001223 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001224 {
anthonyf42014d2012-03-25 09:53:06 +00001225 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001226 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001227 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1228 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001229 break;
1230 }
anthonydcf510d2011-10-30 13:51:40 +00001231 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001232 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001233 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001234 {
anthony92c93bd2012-03-19 14:02:47 +00001235 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001236 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001237 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001238 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001239 break;
1240 }
anthonydcf510d2011-10-30 13:51:40 +00001241 */
anthonyebb73a22012-03-22 14:25:52 +00001242 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001243 }
1244 case 'q':
1245 {
anthonyafa3dfc2012-03-03 11:31:30 +00001246 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001247 {
anthony7bcfe7f2012-03-30 14:01:22 +00001248 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001249 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001250 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1251 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001252 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001253 break;
1254 }
anthonyafa3dfc2012-03-03 11:31:30 +00001255 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001256 {
anthony92c93bd2012-03-19 14:02:47 +00001257 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001258 arg1=ArgOption("undefined");
1259 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1260 if (parse < 0)
1261 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1262 option,arg1);
1263 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001264 break;
1265 }
anthonyafa3dfc2012-03-03 11:31:30 +00001266 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001267 {
anthonyf42014d2012-03-25 09:53:06 +00001268 /* FUTURE: if two -quiet is performed you can not do +quiet!
1269 This needs to be checked over thoughly.
1270 */
anthony805a2d42011-09-25 08:25:12 +00001271 static WarningHandler
1272 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001273
anthonyafbaed72011-10-26 12:05:04 +00001274 WarningHandler
1275 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001276
anthonyafbaed72011-10-26 12:05:04 +00001277 if ( tmp != (WarningHandler) NULL)
1278 warning_handler = tmp; /* remember the old handler */
1279 if (!IfSetOption) /* set the old handler */
1280 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001281 break;
1282 }
anthonyebb73a22012-03-22 14:25:52 +00001283 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001284 }
1285 case 'r':
1286 {
anthonyafa3dfc2012-03-03 11:31:30 +00001287 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001288 {
anthonydcf510d2011-10-30 13:51:40 +00001289 /* Image chromaticity X,Y NB: Y=X if Y not defined
1290 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001291 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001292 */
anthonyf42014d2012-03-25 09:53:06 +00001293 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001294 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001295 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001296 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001297 break;
1298 }
cristyb0f7a182012-04-06 23:33:11 +00001299 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001300 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001301 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001302 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001303 {
anthony92c93bd2012-03-19 14:02:47 +00001304 /* _draw_info only setting */
1305 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001306 break;
1307 }
anthony756cd0d2012-04-08 12:41:44 +00001308 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1309 {
1310 /* link image and setting stacks - option is itself saved on stack! */
1311 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1312 break;
1313 }
anthonyebb73a22012-03-22 14:25:52 +00001314 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001315 }
1316 case 's':
1317 {
anthonyafa3dfc2012-03-03 11:31:30 +00001318 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001319 {
anthonyafbaed72011-10-26 12:05:04 +00001320 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001321 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001322 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001323 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001324 break;
1325 }
anthonyafa3dfc2012-03-03 11:31:30 +00001326 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001327 {
anthonyf42014d2012-03-25 09:53:06 +00001328 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001329 What ??? Why ????
1330 */
anthony7bcfe7f2012-03-30 14:01:22 +00001331 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001332 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001333 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1334 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001335 break;
1336 }
anthonyafa3dfc2012-03-03 11:31:30 +00001337 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001338 {
anthony7bcfe7f2012-03-30 14:01:22 +00001339 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001340 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001341 SetRandomSecretKey(
cristya30f8e62013-02-19 15:03:45 +00001342 IfSetOption ? (unsigned long) StringToUnsignedLong(arg1)
1343 : (unsigned long) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001344 break;
1345 }
anthonyafa3dfc2012-03-03 11:31:30 +00001346 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001347 {
anthony92c93bd2012-03-19 14:02:47 +00001348 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001349 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001350 */
anthony92c93bd2012-03-19 14:02:47 +00001351 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001352 break;
1353 }
anthonyafa3dfc2012-03-03 11:31:30 +00001354 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001355 {
anthonyf42014d2012-03-25 09:53:06 +00001356 arg1=ArgOption("undefined");
1357 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1358 if (parse < 0)
1359 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1360 option,arg1);
1361 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001362 break;
1363 }
anthonyafa3dfc2012-03-03 11:31:30 +00001364 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001365 {
anthonyafbaed72011-10-26 12:05:04 +00001366 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001367 UPDATE: ensure stroke color is not destroyed is a pattern
1368 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001369 */
anthony72feaa62012-01-17 06:46:23 +00001370 MagickBooleanType
1371 status;
anthonyafbaed72011-10-26 12:05:04 +00001372
1373 ExceptionInfo
1374 *sans;
1375
anthonyfd706f92012-01-19 04:22:02 +00001376 PixelInfo
1377 color;
1378
anthony2a0ec8c2012-03-24 04:35:56 +00001379 arg1 = ArgOption("none"); /* +fill turns it off! */
1380 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001381 if (_draw_info->stroke_pattern != (Image *) NULL)
1382 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001383
1384 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001385 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001386 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001387 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001388
anthony7bcfe7f2012-03-30 14:01:22 +00001389 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001390 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001391 else
anthony92c93bd2012-03-19 14:02:47 +00001392 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001393 break;
1394 }
anthonyafa3dfc2012-03-03 11:31:30 +00001395 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001396 {
anthony7bcfe7f2012-03-30 14:01:22 +00001397 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001398 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001399 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1400 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001401 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001402 break;
1403 }
anthonyafa3dfc2012-03-03 11:31:30 +00001404 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001405 {
anthonyf42014d2012-03-25 09:53:06 +00001406 arg1=ArgOption("undefined");
1407 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1408 if (parse < 0)
1409 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1410 option,arg1);
1411 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001412 break;
1413 }
anthonycd358fc2012-04-16 13:59:03 +00001414#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001415 if (LocaleCompare("subimage-search",option+1) == 0)
1416 {
1417 /* FUTURE: this is only used by CompareImages() which is used
1418 only by the "compare" CLI program at this time. */
1419 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1420 break;
1421 }
anthonycd358fc2012-04-16 13:59:03 +00001422#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001423 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001424 {
anthonyf42014d2012-03-25 09:53:06 +00001425 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001426 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001427 break;
1428 }
anthonyebb73a22012-03-22 14:25:52 +00001429 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001430 }
1431 case 't':
1432 {
anthonyafa3dfc2012-03-03 11:31:30 +00001433 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001434 {
anthony72feaa62012-01-17 06:46:23 +00001435 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001436 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001437 break;
1438 }
anthonyafa3dfc2012-03-03 11:31:30 +00001439 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001440 {
anthony4837ac22012-05-18 23:39:48 +00001441 /* Note: arguments do not have percent escapes expanded */
anthony52bef752012-03-27 13:54:47 +00001442 /* FUTURE: move _image_info string to option splay-tree
1443 Other than "montage" what uses "texture" ????
1444 */
anthony92c93bd2012-03-19 14:02:47 +00001445 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001446 break;
1447 }
anthonyafa3dfc2012-03-03 11:31:30 +00001448 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001449 {
anthony4837ac22012-05-18 23:39:48 +00001450 /* Note: arguments do not have percent escapes expanded */
anthony92c93bd2012-03-19 14:02:47 +00001451 _draw_info->fill_pattern=IfSetOption
1452 ?GetImageCache(_image_info,arg1,_exception)
1453 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001454 break;
1455 }
anthonyafa3dfc2012-03-03 11:31:30 +00001456 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001457 {
anthony72feaa62012-01-17 06:46:23 +00001458 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001459 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001460 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001461 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1462 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001463 break;
1464 }
anthonyafa3dfc2012-03-03 11:31:30 +00001465 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001466 {
anthony92c93bd2012-03-19 14:02:47 +00001467 /* FUTURE: both _image_info attribute & ImageOption in use!
1468 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001469 SyncImageSettings() used to set per-image attribute.
1470
anthonyafbaed72011-10-26 12:05:04 +00001471 Note that +transparent-color, means fall-back to image
1472 attribute so ImageOption is deleted, not set to a default.
1473 */
anthony7bcfe7f2012-03-30 14:01:22 +00001474 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001475 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001476 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001477 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001478 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001479 break;
1480 }
anthonyafa3dfc2012-03-03 11:31:30 +00001481 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001482 {
anthony92c93bd2012-03-19 14:02:47 +00001483 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1484 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001485 break;
1486 }
anthonyafa3dfc2012-03-03 11:31:30 +00001487 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001488 {
anthony72feaa62012-01-17 06:46:23 +00001489 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001490 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1491 ArgOption("undefined"));
1492 if (parse < 0)
1493 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1494 option,arg1);
1495 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001496 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001497 break;
1498 }
anthonyebb73a22012-03-22 14:25:52 +00001499 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001500 }
1501 case 'u':
1502 {
anthonyafa3dfc2012-03-03 11:31:30 +00001503 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001504 {
anthony92c93bd2012-03-19 14:02:47 +00001505 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001506 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001507 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001508 break;
1509 }
anthonyafa3dfc2012-03-03 11:31:30 +00001510 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001511 {
anthony72feaa62012-01-17 06:46:23 +00001512 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001513 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001514 FUTURE: this probably should be part of the density setting
1515 */
anthony52bef752012-03-27 13:54:47 +00001516 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1517 ArgOption("undefined"));
1518 if (parse < 0)
1519 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1520 option,arg1);
1521 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001522 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001523 break;
1524 }
anthonyebb73a22012-03-22 14:25:52 +00001525 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001526 }
1527 case 'v':
1528 {
anthonyafa3dfc2012-03-03 11:31:30 +00001529 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001530 {
anthony24aa8822012-03-11 00:56:06 +00001531 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001532 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001533 */
anthony92c93bd2012-03-19 14:02:47 +00001534 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1535 _image_info->verbose= ArgBoolean;
1536 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001537 break;
1538 }
anthonyafa3dfc2012-03-03 11:31:30 +00001539 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001540 {
anthony92c93bd2012-03-19 14:02:47 +00001541 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001542 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001543 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001544 */
anthony92c93bd2012-03-19 14:02:47 +00001545 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001546 break;
1547 }
anthonyafa3dfc2012-03-03 11:31:30 +00001548 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001549 {
anthonyfd706f92012-01-19 04:22:02 +00001550 /* SyncImageSettings() used to set per-image attribute.
1551 This is VERY deep in the image caching structure.
1552 */
anthony52bef752012-03-27 13:54:47 +00001553 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1554 ArgOption("undefined"));
1555 if (parse < 0)
1556 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1557 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001558 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001559 break;
1560 }
anthonyebb73a22012-03-22 14:25:52 +00001561 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001562 }
1563 case 'w':
1564 {
anthonyafa3dfc2012-03-03 11:31:30 +00001565 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001566 {
dirk5acf7022015-07-30 18:37:03 +00001567 ssize_t
1568 weight;
1569
1570 weight=ParseCommandOption(MagickWeightOptions,MagickFalse,arg1);
1571 if (weight == -1)
1572 weight=StringToUnsignedLong(arg1);
1573 _draw_info->weight=(size_t) weight;
anthonyab3a50c2011-10-27 11:48:57 +00001574 break;
1575 }
anthonyafa3dfc2012-03-03 11:31:30 +00001576 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001577 {
anthony72feaa62012-01-17 06:46:23 +00001578 /* Used as a image chromaticity setting
1579 SyncImageSettings() used to set per-image attribute.
1580 */
anthony52bef752012-03-27 13:54:47 +00001581 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001582 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001583 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1584 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001585 break;
1586 }
anthonyebb73a22012-03-22 14:25:52 +00001587 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001588 }
1589 default:
anthonyebb73a22012-03-22 14:25:52 +00001590 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001591 }
anthony24aa8822012-03-11 00:56:06 +00001592
anthony4837ac22012-05-18 23:39:48 +00001593 /* clean up percent escape interpreted strings */
cristy862fc612015-02-16 20:49:10 +00001594 if ((arg1 && arg1n) && (arg1 != arg1n ))
1595 arg1=DestroyString((char *) arg1);
1596 if ((arg2 && arg2n) && (arg2 != arg2n ))
1597 arg2=DestroyString((char *) arg2);
anthony4837ac22012-05-18 23:39:48 +00001598
anthony92c93bd2012-03-19 14:02:47 +00001599#undef _image_info
1600#undef _exception
1601#undef _draw_info
1602#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001603#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001604#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001605#undef ArgBooleanNot
1606#undef ArgBooleanString
1607#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001608
anthony31f1bf72012-01-30 12:37:22 +00001609 return;
anthony805a2d42011-09-25 08:25:12 +00001610}
1611
1612/*
1613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1614% %
1615% %
1616% %
anthony43f425d2012-02-26 12:58:58 +00001617+ 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 +00001618% %
1619% %
1620% %
1621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622%
anthonyc7994672012-11-17 05:33:27 +00001623% CLISimpleOperatorImages() applys one simple image operation given to all
1624% the images in the CLI wand, using any per-image or global settings that was
1625% previously saved in the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001626%
anthonyc7994672012-11-17 05:33:27 +00001627% It is assumed that any such settings are up-to-date.
anthony805a2d42011-09-25 08:25:12 +00001628%
anthony7a4d6102012-07-01 09:48:25 +00001629% The format of the WandSimpleOperatorImages method is:
anthony805a2d42011-09-25 08:25:12 +00001630%
cristy52b632a2014-11-08 00:31:34 +00001631% MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,const char *option,
cristy2c57b742014-10-31 00:40:34 +00001632% const char *arg1, const char *arg2,ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +00001633%
1634% A description of each parameter follows:
1635%
anthony43f425d2012-02-26 12:58:58 +00001636% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001637%
anthonyfd706f92012-01-19 04:22:02 +00001638% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001639%
anthonyfd706f92012-01-19 04:22:02 +00001640% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001641%
anthony805a2d42011-09-25 08:25:12 +00001642*/
anthony31f1bf72012-01-30 12:37:22 +00001643
1644/*
anthonyc7994672012-11-17 05:33:27 +00001645 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1646 image operation to the current image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001647
1648 The image in the list may be modified in three different ways...
1649 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1650 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1651 * one image replace by a list of images (-separate and -crop only!)
1652
anthonyafa3dfc2012-03-03 11:31:30 +00001653 In each case the result replaces the single original image in the list, as
1654 well as the pointer to the modified image (last image added if replaced by a
1655 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001656
1657 As the image pointed to may be replaced, the first image in the list may
1658 also change. GetFirstImageInList() should be used by caller if they wish
1659 return the Image pointer to the first image in list.
1660*/
cristyfe831852013-02-12 14:56:07 +00001661static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
cristy2c57b742014-10-31 00:40:34 +00001662 const char *option, const char *arg1n, const char *arg2n,
1663 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +00001664{
1665 Image *
1666 new_image;
1667
anthony805a2d42011-09-25 08:25:12 +00001668 GeometryInfo
1669 geometry_info;
1670
1671 RectangleInfo
1672 geometry;
1673
1674 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001675 flags;
1676
anthony92c93bd2012-03-19 14:02:47 +00001677 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001678 parse;
anthony92c93bd2012-03-19 14:02:47 +00001679
anthonya322a832013-04-27 06:28:03 +00001680 const char /* percent escaped versions of the args */
anthony964d28e2012-05-17 23:39:46 +00001681 *arg1,
1682 *arg2;
1683
anthonya322a832013-04-27 06:28:03 +00001684#define _image_info (cli_wand->wand.image_info)
1685#define _image (cli_wand->wand.images)
1686#define _exception (cli_wand->wand.exception)
1687#define _draw_info (cli_wand->draw_info)
1688#define _quantize_info (cli_wand->quantize_info)
1689#define _process_flags (cli_wand->process_flags)
1690#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
1691#define IfNormalOp (*option=='-')
1692#define IfPlusOp (*option!='-')
dirkb9dbc292015-07-26 09:50:00 +00001693#define IsNormalOp IfNormalOp ? MagickTrue : MagickFalse
1694#define IsPlusOp IfNormalOp ? MagickFalse : MagickTrue
anthonyfd706f92012-01-19 04:22:02 +00001695
anthony43f425d2012-02-26 12:58:58 +00001696 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001697 assert(cli_wand->signature == MagickWandSignature);
1698 assert(cli_wand->wand.signature == MagickWandSignature);
anthony5330ae02012-03-20 14:17:01 +00001699 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001700 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001701 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001702
anthony964d28e2012-05-17 23:39:46 +00001703 arg1 = arg1n,
1704 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00001705
1706 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00001707 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1708 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1709 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1710 /* Interpret Percent escapes in argument 1 */
1711 if (arg1n != (char *) NULL) {
1712 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1713 if (arg1 == (char *) NULL) {
1714 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1715 arg1=arg1n; /* use the given argument as is */
1716 }
1717 }
1718 if (arg2n != (char *) NULL) {
1719 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1720 if (arg2 == (char *) NULL) {
1721 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1722 arg2=arg2n; /* use the given argument as is */
1723 }
1724 }
1725 }
anthony4837ac22012-05-18 23:39:48 +00001726#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00001727#undef _option_type
1728
1729#if 0
1730 (void) FormatLocaleFile(stderr,
1731 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1732#endif
anthony805a2d42011-09-25 08:25:12 +00001733
cristyf432c632014-12-07 15:11:28 +00001734 new_image = (Image *) NULL; /* the replacement image, if not null at end */
anthony964d28e2012-05-17 23:39:46 +00001735 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001736
anthonyafa3dfc2012-03-03 11:31:30 +00001737 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001738 {
1739 case 'a':
1740 {
anthonyafa3dfc2012-03-03 11:31:30 +00001741 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001742 {
anthonyfd706f92012-01-19 04:22:02 +00001743 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001744 if ((flags & (RhoValue|SigmaValue)) == 0)
1745 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001746 if ((flags & SigmaValue) == 0)
1747 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001748 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001749 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001750 break;
1751 }
anthonyafa3dfc2012-03-03 11:31:30 +00001752 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001753 {
anthonyfe1aa782012-03-24 13:43:04 +00001754 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001755 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001756 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1757 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1758 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001759 _exception);
anthony805a2d42011-09-25 08:25:12 +00001760 break;
1761 }
anthonyafa3dfc2012-03-03 11:31:30 +00001762 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001763 {
anthonyfd706f92012-01-19 04:22:02 +00001764 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001765 if ((flags & (RhoValue|SigmaValue)) == 0)
1766 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001767 if ((flags & SigmaValue) == 0)
1768 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001769 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001770 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001771 break;
1772 }
anthonyafa3dfc2012-03-03 11:31:30 +00001773 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001774 {
cristy288a3532012-08-28 00:19:44 +00001775 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001776 if (parse < 0)
cristyb15b06c2012-08-28 11:36:48 +00001777 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
cristy4366cb82014-09-13 17:57:26 +00001778 option,arg1);
1779 (void) SetImageAlphaChannel(_image,(AlphaChannelOption) parse,
cristy61d844e2014-09-14 00:30:34 +00001780 _exception);
anthony805a2d42011-09-25 08:25:12 +00001781 break;
1782 }
anthonyafa3dfc2012-03-03 11:31:30 +00001783 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001784 {
1785 char
cristy151b66d2015-04-15 10:50:31 +00001786 geometry[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00001787
anthony805a2d42011-09-25 08:25:12 +00001788 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001789 flags=ParseGeometry(arg1,&geometry_info);
cristy8592b052013-02-07 01:24:54 +00001790 if (flags == 0)
anthony22de2722012-04-19 14:43:00 +00001791 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001792 if ((flags & SigmaValue) == 0)
1793 geometry_info.sigma=geometry_info.rho;
anthony964d28e2012-05-17 23:39:46 +00001794 (void) CloneString(&_draw_info->text,arg2);
cristy151b66d2015-04-15 10:50:31 +00001795 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
anthony805a2d42011-09-25 08:25:12 +00001796 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001797 (void) CloneString(&_draw_info->geometry,geometry);
1798 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001799 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001800 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001801 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001802 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001803 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001804 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001805 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001806 (void) AnnotateImage(_image,_draw_info,_exception);
1807 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001808 break;
1809 }
anthonyafa3dfc2012-03-03 11:31:30 +00001810 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001811 {
anthony92c93bd2012-03-19 14:02:47 +00001812 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001813 break;
1814 }
anthonyafa3dfc2012-03-03 11:31:30 +00001815 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001816 {
anthony92c93bd2012-03-19 14:02:47 +00001817 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001818 break;
1819 }
anthonyafa3dfc2012-03-03 11:31:30 +00001820 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001821 {
cristyfa5f6c72013-01-01 14:37:35 +00001822 new_image=AutoOrientImage(_image,_image->orientation,_exception);
anthony805a2d42011-09-25 08:25:12 +00001823 break;
1824 }
anthonyebb73a22012-03-22 14:25:52 +00001825 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001826 }
1827 case 'b':
1828 {
anthonyafa3dfc2012-03-03 11:31:30 +00001829 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001830 {
anthony7bcfe7f2012-03-30 14:01:22 +00001831 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001832 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001833 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001834 break;
1835 }
anthonyafa3dfc2012-03-03 11:31:30 +00001836 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001837 {
anthony805a2d42011-09-25 08:25:12 +00001838 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001839 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001840 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001841 if ((flags & RhoValue) == 0)
1842 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001843 }
anthony92c93bd2012-03-19 14:02:47 +00001844 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001845 break;
1846 }
anthonyafa3dfc2012-03-03 11:31:30 +00001847 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001848 {
anthonyfd706f92012-01-19 04:22:02 +00001849 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001850 if ((flags & (RhoValue|SigmaValue)) == 0)
1851 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001852 if ((flags & SigmaValue) == 0)
1853 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001854 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1855 _exception);
anthony805a2d42011-09-25 08:25:12 +00001856 break;
1857 }
anthonyafa3dfc2012-03-03 11:31:30 +00001858 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001859 {
anthony31f1bf72012-01-30 12:37:22 +00001860 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001861 compose;
1862
1863 const char*
anthony5f867ae2011-10-09 10:28:34 +00001864 value;
1865
anthony22de2722012-04-19 14:43:00 +00001866 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
cristy64ad8f92012-08-03 00:58:24 +00001867 if ((flags & (WidthValue | HeightValue)) == 0)
anthony5330ae02012-03-20 14:17:01 +00001868 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy64ad8f92012-08-03 00:58:24 +00001869 compose=OverCompositeOp;
anthony92c93bd2012-03-19 14:02:47 +00001870 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001871 if (value != (const char *) NULL)
cristy64ad8f92012-08-03 00:58:24 +00001872 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1873 MagickFalse,value);
anthony92c93bd2012-03-19 14:02:47 +00001874 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001875 break;
1876 }
anthonyafa3dfc2012-03-03 11:31:30 +00001877 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001878 {
1879 double
1880 brightness,
1881 contrast;
1882
1883 GeometryInfo
1884 geometry_info;
1885
1886 MagickStatusType
1887 flags;
1888
anthonyfd706f92012-01-19 04:22:02 +00001889 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001890 if ((flags & RhoValue) == 0)
1891 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001892 brightness=geometry_info.rho;
1893 contrast=0.0;
1894 if ((flags & SigmaValue) != 0)
1895 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001896 (void) BrightnessContrastImage(_image,brightness,contrast,
1897 _exception);
anthony805a2d42011-09-25 08:25:12 +00001898 break;
1899 }
anthonyebb73a22012-03-22 14:25:52 +00001900 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001901 }
1902 case 'c':
1903 {
cristy4ceadb82014-03-29 15:30:43 +00001904 if (LocaleCompare("canny",option+1) == 0)
1905 {
1906 flags=ParseGeometry(arg1,&geometry_info);
1907 if ((flags & (RhoValue|SigmaValue)) == 0)
1908 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1909 if ((flags & SigmaValue) == 0)
1910 geometry_info.sigma=1.0;
1911 if ((flags & XiValue) == 0)
cristy2fc10e52014-04-26 14:13:53 +00001912 geometry_info.xi=10;
cristy4ceadb82014-03-29 15:30:43 +00001913 if ((flags & PsiValue) == 0)
cristy2fc10e52014-04-26 14:13:53 +00001914 geometry_info.psi=30;
cristy2b72f792014-03-29 21:58:42 +00001915 if ((flags & PercentValue) != 0)
1916 {
cristy41814f22014-04-09 20:53:11 +00001917 geometry_info.xi/=100.0;
1918 geometry_info.psi/=100.0;
cristy2b72f792014-03-29 21:58:42 +00001919 }
cristy41814f22014-04-09 20:53:11 +00001920 new_image=CannyEdgeImage(_image,geometry_info.rho,geometry_info.sigma,
1921 geometry_info.xi,geometry_info.psi,_exception);
cristy4ceadb82014-03-29 15:30:43 +00001922 break;
1923 }
anthonyafa3dfc2012-03-03 11:31:30 +00001924 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001925 {
anthony4837ac22012-05-18 23:39:48 +00001926 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001927 char
1928 *color_correction_collection;
1929
1930 /*
1931 Color correct with a color decision list.
1932 */
cristy3a5987c2013-11-07 14:18:46 +00001933 color_correction_collection=FileToString(arg1,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001934 if (color_correction_collection == (char *) NULL)
1935 break;
anthony92c93bd2012-03-19 14:02:47 +00001936 (void) ColorDecisionListImage(_image,color_correction_collection,
1937 _exception);
anthony805a2d42011-09-25 08:25:12 +00001938 break;
1939 }
cristy17ada022014-11-07 22:12:23 +00001940 if (LocaleCompare("channel",option+1) == 0)
1941 {
1942 if (IfPlusOp)
1943 {
cristybcd59342015-06-07 14:07:19 +00001944 (void) SetPixelChannelMask(_image,DefaultChannels);
cristy17ada022014-11-07 22:12:23 +00001945 break;
1946 }
1947 parse=ParseChannelOption(arg1);
1948 if (parse < 0)
1949 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
1950 option,arg1);
cristybcd59342015-06-07 14:07:19 +00001951 (void) SetPixelChannelMask(_image,(ChannelType) parse);
cristy17ada022014-11-07 22:12:23 +00001952 break;
1953 }
anthonyafa3dfc2012-03-03 11:31:30 +00001954 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001955 {
anthonyfd706f92012-01-19 04:22:02 +00001956 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001957 if ((flags & (RhoValue|SigmaValue)) == 0)
1958 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001959 if ((flags & SigmaValue) == 0)
1960 geometry_info.sigma=1.0;
1961 if ((flags & XiValue) == 0)
1962 geometry_info.xi=1.0;
cristyee3f7522012-12-21 19:27:44 +00001963 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1964 _exception);
anthony805a2d42011-09-25 08:25:12 +00001965 break;
1966 }
anthonyafa3dfc2012-03-03 11:31:30 +00001967 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001968 {
anthony7bcfe7f2012-03-30 14:01:22 +00001969 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001970 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001971 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1972 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001973 break;
1974 }
anthonyafa3dfc2012-03-03 11:31:30 +00001975 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001976 {
anthony92c93bd2012-03-19 14:02:47 +00001977 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001978 break;
1979 }
anthonyafa3dfc2012-03-03 11:31:30 +00001980 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001981 {
anthonyafa3dfc2012-03-03 11:31:30 +00001982 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001983 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001984 else /* "+mask" remove the write mask */
cristyacd0d4c2015-07-25 16:12:33 +00001985 (void) SetImageMask(_image,ReadPixelMask,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001986 break;
1987 }
anthonyafa3dfc2012-03-03 11:31:30 +00001988 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001989 {
anthony4837ac22012-05-18 23:39:48 +00001990 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001991 CacheView
1992 *mask_view;
1993
1994 Image
1995 *mask_image;
1996
1997 register Quantum
dirk05d2ff72015-11-18 23:13:43 +01001998 *magick_restrict q;
anthony805a2d42011-09-25 08:25:12 +00001999
2000 register ssize_t
2001 x;
2002
2003 ssize_t
2004 y;
2005
anthonyafa3dfc2012-03-03 11:31:30 +00002006 if (IfPlusOp) {
anthony4837ac22012-05-18 23:39:48 +00002007 /* use "+clip-mask" Remove the write mask for -clip-path */
cristyacd0d4c2015-07-25 16:12:33 +00002008 (void) SetImageMask(_image,ReadPixelMask,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002009 break;
2010 }
anthony92c93bd2012-03-19 14:02:47 +00002011 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002012 if (mask_image == (Image *) NULL)
2013 break;
anthony7bcfe7f2012-03-30 14:01:22 +00002014 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00002015 break;
anthony5330ae02012-03-20 14:17:01 +00002016 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002017 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristy46ff2672012-12-14 15:32:26 +00002018 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002019 for (y=0; y < (ssize_t) mask_image->rows; y++)
2020 {
2021 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002022 _exception);
anthony805a2d42011-09-25 08:25:12 +00002023 if (q == (Quantum *) NULL)
2024 break;
2025 for (x=0; x < (ssize_t) mask_image->columns; x++)
2026 {
cristy7d6d3d82014-11-09 17:00:16 +00002027 if (mask_image->alpha_trait == UndefinedPixelTrait)
cristy52b632a2014-11-08 00:31:34 +00002028 SetPixelAlpha(mask_image,(Quantum)
2029 GetPixelIntensity(mask_image,q),q);
cristy81ac7972013-03-31 19:25:23 +00002030 SetPixelGray(mask_image,GetPixelAlpha(mask_image,q),q);
anthony805a2d42011-09-25 08:25:12 +00002031 q+=GetPixelChannels(mask_image);
2032 }
anthony7bcfe7f2012-03-30 14:01:22 +00002033 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002034 break;
2035 }
anthonyfd706f92012-01-19 04:22:02 +00002036 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002037 mask_view=DestroyCacheView(mask_view);
cristy8a46d822012-08-28 23:32:39 +00002038 mask_image->alpha_trait=BlendPixelTrait;
cristy81ac7972013-03-31 19:25:23 +00002039 (void) SetImageColorspace(_image,GRAYColorspace,_exception);
cristyacd0d4c2015-07-25 16:12:33 +00002040 (void) SetImageMask(_image,ReadPixelMask,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002041 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002042 break;
2043 }
anthonyafa3dfc2012-03-03 11:31:30 +00002044 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002045 {
anthonya322a832013-04-27 06:28:03 +00002046 (void) ClipImagePath(_image,arg1,IsNormalOp,_exception);
anthony4837ac22012-05-18 23:39:48 +00002047 /* Note: Use "+clip-mask" remove the write mask added */
anthony805a2d42011-09-25 08:25:12 +00002048 break;
2049 }
anthonyafa3dfc2012-03-03 11:31:30 +00002050 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002051 {
anthony7bcfe7f2012-03-30 14:01:22 +00002052 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002053 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002054 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002055 break;
2056 }
anthonyafa3dfc2012-03-03 11:31:30 +00002057 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002058 {
2059 KernelInfo
2060 *kernel;
2061
cristy2c57b742014-10-31 00:40:34 +00002062 kernel=AcquireKernelInfo(arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002063 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002064 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002065 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002066 kernel=DestroyKernelInfo(kernel);
2067 break;
2068 }
anthonyafa3dfc2012-03-03 11:31:30 +00002069 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002070 {
anthony5330ae02012-03-20 14:17:01 +00002071 /* Reduce the number of colors in the image.
2072 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002073 */
anthony92c93bd2012-03-19 14:02:47 +00002074 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2075 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002076 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002077 if ((_image->storage_class == DirectClass) ||
2078 _image->colors > _quantize_info->number_colors)
2079 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002080 else
anthony92c93bd2012-03-19 14:02:47 +00002081 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002082 break;
2083 }
anthonyafa3dfc2012-03-03 11:31:30 +00002084 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002085 {
anthony5330ae02012-03-20 14:17:01 +00002086 /* WARNING: this is both a image_info setting (already done)
2087 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002088
2089 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002090 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002091
anthonyd2cdc862011-10-07 14:07:17 +00002092 Note that +colorspace sets "undefined" or no effect on
2093 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002094 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002095 */
anthony92c93bd2012-03-19 14:02:47 +00002096 (void) TransformImageColorspace(_image,
cristye0b9b8f2013-03-28 12:39:39 +00002097 IfNormalOp ? _image_info->colorspace : sRGBColorspace,
anthony92c93bd2012-03-19 14:02:47 +00002098 _exception);
anthony805a2d42011-09-25 08:25:12 +00002099 break;
2100 }
cristy6e0b3bc2014-10-19 17:51:42 +00002101 if (LocaleCompare("connected-components",option+1) == 0)
2102 {
2103 if (IfMagickFalse(IsGeometry(arg1)))
2104 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
Cristy62e13982015-12-30 09:26:00 -05002105 new_image=ConnectedComponentsImage(_image,(size_t)
Cristy2ca0e9a2016-01-01 08:36:14 -05002106 StringToInteger(arg1),(CCObjectInfo **) NULL,_exception);
cristy6e0b3bc2014-10-19 17:51:42 +00002107 break;
2108 }
anthonyafa3dfc2012-03-03 11:31:30 +00002109 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002110 {
anthonya322a832013-04-27 06:28:03 +00002111 CLIWandWarnReplaced(IfNormalOp?"-level":"+level");
2112 (void) ContrastImage(_image,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002113 break;
2114 }
anthonyafa3dfc2012-03-03 11:31:30 +00002115 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002116 {
2117 double
2118 black_point,
2119 white_point;
2120
2121 MagickStatusType
2122 flags;
2123
anthonyfd706f92012-01-19 04:22:02 +00002124 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002125 if ((flags & RhoValue) == 0)
2126 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002127 black_point=geometry_info.rho;
2128 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2129 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002130 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002131 black_point*=(double) _image->columns*_image->rows/100.0;
2132 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002133 }
cristy496225b2014-11-05 01:50:39 +00002134 white_point=(double) _image->columns*_image->rows-white_point;
anthony92c93bd2012-03-19 14:02:47 +00002135 (void) ContrastStretchImage(_image,black_point,white_point,
2136 _exception);
anthony805a2d42011-09-25 08:25:12 +00002137 break;
2138 }
anthonyafa3dfc2012-03-03 11:31:30 +00002139 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002140 {
cristy77923262015-02-23 21:57:13 +00002141 double
2142 gamma;
2143
anthony805a2d42011-09-25 08:25:12 +00002144 KernelInfo
2145 *kernel_info;
cristy77923262015-02-23 21:57:13 +00002146
2147 register ssize_t
2148 j;
anthony805a2d42011-09-25 08:25:12 +00002149
cristy2c57b742014-10-31 00:40:34 +00002150 kernel_info=AcquireKernelInfo(arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002151 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002152 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy77923262015-02-23 21:57:13 +00002153 gamma=0.0;
2154 for (j=0; j < (ssize_t) (kernel_info->width*kernel_info->height); j++)
2155 gamma+=kernel_info->values[j];
2156 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
2157 for (j=0; j < (ssize_t) (kernel_info->width*kernel_info->height); j++)
2158 kernel_info->values[j]*=gamma;
cristya12d8ba2012-04-29 16:33:41 +00002159 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2160 _exception);
anthony805a2d42011-09-25 08:25:12 +00002161 kernel_info=DestroyKernelInfo(kernel_info);
2162 break;
2163 }
anthonyafa3dfc2012-03-03 11:31:30 +00002164 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002165 {
anthony31f1bf72012-01-30 12:37:22 +00002166 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002167 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002168 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002169 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002170 break;
2171 }
anthonyafa3dfc2012-03-03 11:31:30 +00002172 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002173 {
anthony7bcfe7f2012-03-30 14:01:22 +00002174 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002175 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002176 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2177 _exception);
anthony805a2d42011-09-25 08:25:12 +00002178 break;
2179 }
anthonyebb73a22012-03-22 14:25:52 +00002180 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002181 }
2182 case 'd':
2183 {
anthonyafa3dfc2012-03-03 11:31:30 +00002184 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002185 {
anthony4837ac22012-05-18 23:39:48 +00002186 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002187 StringInfo
2188 *passkey;
2189
cristy3a5987c2013-11-07 14:18:46 +00002190 passkey=FileToStringInfo(arg1,~0UL,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002191 if (passkey == (StringInfo *) NULL)
2192 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2193
2194 (void) PasskeyDecipherImage(_image,passkey,_exception);
2195 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002196 break;
2197 }
anthonyafa3dfc2012-03-03 11:31:30 +00002198 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002199 {
anthony92c93bd2012-03-19 14:02:47 +00002200 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002201 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002202
anthonydcf510d2011-10-30 13:51:40 +00002203 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2204 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002205
anthonyfd706f92012-01-19 04:22:02 +00002206 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002207 */
anthony92c93bd2012-03-19 14:02:47 +00002208 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002209 break;
2210 }
anthonyafa3dfc2012-03-03 11:31:30 +00002211 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002212 {
2213 double
2214 threshold;
2215
anthonyebb73a22012-03-22 14:25:52 +00002216 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002217 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002218 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002219 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002220 }
anthonyafa3dfc2012-03-03 11:31:30 +00002221 else
2222 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002223 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002224 break;
2225 }
anthonyafa3dfc2012-03-03 11:31:30 +00002226 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002227 {
anthony92c93bd2012-03-19 14:02:47 +00002228 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002229 break;
2230 }
anthonyafa3dfc2012-03-03 11:31:30 +00002231 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002232 {
anthony805a2d42011-09-25 08:25:12 +00002233 double
anthonyb1d483a2012-04-14 12:53:56 +00002234 *args;
anthony805a2d42011-09-25 08:25:12 +00002235
anthonyb1d483a2012-04-14 12:53:56 +00002236 ssize_t
2237 count;
anthony805a2d42011-09-25 08:25:12 +00002238
anthony2a0ec8c2012-03-24 04:35:56 +00002239 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2240 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002241 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2242 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002243 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002244 {
anthony80c37752012-01-16 01:03:11 +00002245 double
2246 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002247 /* Special Case - Argument is actually a resize geometry!
2248 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002249 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002250 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002251 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002252 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2253 option,arg2);
2254 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002255 resize_args[0]=(double) geometry.width;
2256 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002257 new_image=DistortImage(_image,(DistortImageMethod) parse,
2258 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002259 break;
2260 }
anthonyb1d483a2012-04-14 12:53:56 +00002261 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002262 args = StringToArrayOfDoubles(arg2,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00002263 if (args == (double *) NULL )
anthonyb1d483a2012-04-14 12:53:56 +00002264 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2265
cristy52b632a2014-11-08 00:31:34 +00002266 new_image=DistortImage(_image,(DistortImageMethod) parse,(size_t)
2267 count,args,IsPlusOp,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002268 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002269 break;
2270 }
anthonyafa3dfc2012-03-03 11:31:30 +00002271 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002272 {
anthony92c93bd2012-03-19 14:02:47 +00002273 (void) CloneString(&_draw_info->primitive,arg1);
2274 (void) DrawImage(_image,_draw_info,_exception);
cristyf432c632014-12-07 15:11:28 +00002275 (void) CloneString(&_draw_info->primitive,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002276 break;
2277 }
anthonyebb73a22012-03-22 14:25:52 +00002278 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002279 }
2280 case 'e':
2281 {
anthonyafa3dfc2012-03-03 11:31:30 +00002282 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002283 {
anthonyfd706f92012-01-19 04:22:02 +00002284 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002285 if ((flags & (RhoValue|SigmaValue)) == 0)
2286 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy9dc4c512013-03-24 01:38:00 +00002287 new_image=EdgeImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002288 break;
2289 }
anthonyafa3dfc2012-03-03 11:31:30 +00002290 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002291 {
anthonyfd706f92012-01-19 04:22:02 +00002292 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002293 if ((flags & (RhoValue|SigmaValue)) == 0)
2294 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002295 if ((flags & SigmaValue) == 0)
2296 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002297 new_image=EmbossImage(_image,geometry_info.rho,
2298 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002299 break;
2300 }
anthonyafa3dfc2012-03-03 11:31:30 +00002301 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002302 {
anthony4837ac22012-05-18 23:39:48 +00002303 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002304 StringInfo
2305 *passkey;
2306
cristy3a5987c2013-11-07 14:18:46 +00002307 passkey=FileToStringInfo(arg1,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002308 if (passkey != (StringInfo *) NULL)
2309 {
anthony92c93bd2012-03-19 14:02:47 +00002310 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002311 passkey=DestroyStringInfo(passkey);
2312 }
2313 break;
2314 }
anthonyafa3dfc2012-03-03 11:31:30 +00002315 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002316 {
anthony92c93bd2012-03-19 14:02:47 +00002317 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002318 break;
2319 }
anthonyafa3dfc2012-03-03 11:31:30 +00002320 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002321 {
anthony92c93bd2012-03-19 14:02:47 +00002322 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002323 break;
2324 }
anthonyafa3dfc2012-03-03 11:31:30 +00002325 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002326 {
2327 double
2328 constant;
2329
anthony2a0ec8c2012-03-24 04:35:56 +00002330 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2331 if ( parse < 0 )
2332 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2333 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002334 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002335 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002336 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002337 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2338 _exception);
anthony805a2d42011-09-25 08:25:12 +00002339 break;
2340 }
anthonyafa3dfc2012-03-03 11:31:30 +00002341 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002342 {
anthony7bcfe7f2012-03-30 14:01:22 +00002343 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002344 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002345 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002346 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002347 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002348 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002349 geometry.height=_image->rows;
2350 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002351 break;
2352 }
anthonyebb73a22012-03-22 14:25:52 +00002353 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002354 }
2355 case 'f':
2356 {
anthonyafa3dfc2012-03-03 11:31:30 +00002357 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002358 {
anthony92c93bd2012-03-19 14:02:47 +00002359 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002360 break;
2361 }
anthonyafa3dfc2012-03-03 11:31:30 +00002362 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002363 {
anthony92c93bd2012-03-19 14:02:47 +00002364 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002365 break;
2366 }
anthonyafa3dfc2012-03-03 11:31:30 +00002367 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002368 {
2369 PixelInfo
2370 target;
2371
anthony7bcfe7f2012-03-30 14:01:22 +00002372 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002373 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002374 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2375 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2376 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
anthonya322a832013-04-27 06:28:03 +00002377 geometry.y,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002378 break;
2379 }
anthonyafa3dfc2012-03-03 11:31:30 +00002380 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002381 {
2382 FrameInfo
2383 frame_info;
2384
anthony31f1bf72012-01-30 12:37:22 +00002385 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002386 compose;
2387
2388 const char*
2389 value;
2390
anthony92c93bd2012-03-19 14:02:47 +00002391 value=GetImageOption(_image_info,"compose");
anthony92c93bd2012-03-19 14:02:47 +00002392 compose=OverCompositeOp; /* use Over not _image->compose */
cristy4b892612012-08-03 19:31:31 +00002393 if (value != (const char *) NULL)
2394 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2395 MagickFalse,value);
anthony7bcfe7f2012-03-30 14:01:22 +00002396 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002397 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002398 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002399 frame_info.width=geometry.width;
2400 frame_info.height=geometry.height;
anthony805a2d42011-09-25 08:25:12 +00002401 frame_info.outer_bevel=geometry.x;
2402 frame_info.inner_bevel=geometry.y;
2403 frame_info.x=(ssize_t) frame_info.width;
2404 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002405 frame_info.width=_image->columns+2*frame_info.width;
2406 frame_info.height=_image->rows+2*frame_info.height;
2407 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002408 break;
2409 }
anthonyafa3dfc2012-03-03 11:31:30 +00002410 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002411 {
anthony805a2d42011-09-25 08:25:12 +00002412 double
anthonyb1d483a2012-04-14 12:53:56 +00002413 *args;
anthony805a2d42011-09-25 08:25:12 +00002414
anthonyb1d483a2012-04-14 12:53:56 +00002415 ssize_t
2416 count;
anthony805a2d42011-09-25 08:25:12 +00002417
anthony2a0ec8c2012-03-24 04:35:56 +00002418 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2419 if ( parse < 0 )
2420 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2421 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002422 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002423 args = StringToArrayOfDoubles(arg2,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00002424 if (args == (double *) NULL )
anthonyb1d483a2012-04-14 12:53:56 +00002425 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2426
cristy52b632a2014-11-08 00:31:34 +00002427 (void) FunctionImage(_image,(MagickFunction)parse,(size_t) count,args,
anthonyb1d483a2012-04-14 12:53:56 +00002428 _exception);
2429 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002430 break;
2431 }
anthonyebb73a22012-03-22 14:25:52 +00002432 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002433 }
2434 case 'g':
2435 {
anthonyafa3dfc2012-03-03 11:31:30 +00002436 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002437 {
anthony7a4d6102012-07-01 09:48:25 +00002438 double
2439 constant;
2440
anthony7bcfe7f2012-03-30 14:01:22 +00002441 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002442 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony7a4d6102012-07-01 09:48:25 +00002443 constant=StringToDouble(arg1,(char **) NULL);
2444#if 0
2445 /* Using Gamma, via a cache */
2446 if (IfPlusOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002447 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002448 (void) GammaImage(_image,constant,_exception);
2449#else
2450 /* Using Evaluate POW, direct update of values - more accurite */
anthonyafa3dfc2012-03-03 11:31:30 +00002451 if (IfNormalOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002452 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002453 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
cristya4943882015-02-11 11:25:46 +00002454 _image->gamma*=StringToDouble(arg1,(char **) NULL);
anthony7a4d6102012-07-01 09:48:25 +00002455#endif
2456 /* Set gamma setting -- Old meaning of "+gamma"
2457 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2458 */
anthony805a2d42011-09-25 08:25:12 +00002459 break;
2460 }
anthony975a8d72012-04-12 13:54:36 +00002461 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002462 {
anthonyfd706f92012-01-19 04:22:02 +00002463 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002464 if ((flags & (RhoValue|SigmaValue)) == 0)
2465 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002466 if ((flags & SigmaValue) == 0)
2467 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002468 new_image=GaussianBlurImage(_image,geometry_info.rho,
2469 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002470 break;
2471 }
anthony975a8d72012-04-12 13:54:36 +00002472 if (LocaleCompare("gaussian",option+1) == 0)
2473 {
anthony464f1c42012-04-22 08:51:01 +00002474 CLIWandWarnReplaced("-gaussian-blur");
cristy52b632a2014-11-08 00:31:34 +00002475 (void) CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL,exception);
anthony975a8d72012-04-12 13:54:36 +00002476 }
anthonyafa3dfc2012-03-03 11:31:30 +00002477 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002478 {
anthonyfd706f92012-01-19 04:22:02 +00002479 /*
anthony31f1bf72012-01-30 12:37:22 +00002480 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002481 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002482 FUTURE: Why if no 'offset' does this resize ALL images?
2483 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002484 */
anthonyafa3dfc2012-03-03 11:31:30 +00002485 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002486 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002487 if (_image->geometry != (char *) NULL)
2488 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002489 break;
2490 }
anthony7bcfe7f2012-03-30 14:01:22 +00002491 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002492 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002493 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002494 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002495 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002496 else
anthony92c93bd2012-03-19 14:02:47 +00002497 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002498 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002499 break;
2500 }
cristyab943592013-03-29 16:47:23 +00002501 if (LocaleCompare("grayscale",option+1) == 0)
cristye0b9b8f2013-03-28 12:39:39 +00002502 {
cristyab943592013-03-29 16:47:23 +00002503 parse=ParseCommandOption(MagickPixelIntensityOptions,
cristye0b9b8f2013-03-28 12:39:39 +00002504 MagickFalse,arg1);
cristyab943592013-03-29 16:47:23 +00002505 if (parse < 0)
2506 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
2507 option,arg1);
2508 (void) GrayscaleImage(_image,(PixelIntensityMethod) parse,_exception);
cristye0b9b8f2013-03-28 12:39:39 +00002509 break;
2510 }
anthonyebb73a22012-03-22 14:25:52 +00002511 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002512 }
cristy2fc10e52014-04-26 14:13:53 +00002513 case 'h':
2514 {
2515 if (LocaleCompare("hough-lines",option+1) == 0)
2516 {
2517 flags=ParseGeometry(arg1,&geometry_info);
2518 if ((flags & (RhoValue|SigmaValue)) == 0)
2519 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2520 if ((flags & SigmaValue) == 0)
cristyd5b8d2a2014-04-27 17:43:33 +00002521 geometry_info.sigma=geometry_info.rho;
cristy2fc10e52014-04-26 14:13:53 +00002522 if ((flags & XiValue) == 0)
cristy20f90422014-04-27 13:34:21 +00002523 geometry_info.xi=40;
2524 new_image=HoughLineImage(_image,(size_t) geometry_info.rho,
2525 (size_t) geometry_info.sigma,(size_t) geometry_info.xi,_exception);
cristy2fc10e52014-04-26 14:13:53 +00002526 break;
2527 }
2528 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2529 }
anthony805a2d42011-09-25 08:25:12 +00002530 case 'i':
2531 {
anthonyafa3dfc2012-03-03 11:31:30 +00002532 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002533 {
anthony31f1bf72012-01-30 12:37:22 +00002534 const char
2535 *format,
anthony805a2d42011-09-25 08:25:12 +00002536 *text;
2537
anthony92c93bd2012-03-19 14:02:47 +00002538 format=GetImageOption(_image_info,"format");
cristyf9b9b662013-05-25 12:50:16 +00002539 if (format == (char *) NULL)
2540 {
2541 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2542 _exception);
2543 break;
2544 }
anthony92c93bd2012-03-19 14:02:47 +00002545 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002546 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002547 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
cristyf9b9b662013-05-25 12:50:16 +00002548 option);
anthony805a2d42011-09-25 08:25:12 +00002549 (void) fputs(text,stdout);
anthony31f1bf72012-01-30 12:37:22 +00002550 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002551 break;
2552 }
anthonyafa3dfc2012-03-03 11:31:30 +00002553 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002554 {
anthonyb1e21ed2012-04-20 12:43:12 +00002555 flags=ParseGeometry(arg1,&geometry_info);
2556 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002557 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002558 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2559 _exception);
anthony805a2d42011-09-25 08:25:12 +00002560 break;
2561 }
anthonyafa3dfc2012-03-03 11:31:30 +00002562 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002563 {
anthonyfe1aa782012-03-24 13:43:04 +00002564 /* FUTURE: New to IMv7
2565 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002566 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002567 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002568 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2569 new_image=InterpolativeResizeImage(_image,geometry.width,
2570 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002571 break;
2572 }
anthonyebb73a22012-03-22 14:25:52 +00002573 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002574 }
cristy3b207f82014-09-27 14:21:20 +00002575 case 'k':
2576 {
2577 if (LocaleCompare("kuwahara",option+1) == 0)
2578 {
2579 /*
2580 Edge preserving blur.
2581 */
2582 flags=ParseGeometry(arg1,&geometry_info);
2583 if ((flags & (RhoValue|SigmaValue)) == 0)
2584 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2585 if ((flags & SigmaValue) == 0)
cristy25ea9362014-10-04 01:12:09 +00002586 geometry_info.sigma=geometry_info.rho-0.5;
cristy3b207f82014-09-27 14:21:20 +00002587 new_image=KuwaharaImage(_image,geometry_info.rho,geometry_info.sigma,
2588 _exception);
2589 break;
2590 }
2591 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2592 }
anthony805a2d42011-09-25 08:25:12 +00002593 case 'l':
2594 {
anthonyafa3dfc2012-03-03 11:31:30 +00002595 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002596 {
anthonyfd706f92012-01-19 04:22:02 +00002597 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002598 if ((flags & (RhoValue|SigmaValue)) == 0)
2599 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyb5c691e2012-09-14 17:12:40 +00002600 if ((flags & SigmaValue) == 0)
2601 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00002602 if ((flags & PercentValue) != 0)
2603 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002604 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002605 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002606 _exception);
anthony805a2d42011-09-25 08:25:12 +00002607 break;
2608 }
anthonyafa3dfc2012-03-03 11:31:30 +00002609 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002610 {
cristya19f1d72012-08-07 18:24:38 +00002611 double
anthony805a2d42011-09-25 08:25:12 +00002612 black_point,
2613 gamma,
2614 white_point;
2615
2616 MagickStatusType
2617 flags;
2618
anthonyfd706f92012-01-19 04:22:02 +00002619 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002620 if ((flags & RhoValue) == 0)
2621 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002622 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002623 white_point=(double) QuantumRange;
anthony805a2d42011-09-25 08:25:12 +00002624 if ((flags & SigmaValue) != 0)
2625 white_point=geometry_info.sigma;
2626 gamma=1.0;
2627 if ((flags & XiValue) != 0)
2628 gamma=geometry_info.xi;
2629 if ((flags & PercentValue) != 0)
2630 {
cristya19f1d72012-08-07 18:24:38 +00002631 black_point*=(double) (QuantumRange/100.0);
2632 white_point*=(double) (QuantumRange/100.0);
anthony805a2d42011-09-25 08:25:12 +00002633 }
2634 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002635 white_point=(double) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002636 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002637 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002638 else
anthony92c93bd2012-03-19 14:02:47 +00002639 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002640 break;
2641 }
anthonyafa3dfc2012-03-03 11:31:30 +00002642 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002643 {
2644 char
cristy151b66d2015-04-15 10:50:31 +00002645 token[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00002646
2647 const char
2648 *p;
2649
2650 PixelInfo
2651 black_point,
2652 white_point;
2653
anthonyfd706f92012-01-19 04:22:02 +00002654 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002655 GetMagickToken(p,&p,token); /* get black point color */
2656 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002657 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002658 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002659 else
cristy269c9412011-10-13 23:41:15 +00002660 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002661 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002662 if (isalpha((int) token[0]) || (token[0] == '#'))
2663 GetMagickToken(p,&p,token);
2664 if (*token == '\0')
2665 white_point=black_point; /* set everything to that color */
2666 else
2667 {
2668 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2669 GetMagickToken(p,&p,token); /* Get white point color. */
2670 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002671 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002672 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002673 else
cristy269c9412011-10-13 23:41:15 +00002674 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002675 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002676 }
anthony92c93bd2012-03-19 14:02:47 +00002677 (void) LevelImageColors(_image,&black_point,&white_point,
anthonya322a832013-04-27 06:28:03 +00002678 IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002679 break;
2680 }
anthonyafa3dfc2012-03-03 11:31:30 +00002681 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002682 {
2683 double
2684 black_point,
2685 white_point;
2686
2687 MagickStatusType
2688 flags;
2689
anthonyfd706f92012-01-19 04:22:02 +00002690 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002691 if ((flags & RhoValue) == 0)
2692 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002693 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002694 white_point=(double) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002695 if ((flags & SigmaValue) != 0)
2696 white_point=geometry_info.sigma;
2697 if ((flags & PercentValue) != 0)
2698 {
anthony92c93bd2012-03-19 14:02:47 +00002699 black_point*=(double) _image->columns*_image->rows/100.0;
2700 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002701 }
2702 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002703 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002704 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002705 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002706 break;
2707 }
anthonyafa3dfc2012-03-03 11:31:30 +00002708 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002709 {
anthonyfe1aa782012-03-24 13:43:04 +00002710 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002711 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002712 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002713 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002714 if ((flags & XValue) == 0)
2715 geometry.x=1;
2716 if ((flags & YValue) == 0)
2717 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002718 new_image=LiquidRescaleImage(_image,geometry.width,
2719 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002720 break;
2721 }
dirk3505d872015-11-01 23:30:09 +01002722 if (LocaleCompare("local-contrast",option+1) == 0)
2723 {
2724 MagickStatusType
2725 flags;
2726
2727 flags=ParseGeometry(arg1,&geometry_info);
2728 if ((flags & RhoValue) == 0)
dirk394f2112015-11-03 21:27:00 +01002729 geometry_info.rho=10;
dirk3505d872015-11-01 23:30:09 +01002730 if ((flags & SigmaValue) == 0)
dirk394f2112015-11-03 21:27:00 +01002731 geometry_info.sigma=12.5;
2732 if (((flags & RhoValue) == 0) || ((flags & PercentValue) != 0))
2733 geometry_info.rho*=MagickMax(_image->columns,_image->rows)/100.0;
dirk3505d872015-11-01 23:30:09 +01002734 new_image=LocalContrastImage(_image,geometry_info.rho,
2735 geometry_info.sigma,exception);
2736 break;
2737 }
anthonyebb73a22012-03-22 14:25:52 +00002738 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002739 }
2740 case 'm':
2741 {
cristy7220ee42013-04-14 01:30:34 +00002742 if (LocaleCompare("magnify",option+1) == 0)
2743 {
2744 new_image=MagnifyImage(_image,_exception);
2745 break;
2746 }
anthonyafa3dfc2012-03-03 11:31:30 +00002747 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002748 {
anthony464f1c42012-04-22 08:51:01 +00002749 CLIWandWarnReplaced("-remap");
cristy52b632a2014-11-08 00:31:34 +00002750 (void) CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002751 break;
2752 }
anthonyafa3dfc2012-03-03 11:31:30 +00002753 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002754 {
cristy327030c2015-07-25 18:05:50 +00002755 CLIWandWarnReplaced("-read-mask");
2756 (void) CLISimpleOperatorImage(cli_wand,"-read-mask",NULL,NULL,
2757 exception);
anthony805a2d42011-09-25 08:25:12 +00002758 break;
2759 }
cristy52ad9e92013-02-08 23:23:29 +00002760 if (LocaleCompare("matte",option+1) == 0)
2761 {
2762 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2763 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
cristy1309fc32014-04-26 18:48:37 +00002764 DeactivateAlphaChannel, _exception);
cristy52ad9e92013-02-08 23:23:29 +00002765 break;
2766 }
cristy2fc10e52014-04-26 14:13:53 +00002767 if (LocaleCompare("mean-shift",option+1) == 0)
2768 {
2769 flags=ParseGeometry(arg1,&geometry_info);
2770 if ((flags & (RhoValue|SigmaValue)) == 0)
2771 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2772 if ((flags & SigmaValue) == 0)
2773 geometry_info.sigma=1.0;
2774 if ((flags & XiValue) == 0)
cristy1309fc32014-04-26 18:48:37 +00002775 geometry_info.xi=0.10*QuantumRange;
2776 if ((flags & PercentValue) != 0)
2777 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2778 new_image=MeanShiftImage(_image,(size_t) geometry_info.rho,
2779 (size_t) geometry_info.sigma,geometry_info.xi,_exception);
cristy2fc10e52014-04-26 14:13:53 +00002780 break;
2781 }
cristy52ad9e92013-02-08 23:23:29 +00002782 if (LocaleCompare("median",option+1) == 0)
2783 {
2784 CLIWandWarnReplaced("-statistic Median");
cristy52b632a2014-11-08 00:31:34 +00002785 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1,exception);
cristy52ad9e92013-02-08 23:23:29 +00002786 break;
2787 }
2788 if (LocaleCompare("mode",option+1) == 0)
2789 {
2790 /* FUTURE: note this is also a special "montage" option */
2791 CLIWandWarnReplaced("-statistic Mode");
cristy52b632a2014-11-08 00:31:34 +00002792 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1,exception);
cristy52ad9e92013-02-08 23:23:29 +00002793 break;
2794 }
anthonyafa3dfc2012-03-03 11:31:30 +00002795 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002796 {
anthony7bcfe7f2012-03-30 14:01:22 +00002797 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002798 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002799 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002800 break;
2801 }
anthonyafa3dfc2012-03-03 11:31:30 +00002802 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002803 {
anthony92c93bd2012-03-19 14:02:47 +00002804 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002805 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002806 break;
2807 }
anthonyafa3dfc2012-03-03 11:31:30 +00002808 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002809 {
anthony92c93bd2012-03-19 14:02:47 +00002810 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002811 break;
2812 }
anthonyafa3dfc2012-03-03 11:31:30 +00002813 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002814 {
2815 char
cristy151b66d2015-04-15 10:50:31 +00002816 token[MagickPathExtent];
anthony805a2d42011-09-25 08:25:12 +00002817
2818 const char
2819 *p;
2820
2821 KernelInfo
2822 *kernel;
2823
anthony805a2d42011-09-25 08:25:12 +00002824 ssize_t
2825 iterations;
2826
anthonyfd706f92012-01-19 04:22:02 +00002827 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002828 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002829 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2830 if ( parse < 0 )
cristy2c57b742014-10-31 00:40:34 +00002831 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",option,
2832 arg1);
anthony805a2d42011-09-25 08:25:12 +00002833 iterations=1L;
2834 GetMagickToken(p,&p,token);
2835 if ((*p == ':') || (*p == ','))
2836 GetMagickToken(p,&p,token);
2837 if ((*p != '\0'))
2838 iterations=(ssize_t) StringToLong(p);
cristy2c57b742014-10-31 00:40:34 +00002839 kernel=AcquireKernelInfo(arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00002840 if (kernel == (KernelInfo *) NULL)
cristy2c57b742014-10-31 00:40:34 +00002841 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",option,arg2);
2842 new_image=MorphologyImage(_image,(MorphologyMethod)parse,iterations,
2843 kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002844 kernel=DestroyKernelInfo(kernel);
2845 break;
2846 }
anthonyafa3dfc2012-03-03 11:31:30 +00002847 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002848 {
anthonyfd706f92012-01-19 04:22:02 +00002849 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002850 if ((flags & (RhoValue|SigmaValue)) == 0)
2851 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002852 if ((flags & SigmaValue) == 0)
2853 geometry_info.sigma=1.0;
cristy2c57b742014-10-31 00:40:34 +00002854 new_image=MotionBlurImage(_image,geometry_info.rho,geometry_info.sigma,
2855 geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002856 break;
2857 }
anthonyebb73a22012-03-22 14:25:52 +00002858 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002859 }
2860 case 'n':
2861 {
anthonyafa3dfc2012-03-03 11:31:30 +00002862 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002863 {
anthonya322a832013-04-27 06:28:03 +00002864 (void) NegateImage(_image, IsPlusOp, _exception);
anthony805a2d42011-09-25 08:25:12 +00002865 break;
2866 }
anthonyafa3dfc2012-03-03 11:31:30 +00002867 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002868 {
anthony975a8d72012-04-12 13:54:36 +00002869 double
2870 attenuate;
2871
2872 const char*
2873 value;
2874
anthonyafa3dfc2012-03-03 11:31:30 +00002875 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002876 {
anthony464f1c42012-04-22 08:51:01 +00002877 CLIWandWarnReplaced("-statistic NonPeak");
cristy52b632a2014-11-08 00:31:34 +00002878 (void) CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1,exception);
anthony975a8d72012-04-12 13:54:36 +00002879 break;
anthony805a2d42011-09-25 08:25:12 +00002880 }
anthony975a8d72012-04-12 13:54:36 +00002881 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2882 if ( parse < 0 )
2883 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2884 option,arg1);
2885 attenuate=1.0;
2886 value=GetImageOption(_image_info,"attenuate");
2887 if (value != (const char *) NULL)
2888 attenuate=StringToDouble(value,(char **) NULL);
2889 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2890 _exception);
anthony805a2d42011-09-25 08:25:12 +00002891 break;
2892 }
anthonyafa3dfc2012-03-03 11:31:30 +00002893 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002894 {
anthony92c93bd2012-03-19 14:02:47 +00002895 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002896 break;
2897 }
anthonyebb73a22012-03-22 14:25:52 +00002898 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002899 }
2900 case 'o':
2901 {
anthonyafa3dfc2012-03-03 11:31:30 +00002902 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002903 {
2904 PixelInfo
2905 target;
2906
anthony92c93bd2012-03-19 14:02:47 +00002907 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
anthonya322a832013-04-27 06:28:03 +00002908 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,IsPlusOp,
anthony92c93bd2012-03-19 14:02:47 +00002909 _exception);
anthony805a2d42011-09-25 08:25:12 +00002910 break;
2911 }
anthonyafa3dfc2012-03-03 11:31:30 +00002912 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002913 {
anthony92c93bd2012-03-19 14:02:47 +00002914 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002915 break;
2916 }
anthonyebb73a22012-03-22 14:25:52 +00002917 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002918 }
2919 case 'p':
2920 {
anthonyafa3dfc2012-03-03 11:31:30 +00002921 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002922 {
anthony22de2722012-04-19 14:43:00 +00002923 flags=ParseGeometry(arg1,&geometry_info);
2924 if ((flags & (RhoValue|SigmaValue)) == 0)
2925 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002926 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2927 _exception);
anthony805a2d42011-09-25 08:25:12 +00002928 break;
2929 }
cristy7884a932012-11-04 14:33:51 +00002930 if (LocaleCompare("perceptible",option+1) == 0)
2931 {
2932 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2933 _exception);
2934 break;
2935 }
anthonyafa3dfc2012-03-03 11:31:30 +00002936 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002937 {
cristye9e3d382011-12-14 01:50:13 +00002938 const char
2939 *caption;
2940
anthony805a2d42011-09-25 08:25:12 +00002941 double
2942 angle;
2943
anthony7bc87992012-03-25 02:32:51 +00002944 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002945 RandomInfo
cristy2c57b742014-10-31 00:40:34 +00002946 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002947
anthonyf42014d2012-03-25 09:53:06 +00002948 random_info=AcquireRandomInfo();
2949 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2950 random_info=DestroyRandomInfo(random_info);
2951 }
anthony7bc87992012-03-25 02:32:51 +00002952 else {
anthonyf42014d2012-03-25 09:53:06 +00002953 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002954 if ((flags & RhoValue) == 0)
2955 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002956 angle=geometry_info.rho;
2957 }
anthony92c93bd2012-03-19 14:02:47 +00002958 caption=GetImageProperty(_image,"caption",_exception);
2959 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2960 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002961 break;
2962 }
anthonyafa3dfc2012-03-03 11:31:30 +00002963 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002964 {
anthony22de2722012-04-19 14:43:00 +00002965 flags=ParseGeometry(arg1,&geometry_info);
2966 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002967 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002968 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002969 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002970 break;
2971 }
anthonyafa3dfc2012-03-03 11:31:30 +00002972 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002973 {
anthony31f1bf72012-01-30 12:37:22 +00002974 /* FUTURE: should be a 'Genesis' option?
2975 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002976 Why???
cristy947cb4c2011-10-20 18:41:46 +00002977 */
anthony7bc87992012-03-25 02:32:51 +00002978 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2979 if ( parse < 0 )
2980 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2981 option,arg1);
2982 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002983 break;
2984 }
anthonyafa3dfc2012-03-03 11:31:30 +00002985 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002986 {
anthony4837ac22012-05-18 23:39:48 +00002987 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002988 const char
2989 *name;
2990
2991 const StringInfo
2992 *profile;
2993
2994 Image
2995 *profile_image;
2996
2997 ImageInfo
2998 *profile_info;
2999
anthonyafa3dfc2012-03-03 11:31:30 +00003000 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003001 { /* Remove a profile from the _image. */
3002 (void) ProfileImage(_image,arg1,(const unsigned char *)
3003 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003004 break;
3005 }
anthony92c93bd2012-03-19 14:02:47 +00003006 /* Associate a profile with the _image. */
3007 profile_info=CloneImageInfo(_image_info);
3008 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003009 if (profile != (StringInfo *) NULL)
3010 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003011 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003012 profile_info=DestroyImageInfo(profile_info);
3013 if (profile_image == (Image *) NULL)
3014 {
3015 StringInfo
3016 *profile;
3017
anthony92c93bd2012-03-19 14:02:47 +00003018 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003019 (void) CopyMagickString(profile_info->filename,arg1,
cristy151b66d2015-04-15 10:50:31 +00003020 MagickPathExtent);
anthony92c93bd2012-03-19 14:02:47 +00003021 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003022 if (profile != (StringInfo *) NULL)
3023 {
anthony92c93bd2012-03-19 14:02:47 +00003024 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003025 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003026 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003027 profile=DestroyStringInfo(profile);
3028 }
3029 profile_info=DestroyImageInfo(profile_info);
3030 break;
3031 }
3032 ResetImageProfileIterator(profile_image);
3033 name=GetNextImageProfile(profile_image);
3034 while (name != (const char *) NULL)
3035 {
3036 profile=GetImageProfile(profile_image,name);
3037 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003038 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3039 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003040 name=GetNextImageProfile(profile_image);
3041 }
3042 profile_image=DestroyImage(profile_image);
3043 break;
3044 }
anthonyebb73a22012-03-22 14:25:52 +00003045 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003046 }
anthony805a2d42011-09-25 08:25:12 +00003047 case 'r':
3048 {
dirk6d612cf2014-03-13 21:17:23 +00003049 if (LocaleCompare("rotational-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003050 {
anthonyfd706f92012-01-19 04:22:02 +00003051 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003052 if ((flags & RhoValue) == 0)
3053 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
dirk6d612cf2014-03-13 21:17:23 +00003054 new_image=RotationalBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003055 break;
3056 }
anthonyafa3dfc2012-03-03 11:31:30 +00003057 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003058 {
anthony7bcfe7f2012-03-30 14:01:22 +00003059 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003060 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003061 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthonya322a832013-04-27 06:28:03 +00003062 (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003063 break;
3064 }
anthonyafa3dfc2012-03-03 11:31:30 +00003065 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003066 {
anthony7bcfe7f2012-03-30 14:01:22 +00003067 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003068 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003069 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003070 break;
3071 }
cristy327030c2015-07-25 18:05:50 +00003072 if (LocaleCompare("read-mask",option+1) == 0)
3073 {
3074 /* Note: arguments do not have percent escapes expanded */
3075 Image
3076 *mask;
3077
3078 if (IfPlusOp)
3079 { /* Remove a mask. */
3080 (void) SetImageMask(_image,ReadPixelMask,(Image *) NULL,
3081 _exception);
3082 break;
3083 }
3084 /* Set the image mask. */
3085 mask=GetImageCache(_image_info,arg1,_exception);
3086 if (mask == (Image *) NULL)
3087 break;
3088 (void) SetImageMask(_image,ReadPixelMask,mask,_exception);
3089 mask=DestroyImage(mask);
3090 break;
3091 }
anthony975a8d72012-04-12 13:54:36 +00003092 if (LocaleCompare("recolor",option+1) == 0)
3093 {
anthony464f1c42012-04-22 08:51:01 +00003094 CLIWandWarnReplaced("-color-matrix");
cristy52b632a2014-11-08 00:31:34 +00003095 (void) CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL,exception);
anthony975a8d72012-04-12 13:54:36 +00003096 }
anthonyafa3dfc2012-03-03 11:31:30 +00003097 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003098 {
anthony4837ac22012-05-18 23:39:48 +00003099 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00003100 Image
3101 *remap_image;
3102
anthony92c93bd2012-03-19 14:02:47 +00003103 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003104 if (remap_image == (Image *) NULL)
3105 break;
anthony92c93bd2012-03-19 14:02:47 +00003106 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003107 remap_image=DestroyImage(remap_image);
3108 break;
3109 }
anthonyafa3dfc2012-03-03 11:31:30 +00003110 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003111 {
anthonyafa3dfc2012-03-03 11:31:30 +00003112 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003113 {
anthony7bcfe7f2012-03-30 14:01:22 +00003114 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00003115 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3116 arg1);
3117 (void) ResetImagePage(_image,arg1);
3118 }
anthony31f1bf72012-01-30 12:37:22 +00003119 else
anthony92c93bd2012-03-19 14:02:47 +00003120 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003121 break;
3122 }
anthonyafa3dfc2012-03-03 11:31:30 +00003123 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003124 {
anthonyf46d4262012-03-26 03:30:34 +00003125 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00003126 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003127 if ((flags & (RhoValue|SigmaValue)) == 0)
3128 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003129 if ((flags & SigmaValue) == 0)
3130 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003131 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003132 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003133 break;
3134 }
anthonyafa3dfc2012-03-03 11:31:30 +00003135 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003136 {
anthony7bcfe7f2012-03-30 14:01:22 +00003137 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003138 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003139 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3140 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003141 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003142 break;
3143 }
anthonyafa3dfc2012-03-03 11:31:30 +00003144 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003145 {
anthony7bcfe7f2012-03-30 14:01:22 +00003146 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003147 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003148 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3149 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003150 break;
3151 }
anthonyafa3dfc2012-03-03 11:31:30 +00003152 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003153 {
anthony22de2722012-04-19 14:43:00 +00003154 flags=ParseGeometry(arg1,&geometry_info);
3155 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003156 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003157 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003158 break;
3159 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3160 break;
anthony92c93bd2012-03-19 14:02:47 +00003161 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003162 break;
3163 }
anthonyebb73a22012-03-22 14:25:52 +00003164 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003165 }
3166 case 's':
3167 {
anthonyafa3dfc2012-03-03 11:31:30 +00003168 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003169 {
anthonyfe1aa782012-03-24 13:43:04 +00003170 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003171 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003172 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003173 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3174 new_image=SampleImage(_image,geometry.width,geometry.height,
3175 _exception);
anthony805a2d42011-09-25 08:25:12 +00003176 break;
3177 }
anthonyafa3dfc2012-03-03 11:31:30 +00003178 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003179 {
anthonyfe1aa782012-03-24 13:43:04 +00003180 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003181 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003182 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003183 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3184 new_image=ScaleImage(_image,geometry.width,geometry.height,
3185 _exception);
anthony805a2d42011-09-25 08:25:12 +00003186 break;
3187 }
anthonyf42014d2012-03-25 09:53:06 +00003188 if (LocaleCompare("segment",option+1) == 0)
3189 {
anthonyf42014d2012-03-25 09:53:06 +00003190 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003191 if ((flags & (RhoValue|SigmaValue)) == 0)
3192 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003193 if ((flags & SigmaValue) == 0)
3194 geometry_info.sigma=1.0;
3195 (void) SegmentImage(_image,_image->colorspace,
3196 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3197 _exception);
3198 break;
3199 }
anthonyafa3dfc2012-03-03 11:31:30 +00003200 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003201 {
anthonyfd706f92012-01-19 04:22:02 +00003202 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003203 if ((flags & (RhoValue|SigmaValue)) == 0)
3204 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3205 if ((flags & SigmaValue) == 0)
3206 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003207 if ((flags & PercentValue) != 0)
3208 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003209 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003210 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003211 break;
3212 }
anthonyafa3dfc2012-03-03 11:31:30 +00003213 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003214 {
anthony31f1bf72012-01-30 12:37:22 +00003215 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003216 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003217 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003218 break;
3219 }
anthonyafa3dfc2012-03-03 11:31:30 +00003220 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003221 {
anthony7bcfe7f2012-03-30 14:01:22 +00003222 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003223 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3224 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3225 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003226 break;
3227 }
anthonyafa3dfc2012-03-03 11:31:30 +00003228 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003229 {
anthonyfd706f92012-01-19 04:22:02 +00003230 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003231 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3232 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya322a832013-04-27 06:28:03 +00003233 new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
anthony92c93bd2012-03-19 14:02:47 +00003234 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003235 break;
3236 }
anthonyafa3dfc2012-03-03 11:31:30 +00003237 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003238 {
anthonyfd706f92012-01-19 04:22:02 +00003239 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003240 if ((flags & (RhoValue|SigmaValue)) == 0)
3241 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003242 if ((flags & SigmaValue) == 0)
3243 geometry_info.sigma=1.0;
3244 if ((flags & XiValue) == 0)
3245 geometry_info.xi=4.0;
3246 if ((flags & PsiValue) == 0)
3247 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003248 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3249 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3250 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003251 break;
3252 }
anthonyafa3dfc2012-03-03 11:31:30 +00003253 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003254 {
anthonyfd706f92012-01-19 04:22:02 +00003255 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003256 if ((flags & (RhoValue|SigmaValue)) == 0)
3257 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003258 if ((flags & SigmaValue) == 0)
3259 geometry_info.sigma=1.0;
3260 if ((flags & XiValue) == 0)
3261 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003262 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3263 _exception);
anthony805a2d42011-09-25 08:25:12 +00003264 break;
3265 }
anthonyafa3dfc2012-03-03 11:31:30 +00003266 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003267 {
anthony7bcfe7f2012-03-30 14:01:22 +00003268 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003269 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003270 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3271 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003272 break;
3273 }
anthonyafa3dfc2012-03-03 11:31:30 +00003274 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003275 {
anthonyfd706f92012-01-19 04:22:02 +00003276 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003277 if ((flags & RhoValue) == 0)
3278 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003279 if ((flags & SigmaValue) == 0)
3280 geometry_info.sigma=geometry_info.rho;
cristy4b892612012-08-03 19:31:31 +00003281 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3282 _exception);
anthony805a2d42011-09-25 08:25:12 +00003283 break;
3284 }
anthonyafa3dfc2012-03-03 11:31:30 +00003285 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003286 {
anthonyfd706f92012-01-19 04:22:02 +00003287 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003288 if ((flags & RhoValue) == 0)
3289 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003290 if ((flags & SigmaValue) == 0)
3291 geometry_info.sigma=(double) QuantumRange/2.0;
3292 if ((flags & PercentValue) != 0)
3293 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3294 100.0;
anthonya322a832013-04-27 06:28:03 +00003295 (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003296 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003297 break;
3298 }
anthonyafa3dfc2012-03-03 11:31:30 +00003299 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003300 {
anthonyfd706f92012-01-19 04:22:02 +00003301 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003302 if ((flags & (RhoValue|SigmaValue)) == 0)
3303 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003304 if ((flags & SigmaValue) == 0)
3305 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003306 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003307 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003308 break;
3309 }
anthonyafa3dfc2012-03-03 11:31:30 +00003310 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003311 {
anthony7bcfe7f2012-03-30 14:01:22 +00003312 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003313 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003314 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3315 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003316 break;
3317 }
anthonyafa3dfc2012-03-03 11:31:30 +00003318 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003319 {
anthonyf42014d2012-03-25 09:53:06 +00003320 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3321 if ( parse < 0 )
3322 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3323 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003324 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3325 _exception);
anthony805a2d42011-09-25 08:25:12 +00003326 break;
3327 }
anthonyafa3dfc2012-03-03 11:31:30 +00003328 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003329 {
anthony7bcfe7f2012-03-30 14:01:22 +00003330 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003331 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003332 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003333 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003334 break;
3335 }
anthonyafa3dfc2012-03-03 11:31:30 +00003336 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003337 {
anthonyb1e21ed2012-04-20 12:43:12 +00003338 flags=ParseGeometry(arg1,&geometry_info);
3339 if ((flags & RhoValue) == 0)
3340 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
Cristye3319c12015-08-24 07:11:48 -04003341 new_image=SpreadImage(_image,_image->interpolate,geometry_info.rho,
3342 _exception);
anthony805a2d42011-09-25 08:25:12 +00003343 break;
3344 }
anthonyafa3dfc2012-03-03 11:31:30 +00003345 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003346 {
anthony7bc87992012-03-25 02:32:51 +00003347 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3348 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003349 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003350 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003351 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003352 if ((flags & RhoValue) == 0)
3353 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003354 if ((flags & SigmaValue) == 0)
3355 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003356 new_image=StatisticImage(_image,(StatisticType)parse,
3357 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3358 _exception);
anthony805a2d42011-09-25 08:25:12 +00003359 break;
3360 }
anthonyafa3dfc2012-03-03 11:31:30 +00003361 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003362 {
anthony92c93bd2012-03-19 14:02:47 +00003363 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003364 break;
3365 }
anthonyafa3dfc2012-03-03 11:31:30 +00003366 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003367 {
cristy898c6042012-06-24 00:36:34 +00003368 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00003369 if ((flags & RhoValue) == 0)
cristy898c6042012-06-24 00:36:34 +00003370 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003371 new_image=SwirlImage(_image,geometry_info.rho,
3372 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003373 break;
3374 }
anthonyebb73a22012-03-22 14:25:52 +00003375 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003376 }
3377 case 't':
3378 {
anthonyafa3dfc2012-03-03 11:31:30 +00003379 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003380 {
3381 double
3382 threshold;
3383
anthony52bef752012-03-27 13:54:47 +00003384 threshold=(double) QuantumRange/2;
anthonya322a832013-04-27 06:28:03 +00003385 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00003386 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003387 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003388 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003389 }
anthony92c93bd2012-03-19 14:02:47 +00003390 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003391 break;
3392 }
anthonyafa3dfc2012-03-03 11:31:30 +00003393 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003394 {
anthony7bcfe7f2012-03-30 14:01:22 +00003395 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003396 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003397 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3398 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3399 _exception);
anthony805a2d42011-09-25 08:25:12 +00003400 break;
3401 }
anthonyafa3dfc2012-03-03 11:31:30 +00003402 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003403 {
anthony7bcfe7f2012-03-30 14:01:22 +00003404 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003405 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003406 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003407 break;
3408 }
anthonyafa3dfc2012-03-03 11:31:30 +00003409 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003410 {
anthony464f1c42012-04-22 08:51:01 +00003411 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003412 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003413 break;
3414 }
anthonyafa3dfc2012-03-03 11:31:30 +00003415 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003416 {
3417 PixelInfo
3418 target;
3419
anthony92c93bd2012-03-19 14:02:47 +00003420 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3421 (void) TransparentPaintImage(_image,&target,(Quantum)
anthonya322a832013-04-27 06:28:03 +00003422 TransparentAlpha,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003423 break;
3424 }
anthonyafa3dfc2012-03-03 11:31:30 +00003425 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003426 {
anthony92c93bd2012-03-19 14:02:47 +00003427 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003428 break;
3429 }
anthonyafa3dfc2012-03-03 11:31:30 +00003430 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003431 {
anthony92c93bd2012-03-19 14:02:47 +00003432 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003433 break;
3434 }
anthonyafa3dfc2012-03-03 11:31:30 +00003435 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003436 {
anthony92c93bd2012-03-19 14:02:47 +00003437 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003438 break;
3439 }
anthonyafa3dfc2012-03-03 11:31:30 +00003440 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003441 {
anthonyab3a50c2011-10-27 11:48:57 +00003442 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003443 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003444 break;
3445 }
anthonyebb73a22012-03-22 14:25:52 +00003446 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003447 }
3448 case 'u':
3449 {
anthonyafa3dfc2012-03-03 11:31:30 +00003450 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003451 {
anthony52bef752012-03-27 13:54:47 +00003452 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3453 Option is not documented, bt appears to be for "identify".
3454 We may need a identify specific verbose!
3455 */
anthonya322a832013-04-27 06:28:03 +00003456 if (IsPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00003457 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003458 break;
3459 }
anthony92c93bd2012-03-19 14:02:47 +00003460 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3461 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003462 break;
3463 }
anthonyafa3dfc2012-03-03 11:31:30 +00003464 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003465 {
anthony92c93bd2012-03-19 14:02:47 +00003466 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003467 break;
3468 }
anthonyafa3dfc2012-03-03 11:31:30 +00003469 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003470 {
anthonyfd706f92012-01-19 04:22:02 +00003471 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003472 if ((flags & (RhoValue|SigmaValue)) == 0)
3473 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003474 if ((flags & SigmaValue) == 0)
3475 geometry_info.sigma=1.0;
3476 if ((flags & XiValue) == 0)
3477 geometry_info.xi=1.0;
3478 if ((flags & PsiValue) == 0)
3479 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003480 new_image=UnsharpMaskImage(_image,geometry_info.rho,
cristy3afd4012013-03-25 11:30:44 +00003481 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003482 break;
3483 }
anthonyebb73a22012-03-22 14:25:52 +00003484 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003485 }
3486 case 'v':
3487 {
anthonyafa3dfc2012-03-03 11:31:30 +00003488 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003489 {
anthonyafa3dfc2012-03-03 11:31:30 +00003490 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003491 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003492 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003493 */
anthony92c93bd2012-03-19 14:02:47 +00003494 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003495 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003496 break;
3497 }
anthonyafa3dfc2012-03-03 11:31:30 +00003498 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003499 {
anthonyfd706f92012-01-19 04:22:02 +00003500 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003501 if ((flags & (RhoValue|SigmaValue)) == 0)
3502 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003503 if ((flags & SigmaValue) == 0)
3504 geometry_info.sigma=1.0;
3505 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003506 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003507 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003508 geometry_info.psi=0.1*_image->rows;
cristy8e2392e2013-11-11 17:58:38 +00003509 if ((flags & PercentValue) != 0)
3510 {
cristy720d7562013-11-14 19:18:11 +00003511 geometry_info.xi*=(double) _image->columns/100.0;
3512 geometry_info.psi*=(double) _image->rows/100.0;
cristy8e2392e2013-11-11 17:58:38 +00003513 }
anthony92c93bd2012-03-19 14:02:47 +00003514 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003515 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3516 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003517 break;
3518 }
anthonyebb73a22012-03-22 14:25:52 +00003519 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003520 }
3521 case 'w':
3522 {
anthonyafa3dfc2012-03-03 11:31:30 +00003523 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003524 {
anthonyfd706f92012-01-19 04:22:02 +00003525 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003526 if ((flags & (RhoValue|SigmaValue)) == 0)
3527 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003528 if ((flags & SigmaValue) == 0)
3529 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003530 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3531 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003532 break;
3533 }
anthonyafa3dfc2012-03-03 11:31:30 +00003534 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003535 {
anthony7bcfe7f2012-03-30 14:01:22 +00003536 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003537 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003538 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003539 break;
3540 }
cristy327030c2015-07-25 18:05:50 +00003541 if (LocaleCompare("write-mask",option+1) == 0)
3542 {
3543 /* Note: arguments do not have percent escapes expanded */
3544 Image
3545 *mask;
3546
3547 if (IfPlusOp)
3548 { /* Remove a mask. */
3549 (void) SetImageMask(_image,WritePixelMask,(Image *) NULL,
3550 _exception);
3551 break;
3552 }
3553 /* Set the image mask. */
3554 mask=GetImageCache(_image_info,arg1,_exception);
3555 if (mask == (Image *) NULL)
3556 break;
3557 (void) SetImageMask(_image,WritePixelMask,mask,_exception);
3558 mask=DestroyImage(mask);
3559 break;
3560 }
anthonyebb73a22012-03-22 14:25:52 +00003561 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003562 }
3563 default:
anthonyebb73a22012-03-22 14:25:52 +00003564 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003565 }
anthony964d28e2012-05-17 23:39:46 +00003566 /* clean up percent escape interpreted strings */
3567 if (arg1 != arg1n )
3568 arg1=DestroyString((char *)arg1);
3569 if (arg2 != arg2n )
3570 arg2=DestroyString((char *)arg2);
3571
3572 /* Replace current image with any image that was generated
3573 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003574 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003575 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003576
cristyfe831852013-02-12 14:56:07 +00003577 return(MagickTrue);
anthony92c93bd2012-03-19 14:02:47 +00003578#undef _image_info
3579#undef _draw_info
3580#undef _quantize_info
3581#undef _image
3582#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003583#undef IfNormalOp
3584#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00003585#undef IsNormalOp
3586#undef IsPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003587}
anthonyfd706f92012-01-19 04:22:02 +00003588
cristyfe831852013-02-12 14:56:07 +00003589WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
cristy2c57b742014-10-31 00:40:34 +00003590 const char *option,const char *arg1,const char *arg2,ExceptionInfo *exception)
anthony31f1bf72012-01-30 12:37:22 +00003591{
anthonyc7994672012-11-17 05:33:27 +00003592#if !USE_WAND_METHODS
anthony31f1bf72012-01-30 12:37:22 +00003593 size_t
anthony43f425d2012-02-26 12:58:58 +00003594 n,
anthony31f1bf72012-01-30 12:37:22 +00003595 i;
anthonyc7994672012-11-17 05:33:27 +00003596#endif
anthony31f1bf72012-01-30 12:37:22 +00003597
anthony43f425d2012-02-26 12:58:58 +00003598 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003599 assert(cli_wand->signature == MagickWandSignature);
3600 assert(cli_wand->wand.signature == MagickWandSignature);
anthony43f425d2012-02-26 12:58:58 +00003601 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthonya322a832013-04-27 06:28:03 +00003602
anthony7bcfe7f2012-03-30 14:01:22 +00003603 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00003604 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3605 "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
anthony31f1bf72012-01-30 12:37:22 +00003606
anthonyafa3dfc2012-03-03 11:31:30 +00003607#if !USE_WAND_METHODS
3608 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003609 i=0;
anthony43f425d2012-02-26 12:58:58 +00003610 n=GetImageListLength(cli_wand->wand.images);
3611 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003612 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003613 i++;
cristy2c57b742014-10-31 00:40:34 +00003614 CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
anthony43f425d2012-02-26 12:58:58 +00003615 if ( cli_wand->wand.images->next == (Image *) NULL )
3616 break;
3617 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003618 }
anthony43f425d2012-02-26 12:58:58 +00003619 assert( i == n );
3620 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003621#else
3622 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003623 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
cristy52b632a2014-11-08 00:31:34 +00003624 (void) CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003625 MagickResetIterator(&cli_wand->wand);
3626#endif
cristyfe831852013-02-12 14:56:07 +00003627 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003628}
3629
3630/*
3631%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3632% %
3633% %
3634% %
anthony43f425d2012-02-26 12:58:58 +00003635+ 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 +00003636% %
3637% %
3638% %
3639%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3640%
anthony43f425d2012-02-26 12:58:58 +00003641% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003642% entire image list as a whole. The result is often a complete replacment
anthonyc7994672012-11-17 05:33:27 +00003643% of the image list with a completely new list, or with just a single image
3644% result.
anthony805a2d42011-09-25 08:25:12 +00003645%
3646% The format of the MogrifyImage method is:
3647%
cristyfe831852013-02-12 14:56:07 +00003648% MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3649% const char *option,const char *arg1,const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003650%
3651% A description of each parameter follows:
3652%
anthony43f425d2012-02-26 12:58:58 +00003653% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003654%
anthony36a8c2c2012-02-10 00:08:44 +00003655% o option: The option string for the operation
3656%
anthony31f1bf72012-01-30 12:37:22 +00003657% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003658% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003659%
anthony805a2d42011-09-25 08:25:12 +00003660*/
cristyfe831852013-02-12 14:56:07 +00003661WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3662 const char *option,const char *arg1n,const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003663{
anthonya322a832013-04-27 06:28:03 +00003664 const char /* percent escaped versions of the args */
cristya30f8e62013-02-19 15:03:45 +00003665 *arg1,
3666 *arg2;
anthony2a0ec8c2012-03-24 04:35:56 +00003667
anthony31f1bf72012-01-30 12:37:22 +00003668 Image
3669 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003670
cristya30f8e62013-02-19 15:03:45 +00003671 MagickStatusType
3672 status;
3673
3674 ssize_t
3675 parse;
anthony964d28e2012-05-17 23:39:46 +00003676
anthony2e4501b2012-03-30 04:41:54 +00003677#define _image_info (cli_wand->wand.image_info)
3678#define _images (cli_wand->wand.images)
3679#define _exception (cli_wand->wand.exception)
3680#define _draw_info (cli_wand->draw_info)
3681#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003682#define _process_flags (cli_wand->process_flags)
3683#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003684#define IfNormalOp (*option=='-')
3685#define IfPlusOp (*option!='-')
dirkb9dbc292015-07-26 09:50:00 +00003686#define IsNormalOp IfNormalOp ? MagickTrue : MagickFalse
anthony805a2d42011-09-25 08:25:12 +00003687
anthony43f425d2012-02-26 12:58:58 +00003688 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00003689 assert(cli_wand->signature == MagickWandSignature);
3690 assert(cli_wand->wand.signature == MagickWandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003691 assert(_images != (Image *) NULL); /* _images must be present */
anthony31f1bf72012-01-30 12:37:22 +00003692
anthonya322a832013-04-27 06:28:03 +00003693 if (IfMagickTrue(cli_wand->wand.debug))
3694 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
cristy606b9232015-07-04 13:05:09 +00003695 "- List Operator: %s \"%s\" \"%s\"", option,
3696 arg1n == (const char *) NULL ? "null" : arg1n,
3697 arg2n == (const char *) NULL ? "null" : arg2n);
anthonya322a832013-04-27 06:28:03 +00003698
anthony964d28e2012-05-17 23:39:46 +00003699 arg1 = arg1n;
3700 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00003701
3702 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00003703 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3704 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3705 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3706 /* Interpret Percent escapes in argument 1 */
3707 if (arg1n != (char *) NULL) {
3708 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3709 if (arg1 == (char *) NULL) {
3710 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3711 arg1=arg1n; /* use the given argument as is */
3712 }
3713 }
3714 if (arg2n != (char *) NULL) {
3715 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3716 if (arg2 == (char *) NULL) {
3717 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3718 arg2=arg2n; /* use the given argument as is */
3719 }
3720 }
3721 }
anthony4837ac22012-05-18 23:39:48 +00003722#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003723#undef _option_type
3724
cristyfe831852013-02-12 14:56:07 +00003725 status=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00003726 new_images=NewImageList();
3727
anthonyafa3dfc2012-03-03 11:31:30 +00003728 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003729 {
3730 case 'a':
3731 {
anthonyafa3dfc2012-03-03 11:31:30 +00003732 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003733 {
anthonya322a832013-04-27 06:28:03 +00003734 new_images=AppendImages(_images,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003735 break;
3736 }
cristy52ad9e92013-02-08 23:23:29 +00003737 if (LocaleCompare("average",option+1) == 0)
3738 {
3739 CLIWandWarnReplaced("-evaluate-sequence Mean");
cristy52b632a2014-11-08 00:31:34 +00003740 (void) CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
cristy52ad9e92013-02-08 23:23:29 +00003741 break;
3742 }
anthonyebb73a22012-03-22 14:25:52 +00003743 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003744 }
3745 case 'c':
3746 {
cristy5f257b22012-03-07 00:27:29 +00003747 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003748 {
anthony92c93bd2012-03-19 14:02:47 +00003749 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003750 break;
3751 }
anthonyafa3dfc2012-03-03 11:31:30 +00003752 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003753 {
anthony805a2d42011-09-25 08:25:12 +00003754 Image
anthony31f1bf72012-01-30 12:37:22 +00003755 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003756
anthonyafa3dfc2012-03-03 11:31:30 +00003757 /* FUTURE - make this a compose option, and thus can be used
3758 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003759 _images.
cristy87c02f42012-02-24 00:19:10 +00003760 */
anthony92c93bd2012-03-19 14:02:47 +00003761 new_images=RemoveFirstImageFromList(&_images);
3762 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003763 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003764 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003765 break;
cristyf68c0be2015-04-28 22:48:37 +00003766 (void) ClutImage(new_images,clut_image,new_images->interpolate,
3767 _exception);
anthony805a2d42011-09-25 08:25:12 +00003768 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003769 break;
3770 }
anthonyafa3dfc2012-03-03 11:31:30 +00003771 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003772 {
anthony92c93bd2012-03-19 14:02:47 +00003773 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003774 break;
3775 }
anthonyafa3dfc2012-03-03 11:31:30 +00003776 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003777 {
cristy9a0e8ef2015-05-11 23:20:15 +00003778 parse=(ssize_t) _images->colorspace;
anthony5a4ff372013-05-01 04:48:57 +00003779 if ( IfPlusOp )
cristyf68c0be2015-04-28 22:48:37 +00003780 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
cristy8448a0d2013-02-15 18:20:53 +00003781 if (parse < 0)
3782 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3783 arg1);
cristy46f354c2012-07-04 13:31:29 +00003784 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003785 break;
3786 }
cristye863c052013-09-04 11:31:30 +00003787 if (LocaleCompare("compare",option+1) == 0)
3788 {
3789 double
3790 distortion;
3791
3792 Image
3793 *image,
3794 *reconstruct_image;
3795
3796 MetricType
3797 metric;
3798
3799 /*
3800 Mathematically and visually annotate the difference between an
3801 image and its reconstruction.
3802 */
3803 image=RemoveFirstImageFromList(&_images);
3804 reconstruct_image=RemoveFirstImageFromList(&_images);
3805 /* FUTURE - produce Exception, rather than silent fail */
3806 if (reconstruct_image == (Image *) NULL)
3807 break;
3808 metric=UndefinedErrorMetric;
3809 option=GetImageOption(_image_info,"metric");
3810 if (option != (const char *) NULL)
3811 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
3812 MagickFalse,option);
3813 new_images=CompareImages(image,reconstruct_image,metric,&distortion,
3814 _exception);
3815 (void) distortion;
3816 reconstruct_image=DestroyImage(reconstruct_image);
3817 image=DestroyImage(image);
3818 break;
3819 }
cristy790190d2013-10-04 00:51:51 +00003820 if (LocaleCompare("complex",option+1) == 0)
3821 {
3822 parse=ParseCommandOption(MagickComplexOptions,MagickFalse,arg1);
3823 if (parse < 0)
3824 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3825 option,arg1);
cristyb8f66bb2013-10-04 15:21:58 +00003826 new_images=ComplexImages(_images,(ComplexOperator) parse,_exception);
cristy790190d2013-10-04 00:51:51 +00003827 break;
3828 }
anthonyafa3dfc2012-03-03 11:31:30 +00003829 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003830 {
cristyfeb3e962012-03-29 17:25:55 +00003831 CompositeOperator
3832 compose;
3833
3834 const char*
3835 value;
3836
3837 MagickBooleanType
3838 clip_to_self;
3839
anthony805a2d42011-09-25 08:25:12 +00003840 Image
3841 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003842 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003843
3844 RectangleInfo
3845 geometry;
3846
anthony7bcfe7f2012-03-30 14:01:22 +00003847 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003848 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003849 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003850 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003851 else
3852 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3853 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003854
anthony7bcfe7f2012-03-30 14:01:22 +00003855 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003856 value=GetImageOption(_image_info,"compose:clip-to-self");
3857 if (value == (const char *) NULL)
3858 clip_to_self=MagickTrue;
3859 else
3860 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3861 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003862 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003863 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003864 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
dirk9a846de2015-07-25 16:51:01 +00003865 clip_to_self=IsStringFalse(value);
anthony2e4501b2012-03-30 04:41:54 +00003866 }
3867
anthony92c93bd2012-03-19 14:02:47 +00003868 new_images=RemoveFirstImageFromList(&_images);
3869 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003870 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003871 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003872
anthony31f1bf72012-01-30 12:37:22 +00003873 /* FUTURE - this should not be here! - should be part of -geometry */
3874 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003875 source_image->geometry,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003876 SetGeometry(source_image,&geometry);
3877 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3878 GravityAdjustGeometry(new_images->columns,new_images->rows,
cristyfe831852013-02-12 14:56:07 +00003879 new_images->gravity, &geometry);
anthony92c93bd2012-03-19 14:02:47 +00003880 mask_image=RemoveFirstImageFromList(&_images);
cristy052d1f72015-01-04 21:10:37 +00003881 if (mask_image == (Image *) NULL)
3882 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
3883 geometry.x,geometry.y,_exception);
3884 else
cristyfe831852013-02-12 14:56:07 +00003885 {
cristy052d1f72015-01-04 21:10:37 +00003886 if ((compose == DisplaceCompositeOp) ||
3887 (compose == DistortCompositeOp))
3888 {
3889 status&=CompositeImage(source_image,mask_image,
3890 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3891 status&=CompositeImage(new_images,source_image,compose,
3892 clip_to_self,geometry.x,geometry.y,_exception);
3893 }
cristyfae52a22014-11-27 21:49:03 +00003894 else
cristy052d1f72015-01-04 21:10:37 +00003895 {
3896 Image
3897 *clone_image;
3898
3899 clone_image=CloneImage(new_images,0,0,MagickTrue,_exception);
3900 if (clone_image == (Image *) NULL)
3901 break;
3902 status&=CompositeImage(new_images,source_image,compose,
3903 clip_to_self,geometry.x,geometry.y,_exception);
3904 status&=CompositeImage(new_images,mask_image,
3905 CopyAlphaCompositeOp,MagickTrue,0,0,_exception);
3906 status&=CompositeImage(clone_image,new_images,OverCompositeOp,
Cristy087a0592015-08-30 16:40:35 -04003907 clip_to_self,0,0,_exception);
cristy052d1f72015-01-04 21:10:37 +00003908 new_images=DestroyImage(new_images);
3909 new_images=clone_image;
3910 }
cristyfe831852013-02-12 14:56:07 +00003911 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003912 }
anthony31f1bf72012-01-30 12:37:22 +00003913 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003914 break;
3915 }
cristy8c4c1c42015-06-22 23:51:22 +00003916 if (LocaleCompare("copy",option+1) == 0)
3917 {
3918 Image
3919 *source_image;
3920
3921 OffsetInfo
3922 offset;
3923
3924 RectangleInfo
3925 geometry;
3926
3927 /*
3928 Copy image pixels.
3929 */
3930 if (IfMagickFalse(IsGeometry(arg1)))
3931 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3932 if (IfMagickFalse(IsGeometry(arg2)))
3933 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3934 (void) ParsePageGeometry(_images,arg2,&geometry,_exception);
3935 offset.x=geometry.x;
3936 offset.y=geometry.y;
cristy8c4c1c42015-06-22 23:51:22 +00003937 source_image=_images;
3938 if (source_image->next != (Image *) NULL)
3939 source_image=source_image->next;
cristy923019b2015-06-23 01:13:00 +00003940 (void) ParsePageGeometry(source_image,arg1,&geometry,_exception);
cristy8c4c1c42015-06-22 23:51:22 +00003941 (void) CopyImagePixels(_images,source_image,&geometry,&offset,
3942 _exception);
3943 break;
3944 }
anthonyebb73a22012-03-22 14:25:52 +00003945 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003946 }
3947 case 'd':
3948 {
anthonyafa3dfc2012-03-03 11:31:30 +00003949 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003950 {
anthony464f1c42012-04-22 08:51:01 +00003951 CLIWandWarnReplaced("-layer CompareAny");
cristy52b632a2014-11-08 00:31:34 +00003952 (void) CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003953 break;
3954 }
anthonyafa3dfc2012-03-03 11:31:30 +00003955 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003956 {
anthonyafa3dfc2012-03-03 11:31:30 +00003957 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003958 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003959 else
anthony92c93bd2012-03-19 14:02:47 +00003960 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003961 break;
3962 }
anthonyafa3dfc2012-03-03 11:31:30 +00003963 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003964 {
anthonyafa3dfc2012-03-03 11:31:30 +00003965 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003966 {
3967 const char
3968 *p;
3969
3970 size_t
3971 number_duplicates;
3972
anthony7bcfe7f2012-03-30 14:01:22 +00003973 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003974 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3975 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003976 number_duplicates=(size_t) StringToLong(arg1);
3977 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003978 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003979 new_images=DuplicateImages(_images,number_duplicates,"-1",
3980 _exception);
anthony805a2d42011-09-25 08:25:12 +00003981 else
anthony92c93bd2012-03-19 14:02:47 +00003982 new_images=DuplicateImages(_images,number_duplicates,p,
3983 _exception);
anthony805a2d42011-09-25 08:25:12 +00003984 }
anthonyafa3dfc2012-03-03 11:31:30 +00003985 else
anthony92c93bd2012-03-19 14:02:47 +00003986 new_images=DuplicateImages(_images,1,"-1",_exception);
3987 AppendImageToList(&_images, new_images);
cristyf432c632014-12-07 15:11:28 +00003988 new_images=(Image *) NULL;
anthony805a2d42011-09-25 08:25:12 +00003989 break;
3990 }
anthonyebb73a22012-03-22 14:25:52 +00003991 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003992 }
3993 case 'e':
3994 {
anthonyafa3dfc2012-03-03 11:31:30 +00003995 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003996 {
cristy790190d2013-10-04 00:51:51 +00003997 parse=ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3998 if (parse < 0)
anthony2a0ec8c2012-03-24 04:35:56 +00003999 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
cristy790190d2013-10-04 00:51:51 +00004000 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00004001 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
cristy790190d2013-10-04 00:51:51 +00004002 _exception);
anthony805a2d42011-09-25 08:25:12 +00004003 break;
4004 }
anthonyebb73a22012-03-22 14:25:52 +00004005 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004006 }
4007 case 'f':
4008 {
anthonyafa3dfc2012-03-03 11:31:30 +00004009 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004010 {
cristyf68c0be2015-04-28 22:48:37 +00004011 new_images=ForwardFourierTransformImage(_images,IsNormalOp,
4012 _exception);
anthony805a2d42011-09-25 08:25:12 +00004013 break;
4014 }
anthonyafa3dfc2012-03-03 11:31:30 +00004015 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004016 {
anthony319dac62012-03-06 04:12:44 +00004017 /* REDIRECTED to use -layers flatten instead */
cristy52b632a2014-11-08 00:31:34 +00004018 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004019 break;
4020 }
anthonyafa3dfc2012-03-03 11:31:30 +00004021 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004022 {
anthony92c93bd2012-03-19 14:02:47 +00004023 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004024 break;
4025 }
anthonyebb73a22012-03-22 14:25:52 +00004026 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004027 }
4028 case 'h':
4029 {
anthonyafa3dfc2012-03-03 11:31:30 +00004030 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004031 {
anthony31f1bf72012-01-30 12:37:22 +00004032 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00004033 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00004034 */
anthony805a2d42011-09-25 08:25:12 +00004035 Image
anthony31f1bf72012-01-30 12:37:22 +00004036 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00004037
anthony92c93bd2012-03-19 14:02:47 +00004038 new_images=RemoveFirstImageFromList(&_images);
4039 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004040 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004041 break;
anthony92c93bd2012-03-19 14:02:47 +00004042 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00004043 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00004044 break;
4045 }
anthonyebb73a22012-03-22 14:25:52 +00004046 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004047 }
4048 case 'i':
4049 {
anthonyafa3dfc2012-03-03 11:31:30 +00004050 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004051 {
4052 Image
anthony805a2d42011-09-25 08:25:12 +00004053 *magnitude_image,
4054 *phase_image;
4055
anthony92c93bd2012-03-19 14:02:47 +00004056 magnitude_image=RemoveFirstImageFromList(&_images);
4057 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00004058 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00004059 if (phase_image == (Image *) NULL)
4060 break;
4061 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
cristyf68c0be2015-04-28 22:48:37 +00004062 IsNormalOp,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004063 magnitude_image=DestroyImage(magnitude_image);
4064 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00004065 break;
4066 }
anthonyafa3dfc2012-03-03 11:31:30 +00004067 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004068 {
4069 Image
anthony31f1bf72012-01-30 12:37:22 +00004070 *insert_image,
4071 *index_image;
4072
4073 ssize_t
4074 index;
anthony805a2d42011-09-25 08:25:12 +00004075
anthony7bcfe7f2012-03-30 14:01:22 +00004076 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00004077 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004078 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004079 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004080 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004081 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004082 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004083 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004084 PrependImageToList(&_images,insert_image);
4085 else if (index == (ssize_t) GetImageListLength(_images))
4086 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004087 else
anthony43f425d2012-02-26 12:58:58 +00004088 {
anthony92c93bd2012-03-19 14:02:47 +00004089 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004090 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004091 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004092 InsertImageInList(&index_image,insert_image);
4093 }
anthony92c93bd2012-03-19 14:02:47 +00004094 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004095 break;
4096 }
anthonyebb73a22012-03-22 14:25:52 +00004097 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004098 }
4099 case 'l':
4100 {
anthonyafa3dfc2012-03-03 11:31:30 +00004101 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004102 {
anthonyfe1aa782012-03-24 13:43:04 +00004103 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4104 if ( parse < 0 )
4105 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4106 option,arg1);
cristya0417062012-09-02 23:34:56 +00004107 switch ((LayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004108 {
4109 case CoalesceLayer:
4110 {
anthony92c93bd2012-03-19 14:02:47 +00004111 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004112 break;
4113 }
4114 case CompareAnyLayer:
4115 case CompareClearLayer:
4116 case CompareOverlayLayer:
4117 default:
4118 {
cristya0417062012-09-02 23:34:56 +00004119 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00004120 _exception);
anthony805a2d42011-09-25 08:25:12 +00004121 break;
4122 }
4123 case MergeLayer:
4124 case FlattenLayer:
4125 case MosaicLayer:
4126 case TrimBoundsLayer:
4127 {
cristya0417062012-09-02 23:34:56 +00004128 new_images=MergeImageLayers(_images,(LayerMethod) parse,
cristyf68c0be2015-04-28 22:48:37 +00004129 _exception);
anthony805a2d42011-09-25 08:25:12 +00004130 break;
4131 }
4132 case DisposeLayer:
4133 {
anthony92c93bd2012-03-19 14:02:47 +00004134 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004135 break;
4136 }
4137 case OptimizeImageLayer:
4138 {
anthony92c93bd2012-03-19 14:02:47 +00004139 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004140 break;
4141 }
4142 case OptimizePlusLayer:
4143 {
anthony92c93bd2012-03-19 14:02:47 +00004144 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004145 break;
4146 }
4147 case OptimizeTransLayer:
4148 {
anthony92c93bd2012-03-19 14:02:47 +00004149 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004150 break;
4151 }
4152 case RemoveDupsLayer:
4153 {
anthony92c93bd2012-03-19 14:02:47 +00004154 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004155 break;
4156 }
4157 case RemoveZeroLayer:
4158 {
anthony92c93bd2012-03-19 14:02:47 +00004159 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004160 break;
4161 }
4162 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004163 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004164 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004165 if (new_images == (Image *) NULL)
4166 break;
anthony92c93bd2012-03-19 14:02:47 +00004167 _images=DestroyImageList(_images);
4168 _images=OptimizeImageLayers(new_images,_exception);
4169 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004170 break;
4171 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004172 OptimizeImageTransparency(_images,_exception);
4173 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4174 _exception);
anthony805a2d42011-09-25 08:25:12 +00004175 break;
4176 }
4177 case CompositeLayer:
4178 {
anthony805a2d42011-09-25 08:25:12 +00004179 Image
4180 *source;
4181
4182 RectangleInfo
4183 geometry;
4184
anthony31f1bf72012-01-30 12:37:22 +00004185 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004186 compose;
4187
4188 const char*
4189 value;
4190
anthony92c93bd2012-03-19 14:02:47 +00004191 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004192 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004193 if (value != (const char *) NULL)
4194 compose=(CompositeOperator) ParseCommandOption(
4195 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004196
anthony31f1bf72012-01-30 12:37:22 +00004197 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004198 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004199 while (source != (Image *) NULL)
4200 {
4201 source=GetNextImageInList(source);
4202 if ((source != (Image *) NULL) &&
4203 (LocaleCompare(source->magick,"NULL") == 0))
4204 break;
4205 }
4206 if (source != (Image *) NULL)
4207 {
4208 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4209 (GetNextImageInList(source) == (Image *) NULL))
4210 source=(Image *) NULL;
4211 else
anthony31f1bf72012-01-30 12:37:22 +00004212 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004213 source=SplitImageList(source->previous);
4214 DeleteImageFromList(&source);
4215 }
4216 }
4217 if (source == (Image *) NULL)
4218 {
anthony92c93bd2012-03-19 14:02:47 +00004219 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004220 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004221 break;
4222 }
anthony31f1bf72012-01-30 12:37:22 +00004223 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004224 SetGeometry(_images,&geometry);
4225 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004226 geometry.width=source->page.width != 0 ?
4227 source->page.width : source->columns;
4228 geometry.height=source->page.height != 0 ?
4229 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004230 GravityAdjustGeometry(_images->page.width != 0 ?
4231 _images->page.width : _images->columns,
4232 _images->page.height != 0 ? _images->page.height :
4233 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004234
anthony31f1bf72012-01-30 12:37:22 +00004235 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004236 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4237 _exception);
anthony805a2d42011-09-25 08:25:12 +00004238 source=DestroyImageList(source);
4239 break;
4240 }
4241 }
anthony805a2d42011-09-25 08:25:12 +00004242 break;
4243 }
anthonyebb73a22012-03-22 14:25:52 +00004244 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004245 }
4246 case 'm':
4247 {
anthonyafa3dfc2012-03-03 11:31:30 +00004248 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004249 {
anthony464f1c42012-04-22 08:51:01 +00004250 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004251 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004252 break;
4253 }
cristye863c052013-09-04 11:31:30 +00004254 if (LocaleCompare("metric",option+1) == 0)
4255 break;
anthonyafa3dfc2012-03-03 11:31:30 +00004256 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004257 {
4258 Image
4259 *morph_image;
4260
anthony7bcfe7f2012-03-30 14:01:22 +00004261 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004262 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004263 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4264 _exception);
anthony805a2d42011-09-25 08:25:12 +00004265 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004266 break;
anthony92c93bd2012-03-19 14:02:47 +00004267 _images=DestroyImageList(_images);
4268 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004269 break;
4270 }
anthonyafa3dfc2012-03-03 11:31:30 +00004271 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004272 {
anthony319dac62012-03-06 04:12:44 +00004273 /* REDIRECTED to use -layers mosaic instead */
cristy52b632a2014-11-08 00:31:34 +00004274 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004275 break;
4276 }
anthonyebb73a22012-03-22 14:25:52 +00004277 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004278 }
4279 case 'p':
4280 {
cristy02016cf2012-11-13 01:14:41 +00004281 if (LocaleCompare("poly",option+1) == 0)
4282 {
4283 double
4284 *args;
4285
4286 ssize_t
4287 count;
4288
4289 /* convert argument string into an array of doubles */
cristyace09c62015-01-21 12:54:30 +00004290 args = StringToArrayOfDoubles(arg1,&count,_exception);
cristyf432c632014-12-07 15:11:28 +00004291 if (args == (double *) NULL )
cristyace09c62015-01-21 12:54:30 +00004292 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg1);
cristyf68c0be2015-04-28 22:48:37 +00004293 new_images=PolynomialImage(_images,(size_t) (count >> 1),args,
4294 _exception);
cristy02016cf2012-11-13 01:14:41 +00004295 args=(double *) RelinquishMagickMemory(args);
4296 break;
4297 }
anthonyafa3dfc2012-03-03 11:31:30 +00004298 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004299 {
anthonyb1d483a2012-04-14 12:53:56 +00004300 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004301 char
4302 **arguments;
4303
4304 int
4305 j,
4306 number_arguments;
4307
anthony31f1bf72012-01-30 12:37:22 +00004308 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004309 if (arguments == (char **) NULL)
4310 break;
anthony31f1bf72012-01-30 12:37:22 +00004311 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004312 {
4313 char
4314 breaker,
4315 quote,
4316 *token;
4317
4318 const char
4319 *arguments;
4320
4321 int
4322 next,
4323 status;
4324
4325 size_t
4326 length;
4327
4328 TokenInfo
4329 *token_info;
4330
4331 /*
anthony24aa8822012-03-11 00:56:06 +00004332 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004333 */
cristy4bc3dac2014-01-18 15:17:26 +00004334 assert(arg1 != (const char *) NULL);
anthony31f1bf72012-01-30 12:37:22 +00004335 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004336 token=(char *) NULL;
cristy151b66d2015-04-15 10:50:31 +00004337 if (~length >= (MagickPathExtent-1))
4338 token=(char *) AcquireQuantumMemory(length+MagickPathExtent,
anthony805a2d42011-09-25 08:25:12 +00004339 sizeof(*token));
4340 if (token == (char *) NULL)
4341 break;
4342 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004343 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004344 token_info=AcquireTokenInfo();
4345 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4346 "\"",'\0',&breaker,&next,&quote);
4347 token_info=DestroyTokenInfo(token_info);
4348 if (status == 0)
4349 {
4350 const char
4351 *argv;
4352
4353 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004354 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4355 _exception);
anthony805a2d42011-09-25 08:25:12 +00004356 }
4357 token=DestroyString(token);
4358 break;
4359 }
4360 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004361 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4362 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004363 for (j=0; j < number_arguments; j++)
4364 arguments[j]=DestroyString(arguments[j]);
4365 arguments=(char **) RelinquishMagickMemory(arguments);
4366 break;
4367 }
anthonyebb73a22012-03-22 14:25:52 +00004368 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004369 }
4370 case 'r':
4371 {
anthonyafa3dfc2012-03-03 11:31:30 +00004372 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004373 {
anthony92c93bd2012-03-19 14:02:47 +00004374 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004375 break;
4376 }
anthonyafa3dfc2012-03-03 11:31:30 +00004377 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004378 {
anthony92c93bd2012-03-19 14:02:47 +00004379 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004380 break;
4381 }
anthonyebb73a22012-03-22 14:25:52 +00004382 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004383 }
4384 case 's':
4385 {
anthonyafa3dfc2012-03-03 11:31:30 +00004386 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004387 {
anthonycd358fc2012-04-16 13:59:03 +00004388 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004389 ssize_t
4390 offset;
4391
anthony7bcfe7f2012-03-30 14:01:22 +00004392 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004393 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004394 offset=(ssize_t) StringToLong(arg1);
anthonya322a832013-04-27 06:28:03 +00004395 new_images=SmushImages(_images,IsNormalOp,offset,_exception);
anthonycd358fc2012-04-16 13:59:03 +00004396 break;
4397 }
4398 if (LocaleCompare("subimage",option+1) == 0)
4399 {
4400 Image
4401 *base_image,
4402 *compare_image;
4403
cristyf68c0be2015-04-28 22:48:37 +00004404 const char
4405 *value;
anthonycd358fc2012-04-16 13:59:03 +00004406
4407 MetricType
4408 metric;
4409
4410 double
4411 similarity;
4412
4413 RectangleInfo
4414 offset;
4415
4416 base_image=GetImageFromList(_images,0);
4417 compare_image=GetImageFromList(_images,1);
4418
4419 /* Comparision Metric */
cristy08163292013-07-11 00:00:37 +00004420 metric=UndefinedErrorMetric;
anthonycd358fc2012-04-16 13:59:03 +00004421 value=GetImageOption(_image_info,"metric");
4422 if (value != (const char *) NULL)
4423 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4424 MagickFalse,value);
4425
cristy99fcec42013-03-15 21:37:59 +00004426 new_images=SimilarityImage(base_image,compare_image,metric,0.0,
cristyf68c0be2015-04-28 22:48:37 +00004427 &offset,&similarity,_exception);
anthonycd358fc2012-04-16 13:59:03 +00004428
cristye0246372015-06-28 12:38:15 +00004429 if (new_images != (Image *) NULL)
4430 {
4431 char
4432 result[MagickPathExtent];
anthonycd358fc2012-04-16 13:59:03 +00004433
cristye0246372015-06-28 12:38:15 +00004434 (void) FormatLocaleString(result,MagickPathExtent,"%lf",
4435 similarity);
4436 (void) SetImageProperty(new_images,"subimage:similarity",result,
4437 _exception);
4438 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4439 offset.x);
4440 (void) SetImageProperty(new_images,"subimage:x",result,
4441 _exception);
4442 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4443 offset.y);
4444 (void) SetImageProperty(new_images,"subimage:y",result,
4445 _exception);
4446 (void) FormatLocaleString(result,MagickPathExtent,
4447 "%lux%lu%+ld%+ld",(unsigned long) offset.width,(unsigned long)
4448 offset.height,(long) offset.x,(long) offset.y);
4449 (void) SetImageProperty(new_images,"subimage:offset",result,
4450 _exception);
4451 }
anthony805a2d42011-09-25 08:25:12 +00004452 break;
4453 }
cristyf68c0be2015-04-28 22:48:37 +00004454 if (LocaleCompare("swap",option+1) == 0)
4455 {
anthony0ea037a2012-04-03 12:14:39 +00004456 Image
4457 *p,
4458 *q,
4459 *swap;
anthony805a2d42011-09-25 08:25:12 +00004460
anthony0ea037a2012-04-03 12:14:39 +00004461 ssize_t
4462 index,
4463 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004464
cristy6b36c942013-02-17 00:36:24 +00004465 index=(-1);
4466 swap_index=(-2);
anthony0ea037a2012-04-03 12:14:39 +00004467 if (IfNormalOp) {
4468 GeometryInfo
4469 geometry_info;
4470
4471 MagickStatusType
4472 flags;
4473
4474 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004475 flags=ParseGeometry(arg1,&geometry_info);
cristy90fbd1c2013-02-17 00:35:35 +00004476 if ((flags & RhoValue) == 0)
anthonyb1e21ed2012-04-20 12:43:12 +00004477 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004478 index=(ssize_t) geometry_info.rho;
4479 if ((flags & SigmaValue) != 0)
4480 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004481 }
anthony0ea037a2012-04-03 12:14:39 +00004482 p=GetImageFromList(_images,index);
4483 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004484 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4485 if (IfNormalOp)
4486 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4487 else
4488 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4489 }
anthony0ea037a2012-04-03 12:14:39 +00004490 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004491 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004492 swap=CloneImage(p,0,0,MagickTrue,_exception);
4493 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4494 ReplaceImageInList(&q,swap);
4495 _images=GetFirstImageInList(q);
4496 break;
4497 }
anthonyebb73a22012-03-22 14:25:52 +00004498 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004499 }
anthony805a2d42011-09-25 08:25:12 +00004500 default:
anthonyebb73a22012-03-22 14:25:52 +00004501 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004502 }
anthony964d28e2012-05-17 23:39:46 +00004503
4504 /* clean up percent escape interpreted strings */
4505 if (arg1 != arg1n )
4506 arg1=DestroyString((char *)arg1);
4507 if (arg2 != arg2n )
4508 arg2=DestroyString((char *)arg2);
4509
4510 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004511 if (new_images == (Image *) NULL)
cristy6398ec72013-11-28 02:00:27 +00004512 return(status == 0 ? MagickFalse : MagickTrue);
anthony964d28e2012-05-17 23:39:46 +00004513 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004514 _images=GetFirstImageInList(new_images);
cristy6398ec72013-11-28 02:00:27 +00004515 return(status == 0 ? MagickFalse : MagickTrue);
anthony31f1bf72012-01-30 12:37:22 +00004516
anthony92c93bd2012-03-19 14:02:47 +00004517#undef _image_info
4518#undef _images
4519#undef _exception
4520#undef _draw_info
4521#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004522#undef IfNormalOp
4523#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00004524#undef IsNormalOp
anthony805a2d42011-09-25 08:25:12 +00004525}
anthony43f425d2012-02-26 12:58:58 +00004526
4527/*
4528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4529% %
4530% %
4531% %
anthony964d28e2012-05-17 23:39:46 +00004532+ 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 +00004533% %
4534% %
4535% %
4536%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4537%
anthony464f1c42012-04-22 08:51:01 +00004538% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004539% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004540%
anthony4837ac22012-05-18 23:39:48 +00004541% The classic operators of this type is "-read", which actually creates
4542% images even when no images are present. Or image stack operators, which
4543% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004544%
anthony4837ac22012-05-18 23:39:48 +00004545% Note that these operators may involve other special 'option' prefix
4546% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004547%
anthony464f1c42012-04-22 08:51:01 +00004548% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004549%
anthony464f1c42012-04-22 08:51:01 +00004550% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4551% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004552%
4553% A description of each parameter follows:
4554%
anthonyc7994672012-11-17 05:33:27 +00004555% o cli_wand: the main CLI Wand to use. (sometimes not required)
anthony43f425d2012-02-26 12:58:58 +00004556%
4557% o option: The special option (with any switch char) to process
4558%
anthony464f1c42012-04-22 08:51:01 +00004559% o arg1 & arg2: Argument for option, if required
4560% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004561%
4562*/
cristyfe831852013-02-12 14:56:07 +00004563WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
anthonya322a832013-04-27 06:28:03 +00004564 const char *option,const char *arg1n,const char *arg2n)
anthony43f425d2012-02-26 12:58:58 +00004565{
anthonya322a832013-04-27 06:28:03 +00004566 const char /* percent escaped versions of the args */
anthony4837ac22012-05-18 23:39:48 +00004567 *arg1,
4568 *arg2;
anthony4837ac22012-05-18 23:39:48 +00004569
anthony8226e722012-04-05 14:25:46 +00004570#define _image_info (cli_wand->wand.image_info)
4571#define _images (cli_wand->wand.images)
4572#define _exception (cli_wand->wand.exception)
anthonya322a832013-04-27 06:28:03 +00004573#define _process_flags (cli_wand->process_flags)
4574#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthony8226e722012-04-05 14:25:46 +00004575#define IfNormalOp (*option=='-')
4576#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004577
4578 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004579 assert(cli_wand->signature == MagickWandSignature);
4580 assert(cli_wand->wand.signature == MagickWandSignature);
anthonya322a832013-04-27 06:28:03 +00004581
anthony7bcfe7f2012-03-30 14:01:22 +00004582 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00004583 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
cristye1f6cfe2015-06-27 15:50:30 +00004584 "- NoImage Operator: %s \"%s\" \"%s\"", option,
4585 arg1n != (char *) NULL ? arg1n : "",
4586 arg2n != (char *) NULL ? arg2n : "");
anthony43f425d2012-02-26 12:58:58 +00004587
anthony4837ac22012-05-18 23:39:48 +00004588 arg1 = arg1n;
4589 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00004590
4591 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +00004592 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4593 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4594 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4595 /* Interpret Percent escapes in argument 1 */
4596 if (arg1n != (char *) NULL) {
4597 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4598 if (arg1 == (char *) NULL) {
4599 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4600 arg1=arg1n; /* use the given argument as is */
4601 }
4602 }
4603 if (arg2n != (char *) NULL) {
4604 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4605 if (arg2 == (char *) NULL) {
4606 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4607 arg2=arg2n; /* use the given argument as is */
4608 }
4609 }
4610 }
4611#undef _process_flags
4612#undef _option_type
anthony4837ac22012-05-18 23:39:48 +00004613
4614 do { /* break to exit code */
4615 /*
4616 No-op options (ignore these)
4617 */
anthonyc7994672012-11-17 05:33:27 +00004618 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
anthony4837ac22012-05-18 23:39:48 +00004619 break;
4620 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4621 break;
anthonyc7994672012-11-17 05:33:27 +00004622 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4623 break;
4624 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
anthony4837ac22012-05-18 23:39:48 +00004625 break;
4626 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4627 break;
4628 /*
4629 Image Reading
4630 */
4631 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4632 ( LocaleCompare("--",option) == 0 ) ) {
4633 /* Do Glob filename Expansion for 'arg1' then read all images.
4634 *
4635 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4636 * (but attaching to the filenames in the generated argument list) any
4637 * [...] read modifiers that may be present.
4638 *
4639 * For example: It will expand '*.gif[20x20]' into a list such as
4640 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4641 *
4642 * NOTE: In IMv6 this was done globally across all images. This
4643 * meant you could include IM options in '@filename' lists, but you
4644 * could not include comments. Doing it only for image read makes
4645 * it far more secure.
4646 *
4647 * Note: arguments do not have percent escapes expanded for security
4648 * reasons.
4649 */
4650 int argc;
4651 char **argv;
4652 ssize_t i;
4653
4654 argc = 1;
4655 argv = (char **) &arg1;
4656
4657 /* Expand 'glob' expressions in the given filename.
4658 Expansion handles any 'coder:' prefix, or read modifiers attached
4659 to the filename, including them in the resulting expanded list.
4660 */
4661 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4662 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4663 option,GetExceptionMessage(errno));
4664
4665 /* loop over expanded filename list, and read then all in */
cristy52b632a2014-11-08 00:31:34 +00004666 for (i=0; i < (ssize_t) argc; i++) {
anthony4837ac22012-05-18 23:39:48 +00004667 Image *
4668 new_images;
4669 if (IfMagickTrue(_image_info->ping))
4670 new_images=PingImages(_image_info,argv[i],_exception);
4671 else
4672 new_images=ReadImages(_image_info,argv[i],_exception);
4673 AppendImageToList(&_images, new_images);
4674 }
4675 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4676 break;
4677 }
4678 /*
4679 Image Writing
4680 Note: Writing a empty image list is valid in specific cases
4681 */
4682 if (LocaleCompare("write",option+1) == 0) {
4683 /* Note: arguments do not have percent escapes expanded */
4684 char
cristy151b66d2015-04-15 10:50:31 +00004685 key[MagickPathExtent];
anthony4837ac22012-05-18 23:39:48 +00004686
4687 Image
4688 *write_images;
4689
4690 ImageInfo
4691 *write_info;
4692
4693 /* Need images, unless a "null:" output coder is used */
anthonya322a832013-04-27 06:28:03 +00004694 if ( _images == (Image *) NULL ) {
anthony4837ac22012-05-18 23:39:48 +00004695 if ( LocaleCompare(arg1,"null:") == 0 )
4696 break;
4697 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4698 }
4699
cristy151b66d2015-04-15 10:50:31 +00004700 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",arg1);
anthony4837ac22012-05-18 23:39:48 +00004701 (void) DeleteImageRegistry(key);
4702 write_images=_images;
4703 if (IfPlusOp)
4704 write_images=CloneImageList(_images,_exception);
4705 write_info=CloneImageInfo(_image_info);
4706 (void) WriteImages(write_info,write_images,arg1,_exception);
4707 write_info=DestroyImageInfo(write_info);
4708 if (IfPlusOp)
4709 write_images=DestroyImageList(write_images);
4710 break;
4711 }
4712 /*
4713 Parenthesis and Brace operations
4714 */
4715 if (LocaleCompare("(",option) == 0) {
4716 /* stack 'push' images */
4717 Stack
4718 *node;
4719
4720 size_t
4721 size;
4722
4723 size=0;
4724 node=cli_wand->image_list_stack;
cristyf432c632014-12-07 15:11:28 +00004725 for ( ; node != (Stack *) NULL; node=node->next)
anthony4837ac22012-05-18 23:39:48 +00004726 size++;
4727 if ( size >= MAX_STACK_DEPTH )
4728 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4729 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4730 if (node == (Stack *) NULL)
4731 CLIWandExceptionBreak(ResourceLimitFatalError,
4732 "MemoryAllocationFailed",option);
4733 node->data = (void *)cli_wand->wand.images;
anthony4837ac22012-05-18 23:39:48 +00004734 node->next = cli_wand->image_list_stack;
4735 cli_wand->image_list_stack = node;
anthonya322a832013-04-27 06:28:03 +00004736 cli_wand->wand.images = NewImageList();
anthony4837ac22012-05-18 23:39:48 +00004737
4738 /* handle respect-parenthesis */
4739 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4740 "respect-parenthesis"))))
4741 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004742 else
anthony4837ac22012-05-18 23:39:48 +00004743 break;
anthonya322a832013-04-27 06:28:03 +00004744 /* fall thru to operation */
anthony52bef752012-03-27 13:54:47 +00004745 }
anthony4837ac22012-05-18 23:39:48 +00004746 if (LocaleCompare("{",option) == 0) {
4747 /* stack 'push' of image_info settings */
4748 Stack
4749 *node;
anthony8226e722012-04-05 14:25:46 +00004750
anthony4837ac22012-05-18 23:39:48 +00004751 size_t
4752 size;
anthony8226e722012-04-05 14:25:46 +00004753
anthony4837ac22012-05-18 23:39:48 +00004754 size=0;
4755 node=cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004756 for ( ; node != (Stack *) NULL; node=node->next)
anthony4837ac22012-05-18 23:39:48 +00004757 size++;
4758 if ( size >= MAX_STACK_DEPTH )
4759 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4760 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4761 if (node == (Stack *) NULL)
4762 CLIWandExceptionBreak(ResourceLimitFatalError,
4763 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004764
anthony4837ac22012-05-18 23:39:48 +00004765 node->data = (void *)cli_wand->wand.image_info;
anthonya322a832013-04-27 06:28:03 +00004766 node->next = cli_wand->image_info_stack;
4767
4768 cli_wand->image_info_stack = node;
anthony4837ac22012-05-18 23:39:48 +00004769 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
cristyf432c632014-12-07 15:11:28 +00004770 if (cli_wand->wand.image_info == (ImageInfo *) NULL) {
anthony4837ac22012-05-18 23:39:48 +00004771 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4772 option);
4773 cli_wand->wand.image_info = (ImageInfo *)node->data;
4774 node = (Stack *)RelinquishMagickMemory(node);
4775 break;
4776 }
4777
anthony4837ac22012-05-18 23:39:48 +00004778 break;
anthony8226e722012-04-05 14:25:46 +00004779 }
anthony4837ac22012-05-18 23:39:48 +00004780 if (LocaleCompare(")",option) == 0) {
4781 /* pop images from stack */
4782 Stack
4783 *node;
anthony8226e722012-04-05 14:25:46 +00004784
anthony4837ac22012-05-18 23:39:48 +00004785 node = (Stack *)cli_wand->image_list_stack;
cristyf432c632014-12-07 15:11:28 +00004786 if ( node == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004787 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4788 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004789
anthony4837ac22012-05-18 23:39:48 +00004790 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4791 cli_wand->wand.images= (Image *)node->data;
4792 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004793
anthony4837ac22012-05-18 23:39:48 +00004794 /* handle respect-parenthesis - of the previous 'pushed' settings */
4795 node = cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004796 if ( node != (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004797 {
4798 if (IfMagickTrue(IsStringTrue(GetImageOption(
4799 cli_wand->wand.image_info,"respect-parenthesis"))))
4800 option="}"; /* fall-thru so as to pop image settings too */
4801 else
4802 break;
4803 }
4804 else
4805 break;
4806 /* fall thru to next if */
4807 }
4808 if (LocaleCompare("}",option) == 0) {
4809 /* pop image_info settings from stack */
4810 Stack
4811 *node;
anthony43f425d2012-02-26 12:58:58 +00004812
anthony4837ac22012-05-18 23:39:48 +00004813 node = (Stack *)cli_wand->image_info_stack;
cristyf432c632014-12-07 15:11:28 +00004814 if ( node == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004815 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4816 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004817
anthony4837ac22012-05-18 23:39:48 +00004818 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004819 cli_wand->wand.image_info = (ImageInfo *)node->data;
4820 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004821
4822 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4823 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4824 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4825
4826 break;
4827 }
anthonya322a832013-04-27 06:28:03 +00004828 if (LocaleCompare("print",option+1) == 0)
4829 {
4830 (void) FormatLocaleFile(stdout,"%s",arg1);
4831 break;
4832 }
anthonyc7994672012-11-17 05:33:27 +00004833 if (LocaleCompare("set",option+1) == 0)
4834 {
anthonya322a832013-04-27 06:28:03 +00004835 /* Settings are applied to each image in memory in turn (if any).
4836 While a option: only need to be applied once globally.
4837
4838 NOTE: rguments have not been automatically percent expaneded
anthonyc7994672012-11-17 05:33:27 +00004839 */
anthonya322a832013-04-27 06:28:03 +00004840
4841 /* escape the 'key' once only, using first image. */
4842 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4843 if (arg1 == (char *) NULL)
4844 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4845 option);
anthonyc7994672012-11-17 05:33:27 +00004846
4847 if (LocaleNCompare(arg1,"registry:",9) == 0)
4848 {
4849 if (IfPlusOp)
4850 {
4851 (void) DeleteImageRegistry(arg1+9);
anthonya322a832013-04-27 06:28:03 +00004852 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004853 break;
4854 }
anthonya322a832013-04-27 06:28:03 +00004855 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4856 if (arg2 == (char *) NULL) {
4857 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004858 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4859 option);
anthonya322a832013-04-27 06:28:03 +00004860 }
4861 (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
4862 arg1=DestroyString((char *)arg1);
4863 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004864 break;
4865 }
4866 if (LocaleNCompare(arg1,"option:",7) == 0)
4867 {
4868 /* delete equivelent artifact from all images (if any) */
cristyf432c632014-12-07 15:11:28 +00004869 if (_images != (Image *) NULL)
anthonya322a832013-04-27 06:28:03 +00004870 {
4871 MagickResetIterator(&cli_wand->wand);
4872 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4873 (void) DeleteImageArtifact(_images,arg1+7);
4874 MagickResetIterator(&cli_wand->wand);
4875 }
anthonyc7994672012-11-17 05:33:27 +00004876 /* now set/delete the global option as needed */
anthonya322a832013-04-27 06:28:03 +00004877 /* FUTURE: make escapes in a global 'option:' delayed */
cristyf432c632014-12-07 15:11:28 +00004878 arg2=(char *) NULL;
anthonya322a832013-04-27 06:28:03 +00004879 if (IfNormalOp)
4880 {
4881 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4882 if (arg2 == (char *) NULL)
4883 CLIWandExceptionBreak(OptionWarning,
4884 "InterpretPropertyFailure",option);
4885 }
4886 (void) SetImageOption(_image_info,arg1+7,arg2);
4887 arg1=DestroyString((char *)arg1);
4888 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004889 break;
4890 }
anthonya322a832013-04-27 06:28:03 +00004891 /* Set Artifacts/Properties/Attributes all images (required) */
4892 if ( _images == (Image *) NULL )
4893 CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
4894
anthonyc7994672012-11-17 05:33:27 +00004895 MagickResetIterator(&cli_wand->wand);
4896 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4897 {
cristyf432c632014-12-07 15:11:28 +00004898 arg2=(char *) NULL;
anthonya322a832013-04-27 06:28:03 +00004899 if (IfNormalOp)
4900 {
4901 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4902 if (arg2 == (char *) NULL)
4903 CLIWandExceptionBreak(OptionWarning,
4904 "InterpretPropertyFailure",option);
4905 }
4906 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4907 (void) SetImageArtifact(_images,arg1+9,arg2);
4908 else if (LocaleNCompare(arg1,"property:",9) == 0)
4909 (void) SetImageProperty(_images,arg1+9,arg2,_exception);
4910 else
4911 (void) SetImageProperty(_images,arg1,arg2,_exception);
4912 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004913 }
4914 MagickResetIterator(&cli_wand->wand);
anthonya322a832013-04-27 06:28:03 +00004915 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004916 break;
4917 }
anthony4837ac22012-05-18 23:39:48 +00004918 if (LocaleCompare("clone",option+1) == 0) {
4919 Image
4920 *new_images;
4921
4922 if (*option == '+')
cristy3677cc72014-11-14 23:22:55 +00004923 arg1=AcquireString("-1");
anthony4837ac22012-05-18 23:39:48 +00004924 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4925 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
cristyf432c632014-12-07 15:11:28 +00004926 if ( cli_wand->image_list_stack == (Stack *) NULL)
anthony4837ac22012-05-18 23:39:48 +00004927 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4928 new_images = (Image *)cli_wand->image_list_stack->data;
4929 if (new_images == (Image *) NULL)
4930 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4931 new_images=CloneImages(new_images,arg1,_exception);
4932 if (new_images == (Image *) NULL)
4933 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4934 AppendImageToList(&_images,new_images);
4935 break;
4936 }
4937 /*
cristy422d5502012-12-22 22:20:57 +00004938 Informational Operations.
anthony4837ac22012-05-18 23:39:48 +00004939
anthonyc7994672012-11-17 05:33:27 +00004940 Note that these do not require either a cli-wand or images!
4941 Though currently a cli-wand much be provided regardless.
anthony4837ac22012-05-18 23:39:48 +00004942 */
cristy422d5502012-12-22 22:20:57 +00004943 if (LocaleCompare("version",option+1) == 0)
4944 {
cristy4f7a6132012-12-23 00:35:19 +00004945 ListMagickVersion(stdout);
cristy422d5502012-12-22 22:20:57 +00004946 break;
4947 }
anthony4837ac22012-05-18 23:39:48 +00004948 if (LocaleCompare("list",option+1) == 0) {
4949 /*
anthonyc7994672012-11-17 05:33:27 +00004950 FUTURE: This 'switch' should really be part of MagickCore
anthony4837ac22012-05-18 23:39:48 +00004951 */
4952 ssize_t
4953 list;
4954
4955 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4956 if ( list < 0 ) {
4957 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4958 break;
4959 }
4960 switch (list)
4961 {
4962 case MagickCoderOptions:
4963 {
4964 (void) ListCoderInfo((FILE *) NULL,_exception);
4965 break;
4966 }
4967 case MagickColorOptions:
4968 {
4969 (void) ListColorInfo((FILE *) NULL,_exception);
4970 break;
4971 }
4972 case MagickConfigureOptions:
4973 {
4974 (void) ListConfigureInfo((FILE *) NULL,_exception);
4975 break;
4976 }
4977 case MagickDelegateOptions:
4978 {
4979 (void) ListDelegateInfo((FILE *) NULL,_exception);
4980 break;
4981 }
4982 case MagickFontOptions:
4983 {
4984 (void) ListTypeInfo((FILE *) NULL,_exception);
4985 break;
4986 }
4987 case MagickFormatOptions:
4988 (void) ListMagickInfo((FILE *) NULL,_exception);
4989 break;
4990 case MagickLocaleOptions:
4991 (void) ListLocaleInfo((FILE *) NULL,_exception);
4992 break;
4993 case MagickLogOptions:
4994 (void) ListLogInfo((FILE *) NULL,_exception);
4995 break;
4996 case MagickMagicOptions:
4997 (void) ListMagicInfo((FILE *) NULL,_exception);
4998 break;
4999 case MagickMimeOptions:
5000 (void) ListMimeInfo((FILE *) NULL,_exception);
5001 break;
5002 case MagickModuleOptions:
5003 (void) ListModuleInfo((FILE *) NULL,_exception);
5004 break;
5005 case MagickPolicyOptions:
5006 (void) ListPolicyInfo((FILE *) NULL,_exception);
5007 break;
5008 case MagickResourceOptions:
5009 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
5010 break;
5011 case MagickThresholdOptions:
5012 (void) ListThresholdMaps((FILE *) NULL,_exception);
5013 break;
5014 default:
5015 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
5016 _exception);
5017 break;
5018 }
5019 break;
anthony43f425d2012-02-26 12:58:58 +00005020 }
anthony8226e722012-04-05 14:25:46 +00005021
anthony4837ac22012-05-18 23:39:48 +00005022 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony8226e722012-04-05 14:25:46 +00005023
dirk93b02b72013-11-16 16:03:36 +00005024DisableMSCWarning(4127)
anthony4837ac22012-05-18 23:39:48 +00005025 } while (0); /* break to exit code. */
dirk93b02b72013-11-16 16:03:36 +00005026RestoreMSCWarning
anthony43f425d2012-02-26 12:58:58 +00005027
anthony4837ac22012-05-18 23:39:48 +00005028 /* clean up percent escape interpreted strings */
5029 if (arg1 != arg1n )
5030 arg1=DestroyString((char *)arg1);
5031 if (arg2 != arg2n )
5032 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00005033
anthony8226e722012-04-05 14:25:46 +00005034#undef _image_info
5035#undef _images
anthony92c93bd2012-03-19 14:02:47 +00005036#undef _exception
anthony8226e722012-04-05 14:25:46 +00005037#undef IfNormalOp
5038#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00005039}
anthony464f1c42012-04-22 08:51:01 +00005040
5041/*
5042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5043% %
5044% %
5045% %
anthony964d28e2012-05-17 23:39:46 +00005046+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00005047% %
5048% %
5049% %
5050%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5051%
5052% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00005053% The option arguments can be variable in number, though at this time no more
5054% that two is actually used by any option (this may change). Excess options
5055% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00005056%
5057% If the cli_wand->command pointer is non-null, then it is assumed that the
5058% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00005059% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
5060% routine will do the lookup instead. The pointer is reset afterward.
5061%
5062% This action allows the caller to lookup and pre-handle any 'special'
5063% options, (such as implicit reads) before calling this general option
5064% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00005065%
5066% The format of the CLIOption method is:
5067%
5068% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
5069%
5070% A description of each parameter follows:
5071%
5072% o cli_wand: the main CLI Wand to use.
5073%
5074% o option: The special option (with any switch char) to process
5075%
anthony964d28e2012-05-17 23:39:46 +00005076% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00005077%
5078% Example Usage...
5079%
5080% CLIoption(cli_wand,"-read","rose:");
5081% CLIoption(cli_wand,"-virtual-pixel","transparent");
5082% CLIoption(cli_wand,"-distort","SRT:","30");
5083% CLIoption(cli_wand,"-write","rotated_rose.png");
5084%
5085*/
5086WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
5087{
anthonya322a832013-04-27 06:28:03 +00005088 const char /* extracted option args from args */
anthony464f1c42012-04-22 08:51:01 +00005089 *arg1,
5090 *arg2;
5091
5092 CommandOptionFlags
5093 option_type;
5094
5095 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +00005096 assert(cli_wand->signature == MagickWandSignature);
5097 assert(cli_wand->wand.signature == MagickWandSignature);
anthony464f1c42012-04-22 08:51:01 +00005098
anthony964d28e2012-05-17 23:39:46 +00005099 do { /* Break Code Block for error handling */
5100
5101 /* get information about option */
5102 if ( cli_wand->command == (const OptionInfo *) NULL )
5103 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00005104#if 0
anthony964d28e2012-05-17 23:39:46 +00005105 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
5106 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00005107#endif
anthony964d28e2012-05-17 23:39:46 +00005108 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00005109
anthony964d28e2012-05-17 23:39:46 +00005110 if ( option_type == UndefinedOptionFlag )
5111 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00005112
anthony964d28e2012-05-17 23:39:46 +00005113 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00005114
dirkab5c7452014-10-11 19:14:52 +00005115 /* deprecated options */
anthony964d28e2012-05-17 23:39:46 +00005116 if ( (option_type & DeprecateOptionFlag) != 0 )
5117 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00005118
anthony964d28e2012-05-17 23:39:46 +00005119 /* options that this module does not handle */
5120 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
5121 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00005122
anthony964d28e2012-05-17 23:39:46 +00005123 /* Get argument strings from VarArgs
anthonya322a832013-04-27 06:28:03 +00005124 How can you determine if enough arguments was supplied?
5125 What happens if not enough arguments were supplied?
5126 */
anthony964d28e2012-05-17 23:39:46 +00005127 { size_t
cristy52b632a2014-11-08 00:31:34 +00005128 count = (size_t) cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00005129
anthony964d28e2012-05-17 23:39:46 +00005130 va_list
5131 operands;
anthony464f1c42012-04-22 08:51:01 +00005132
anthony964d28e2012-05-17 23:39:46 +00005133 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00005134
anthony964d28e2012-05-17 23:39:46 +00005135 arg1=arg2=NULL;
5136 if ( count >= 1 )
5137 arg1=(const char *) va_arg(operands, const char *);
5138 if ( count >= 2 )
5139 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00005140
anthony964d28e2012-05-17 23:39:46 +00005141 va_end(operands);
anthony52cb3df2012-04-24 03:29:32 +00005142#if 0
anthony964d28e2012-05-17 23:39:46 +00005143 (void) FormatLocaleFile(stderr,
5144 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
5145 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00005146#endif
anthony964d28e2012-05-17 23:39:46 +00005147 }
5148
5149 /*
5150 Call the appropriate option handler
5151 */
5152
5153 /* FUTURE: this is temporary - get 'settings' to handle distribution of
5154 settings to images attributes,proprieties,artifacts */
cristyf432c632014-12-07 15:11:28 +00005155 if ( cli_wand->wand.images != (Image *) NULL )
cristy52b632a2014-11-08 00:31:34 +00005156 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
5157 cli_wand->wand.exception);
anthony964d28e2012-05-17 23:39:46 +00005158
5159 if ( (option_type & SettingOptionFlags) != 0 ) {
5160 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
5161 // FUTURE: Sync Specific Settings into Image Properities (not global)
5162 }
5163
5164 /* Operators that do not need images - read, write, stack, clone */
cristye1f6cfe2015-06-27 15:50:30 +00005165 if ((option_type & NoImageOperatorFlag) != 0)
anthony964d28e2012-05-17 23:39:46 +00005166 CLINoImageOperator(cli_wand, option, arg1, arg2);
5167
5168 /* FUTURE: The not a setting part below is a temporary hack due to
5169 * some options being both a Setting and a Simple operator.
5170 * Specifically -monitor, -depth, and -colorspace */
cristyf432c632014-12-07 15:11:28 +00005171 if ( cli_wand->wand.images == (Image *) NULL )
anthony964d28e2012-05-17 23:39:46 +00005172 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
5173 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
5174 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
5175
anthonya322a832013-04-27 06:28:03 +00005176 /* Operators which loop of individual images, simply */
5177 if ( (option_type & SimpleOperatorFlag) != 0 &&
cristyf432c632014-12-07 15:11:28 +00005178 cli_wand->wand.images != (Image *) NULL) /* temp hack */
cristy2c57b742014-10-31 00:40:34 +00005179 {
5180 ExceptionInfo *exception=AcquireExceptionInfo();
cristy52b632a2014-11-08 00:31:34 +00005181 (void) CLISimpleOperatorImages(cli_wand, option, arg1, arg2,exception);
cristy2c57b742014-10-31 00:40:34 +00005182 exception=DestroyExceptionInfo(exception);
5183 }
anthony964d28e2012-05-17 23:39:46 +00005184
5185 /* Operators that work on the image list as a whole */
5186 if ( (option_type & ListOperatorFlag) != 0 )
cristy52b632a2014-11-08 00:31:34 +00005187 (void) CLIListOperatorImages(cli_wand, option, arg1, arg2);
anthony964d28e2012-05-17 23:39:46 +00005188
dirk93b02b72013-11-16 16:03:36 +00005189DisableMSCWarning(4127)
anthony964d28e2012-05-17 23:39:46 +00005190 } while (0); /* end Break code block */
dirk93b02b72013-11-16 16:03:36 +00005191RestoreMSCWarning
anthony464f1c42012-04-22 08:51:01 +00005192
5193 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00005194}