blob: 0254708cb407cd349451d9ce78da71e55719e1ed [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% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 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"
anthony43f425d2012-02-26 12:58:58 +000053#include "MagickWand/wand.h"
anthony756cd0d2012-04-08 12:41:44 +000054#include "MagickWand/wandcli.h"
55#include "MagickWand/wandcli-private.h"
56#include "MagickWand/operation.h"
anthony805a2d42011-09-25 08:25:12 +000057#include "MagickCore/monitor-private.h"
58#include "MagickCore/thread-private.h"
59#include "MagickCore/string-private.h"
60
61/*
62 Define declarations.
63*/
anthonyafa3dfc2012-03-03 11:31:30 +000064#define USE_WAND_METHODS 0
65#define MAX_STACK_DEPTH 32
66#define UNDEFINED_COMPRESSION_QUALITY 0UL
67
anthonyb1d483a2012-04-14 12:53:56 +000068/* FUTURE: why is this default so specific? */
69#define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
70
anthony805a2d42011-09-25 08:25:12 +000071/*
72 Constant declaration. (temporary exports)
73*/
74static const char
75 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000076 BorderColor[] = "#dfdfdf", /* sRGB gray */
77 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony22de2722012-04-19 14:43:00 +000078
79/* For Debugging Geometry Input */
80#define ReportGeometry(flags,info) \
81 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
82 flags, info.rho, info.sigma, info.xi, info.psi )
anthony805a2d42011-09-25 08:25:12 +000083
84/*
85** Function to report on the progress of image operations
86*/
87static MagickBooleanType MonitorProgress(const char *text,
88 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000089 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000090{
91 char
92 message[MaxTextExtent],
93 tag[MaxTextExtent];
94
95 const char
96 *locale_message;
97
98 register char
99 *p;
100
101 if (extent < 2)
102 return(MagickTrue);
103 (void) CopyMagickMemory(tag,text,MaxTextExtent);
104 p=strrchr(tag,'/');
105 if (p != (char *) NULL)
106 *p='\0';
107 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
108 locale_message=GetLocaleMessage(message);
109 if (locale_message == message)
110 locale_message=tag;
111 if (p == (char *) NULL)
112 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
113 locale_message,(long) offset,(unsigned long) extent,(long)
114 (100L*offset/(extent-1)));
115 else
116 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
117 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
118 (100L*offset/(extent-1)));
119 if (offset == (MagickOffsetType) (extent-1))
120 (void) FormatLocaleFile(stderr,"\n");
121 (void) fflush(stderr);
122 return(MagickTrue);
123}
124
125/*
126** GetImageCache() will read an image into a image cache if not already
127** present then return the image that is in the cache under that filename.
128*/
129static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
130 ExceptionInfo *exception)
131{
132 char
133 key[MaxTextExtent];
134
135 ExceptionInfo
136 *sans_exception;
137
138 Image
139 *image;
140
141 ImageInfo
142 *read_info;
143
144 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
145 sans_exception=AcquireExceptionInfo();
146 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
147 sans_exception=DestroyExceptionInfo(sans_exception);
148 if (image != (Image *) NULL)
149 return(image);
150 read_info=CloneImageInfo(image_info);
151 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
152 image=ReadImage(read_info,exception);
153 read_info=DestroyImageInfo(read_info);
154 if (image != (Image *) NULL)
155 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
156 return(image);
157}
158
anthony756cd0d2012-04-08 12:41:44 +0000159/*
anthonya89dd172011-10-04 13:29:35 +0000160 SparseColorOption() parse the complex -sparse-color argument into an
161 an array of floating point values than call SparseColorImage().
162 Argument is a complex mix of floating-point pixel coodinates, and color
163 specifications (or direct floating point numbers). The number of floats
164 needed to represent a color varies depending on teh current channel
165 setting.
anthony43f425d2012-02-26 12:58:58 +0000166
167 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000168*/
169static Image *SparseColorOption(const Image *image,
170 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000171 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000172{
173 char
174 token[MaxTextExtent];
175
176 const char
177 *p;
178
179 double
180 *sparse_arguments;
181
182 Image
183 *sparse_image;
184
185 PixelInfo
186 color;
187
188 MagickBooleanType
189 error;
190
191 register size_t
192 x;
193
194 size_t
195 number_arguments,
196 number_colors;
197
198 assert(image != (Image *) NULL);
199 assert(image->signature == MagickSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000200 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000201 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
202 assert(exception != (ExceptionInfo *) NULL);
203 assert(exception->signature == MagickSignature);
204 /*
anthonyb1d483a2012-04-14 12:53:56 +0000205 Limit channels according to image
206 add up number of values needed per color.
anthony805a2d42011-09-25 08:25:12 +0000207 */
208 number_colors=0;
209 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
210 number_colors++;
211 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
212 number_colors++;
213 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
214 number_colors++;
215 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
216 (image->colorspace == CMYKColorspace))
217 number_colors++;
218 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000219 IfMagickTrue(image->matte))
anthony805a2d42011-09-25 08:25:12 +0000220 number_colors++;
221
222 /*
223 Read string, to determine number of arguments needed,
224 */
225 p=arguments;
226 x=0;
227 while( *p != '\0' )
228 {
229 GetMagickToken(p,&p,token);
230 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000231 if ( isalpha((int) token[0]) || token[0] == '#' )
232 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000233 else
anthony805a2d42011-09-25 08:25:12 +0000234 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000235 }
anthony31f1bf72012-01-30 12:37:22 +0000236 /* control points and color values */
anthony7bcfe7f2012-03-30 14:01:22 +0000237 error = IsMagickTrue( x % (2+number_colors) );
anthony31f1bf72012-01-30 12:37:22 +0000238 number_arguments=x;
anthony7bcfe7f2012-03-30 14:01:22 +0000239 if ( IfMagickTrue(error) ) {
anthony805a2d42011-09-25 08:25:12 +0000240 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000241 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000242 "Invalid number of Arguments");
243 return( (Image *)NULL);
244 }
245
246 /* Allocate and fill in the floating point arguments */
247 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
248 sizeof(*sparse_arguments));
249 if (sparse_arguments == (double *) NULL) {
250 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
251 "MemoryAllocationFailed","%s","SparseColorOption");
252 return( (Image *)NULL);
253 }
254 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
255 sizeof(*sparse_arguments));
256 p=arguments;
257 x=0;
258 while( *p != '\0' && x < number_arguments ) {
259 /* X coordinate */
260 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
261 if ( token[0] == '\0' ) break;
262 if ( isalpha((int) token[0]) || token[0] == '#' ) {
263 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000264 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000265 "Color found, instead of X-coord");
266 error = MagickTrue;
267 break;
268 }
cristydbdd0e32011-11-04 23:29:40 +0000269 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000270 /* Y coordinate */
271 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
272 if ( token[0] == '\0' ) break;
273 if ( isalpha((int) token[0]) || token[0] == '#' ) {
274 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000275 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000276 "Color found, instead of Y-coord");
277 error = MagickTrue;
278 break;
279 }
cristydbdd0e32011-11-04 23:29:40 +0000280 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000281 /* color name or function given in string argument */
282 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
283 if ( token[0] == '\0' ) break;
284 if ( isalpha((int) token[0]) || token[0] == '#' ) {
285 /* Color string given */
286 (void) QueryColorCompliance(token,AllCompliance,&color,
287 exception);
288 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
289 sparse_arguments[x++] = QuantumScale*color.red;
290 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
291 sparse_arguments[x++] = QuantumScale*color.green;
292 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
293 sparse_arguments[x++] = QuantumScale*color.blue;
294 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
295 (image->colorspace == CMYKColorspace))
296 sparse_arguments[x++] = QuantumScale*color.black;
297 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000298 IfMagickTrue(image->matte))
anthony31f1bf72012-01-30 12:37:22 +0000299 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000300 }
anthony31f1bf72012-01-30 12:37:22 +0000301 else {
302 /* Colors given as a set of floating point values - experimental */
303 /* NB: token contains the first floating point value to use! */
304 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
305 {
306 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
307 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
308 break;
309 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
310 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000311 }
anthony31f1bf72012-01-30 12:37:22 +0000312 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
313 {
314 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
316 break;
317 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
318 token[0] = ','; /* used this token - get another */
319 }
320 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
321 {
322 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324 break;
325 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
326 token[0] = ','; /* used this token - get another */
327 }
328 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
329 (image->colorspace == CMYKColorspace))
330 {
331 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
333 break;
334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
335 token[0] = ','; /* used this token - get another */
336 }
337 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000338 IfMagickTrue(image->matte))
anthony31f1bf72012-01-30 12:37:22 +0000339 {
340 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
341 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
342 break;
343 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
344 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000345 }
346 }
347 }
348 if ( number_arguments != x && !error ) {
349 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000350 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000351 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
352 return( (Image *)NULL);
353 }
354 if ( error )
355 return( (Image *)NULL);
356
anthony31f1bf72012-01-30 12:37:22 +0000357 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000358 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
359 exception);
360 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
361 return( sparse_image );
362}
363
364/*
365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366% %
367% %
368% %
anthony464f1c42012-04-22 08:51:01 +0000369% 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 +0000370% %
371% %
372% %
373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374%
375% CLISettingOptionInfo() applies a single settings option into a CLI wand
376% holding the image_info, draw_info, quantize_info structures that will be
377% used when processing the images.
378%
379% These options do no require images to be present in the CLI wand for them
380% to be able to be set, in which case they will generally be applied to image
381% that are read in later
anthony80c37752012-01-16 01:03:11 +0000382%
383% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000384% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000385%
anthony2052d272012-02-28 12:48:29 +0000386% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000387%
anthonyafa3dfc2012-03-03 11:31:30 +0000388% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000389% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000390%
391% A description of each parameter follows:
392%
anthony43f425d2012-02-26 12:58:58 +0000393% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000394%
anthonydcf510d2011-10-30 13:51:40 +0000395% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000396%
anthonye5fcd362012-04-09 04:02:09 +0000397% o arg1, arg2: optional argument strings to the operation
398% arg2 is currently only used by "-limit"
anthonydcf510d2011-10-30 13:51:40 +0000399%
anthony805a2d42011-09-25 08:25:12 +0000400*/
anthonyafa3dfc2012-03-03 11:31:30 +0000401WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000402 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000403{
anthony30b912a2012-03-22 01:20:28 +0000404 ssize_t
405 parse; /* option argument parsing (string to value table lookup) */
406
anthony43f425d2012-02-26 12:58:58 +0000407 assert(cli_wand != (MagickCLI *) NULL);
408 assert(cli_wand->signature == WandSignature);
409 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000410 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +0000411 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000412
anthony2e4501b2012-03-30 04:41:54 +0000413#define _image_info (cli_wand->wand.image_info)
414#define _exception (cli_wand->wand.exception)
415#define _draw_info (cli_wand->draw_info)
416#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000417#define IfSetOption (*option=='-')
anthony7bcfe7f2012-03-30 14:01:22 +0000418#define ArgBoolean IsMagickTrue(IfSetOption)
419#define ArgBooleanNot IsMagickFalse(IfSetOption)
anthony24aa8822012-03-11 00:56:06 +0000420#define ArgBooleanString (IfSetOption?"true":"false")
421#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000422
anthonyafa3dfc2012-03-03 11:31:30 +0000423 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000424 {
425 case 'a':
426 {
anthonyafa3dfc2012-03-03 11:31:30 +0000427 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000428 {
anthony92c93bd2012-03-19 14:02:47 +0000429 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000430 break;
431 }
anthonyafa3dfc2012-03-03 11:31:30 +0000432 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000433 {
anthony464f1c42012-04-22 08:51:01 +0000434 CLIWandWarnReplaced("-draw 'affine ...'");
anthony74b1cfc2011-10-06 12:44:16 +0000435 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000436 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000437 else
anthony92c93bd2012-03-19 14:02:47 +0000438 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000439 break;
440 }
anthonyafa3dfc2012-03-03 11:31:30 +0000441 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000442 {
anthony92c93bd2012-03-19 14:02:47 +0000443 _image_info->antialias =
444 _draw_info->stroke_antialias =
445 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000446 break;
447 }
anthony31f1bf72012-01-30 12:37:22 +0000448 if (LocaleCompare("attenuate",option+1) == 0)
449 {
anthony7bcfe7f2012-03-30 14:01:22 +0000450 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000451 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
452 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000453 break;
454 }
anthonyafa3dfc2012-03-03 11:31:30 +0000455 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000456 {
anthony92c93bd2012-03-19 14:02:47 +0000457 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000458 break;
459 }
anthonyebb73a22012-03-22 14:25:52 +0000460 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000461 }
462 case 'b':
463 {
anthonyafa3dfc2012-03-03 11:31:30 +0000464 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000465 {
anthony92c93bd2012-03-19 14:02:47 +0000466 /* FUTURE: both _image_info attribute & ImageOption in use!
467 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000468 SyncImageSettings() used to set per-image attribute.
469
anthony92c93bd2012-03-19 14:02:47 +0000470 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000471 we should fall back to per-image background_color
472
473 At this time -background will 'wipe out' the per-image
474 background color!
475
476 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000477 */
anthony92c93bd2012-03-19 14:02:47 +0000478 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000479 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000480 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000481 break;
482 }
anthonyafa3dfc2012-03-03 11:31:30 +0000483 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000484 {
anthony52bef752012-03-27 13:54:47 +0000485 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000486 as it is actually rarely used except in direct convolve operations
487 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000488
489 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000490 */
anthony7bcfe7f2012-03-30 14:01:22 +0000491 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000492 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000493 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000494 break;
495 }
anthonyafa3dfc2012-03-03 11:31:30 +0000496 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000497 {
anthony72feaa62012-01-17 06:46:23 +0000498 /* Used as a image chromaticity setting
499 SyncImageSettings() used to set per-image attribute.
500 */
anthony92c93bd2012-03-19 14:02:47 +0000501 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000502 break;
503 }
anthonyafa3dfc2012-03-03 11:31:30 +0000504 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000505 {
anthonyafbaed72011-10-26 12:05:04 +0000506 /* Image chromaticity X,Y NB: Y=X if Y not defined
507 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000508 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000509 */
anthonyf42014d2012-03-25 09:53:06 +0000510 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000511 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000512 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000513 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000514 break;
515 }
anthonyafa3dfc2012-03-03 11:31:30 +0000516 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000517 {
anthony92c93bd2012-03-19 14:02:47 +0000518 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000519 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000520 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000521 */
anthony74b1cfc2011-10-06 12:44:16 +0000522 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000523 {
anthony92c93bd2012-03-19 14:02:47 +0000524 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000525 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000526 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000527 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000528 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000529 break;
530 }
anthony92c93bd2012-03-19 14:02:47 +0000531 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000532 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000533 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000534 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000535 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000536 break;
537 }
anthonyafa3dfc2012-03-03 11:31:30 +0000538 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000539 {
anthony464f1c42012-04-22 08:51:01 +0000540 CLIWandWarnReplaced("-undercolor");
anthony975a8d72012-04-12 13:54:36 +0000541 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
anthonyfd706f92012-01-19 04:22:02 +0000542 break;
anthony805a2d42011-09-25 08:25:12 +0000543 }
anthonyebb73a22012-03-22 14:25:52 +0000544 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000545 }
546 case 'c':
547 {
anthonyafa3dfc2012-03-03 11:31:30 +0000548 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000549 {
550 MagickSizeType
551 limit;
552
anthony7bcfe7f2012-03-30 14:01:22 +0000553 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000554 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000555 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000556 if (LocaleCompare("unlimited",arg1) != 0)
557 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000558 (void) SetMagickResourceLimit(MemoryResource,limit);
559 (void) SetMagickResourceLimit(MapResource,2*limit);
560 break;
561 }
anthonyafa3dfc2012-03-03 11:31:30 +0000562 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000563 {
anthony92c93bd2012-03-19 14:02:47 +0000564 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000565 break;
566 }
anthonyafa3dfc2012-03-03 11:31:30 +0000567 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000568 {
anthony30b912a2012-03-22 01:20:28 +0000569 arg1=ArgOption("default");
570 parse=ParseChannelOption(arg1);
571 if (parse < 0)
572 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
573 option,arg1);
574 _image_info->channel=(ChannelType) parse;
575 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000576 break;
577 }
anthonyafa3dfc2012-03-03 11:31:30 +0000578 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000579 {
anthonyafbaed72011-10-26 12:05:04 +0000580 /* Setting used for new images via AquireImage()
581 But also used as a SimpleImageOperator
582 Undefined colorspace means don't modify images on
583 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000584 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
585 ArgOption("undefined"));
586 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000587 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
588 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000589 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000590 break;
591 }
anthonyafa3dfc2012-03-03 11:31:30 +0000592 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000593 {
anthony92c93bd2012-03-19 14:02:47 +0000594 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000595 break;
596 }
anthonyafa3dfc2012-03-03 11:31:30 +0000597 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000598 {
anthony92c93bd2012-03-19 14:02:47 +0000599 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000600 SyncImageSettings() used to set per-image attribute. - REMOVE
601
anthonyafbaed72011-10-26 12:05:04 +0000602 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000603 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000604 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000605 */
anthonyebb73a22012-03-22 14:25:52 +0000606 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
607 ArgOption("undefined"));
608 if (parse < 0)
609 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
610 option,arg1);
611 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000612 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000613 break;
614 }
anthonyafa3dfc2012-03-03 11:31:30 +0000615 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000616 {
anthony92c93bd2012-03-19 14:02:47 +0000617 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000618 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000619 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000620
anthony92c93bd2012-03-19 14:02:47 +0000621 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000622 however the image attribute (for save) is set from the
623 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000624
625 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000626 */
anthonyebb73a22012-03-22 14:25:52 +0000627 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
628 ArgOption("undefined"));
629 if (parse < 0)
630 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
631 option,arg1);
632 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000633 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000634 break;
635 }
anthonyebb73a22012-03-22 14:25:52 +0000636 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000637 }
638 case 'd':
639 {
anthonyafa3dfc2012-03-03 11:31:30 +0000640 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000641 {
anthony72feaa62012-01-17 06:46:23 +0000642 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000643 arg1=ArgOption("none");
644 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
645 if (parse < 0)
646 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
647 option,arg1);
648 (void) SetLogEventMask(arg1);
649 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000650 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000651 break;
652 }
anthonyafa3dfc2012-03-03 11:31:30 +0000653 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000654 {
anthony24aa8822012-03-11 00:56:06 +0000655 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000656 {
anthony5f867ae2011-10-09 10:28:34 +0000657 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000658 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000659 else
anthony24aa8822012-03-11 00:56:06 +0000660 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000661 break;
662 }
anthony24aa8822012-03-11 00:56:06 +0000663 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000664 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000665 (void) DefineImageOption(_image_info,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +0000666 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000667 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000668 break;
669 }
anthonyafa3dfc2012-03-03 11:31:30 +0000670 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000671 {
anthonyafbaed72011-10-26 12:05:04 +0000672 /* Only used for new images via AcquireImage()
673 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000674 */
anthonyebb73a22012-03-22 14:25:52 +0000675 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000676 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000677 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
678 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000679 break;
680 }
anthonyafa3dfc2012-03-03 11:31:30 +0000681 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000682 {
anthony92c93bd2012-03-19 14:02:47 +0000683 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000684 Basically as density can be in a XxY form!
685
686 SyncImageSettings() used to set per-image attribute.
687 */
anthony7bcfe7f2012-03-30 14:01:22 +0000688 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000689 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000690 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
691 (void) CloneString(&_image_info->density,ArgOption(NULL));
692 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000693 break;
694 }
anthonyafa3dfc2012-03-03 11:31:30 +0000695 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000696 {
anthony72feaa62012-01-17 06:46:23 +0000697 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
698 SyncImageSettings() used to set per-image attribute.
699 */
anthony7bcfe7f2012-03-30 14:01:22 +0000700 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000701 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000702 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000703 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000704 break;
705 }
anthonyafa3dfc2012-03-03 11:31:30 +0000706 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000707 {
anthony92c93bd2012-03-19 14:02:47 +0000708 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000709 arg1=ArgOption("undefined");
710 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
711 if (parse < 0)
712 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
713 option,arg1);
714 _draw_info->direction=(DirectionType) parse;
715 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000716 break;
717 }
anthonyafa3dfc2012-03-03 11:31:30 +0000718 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000719 {
anthony92c93bd2012-03-19 14:02:47 +0000720 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
721 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000722 break;
723 }
anthonyafa3dfc2012-03-03 11:31:30 +0000724 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000725 {
anthony72feaa62012-01-17 06:46:23 +0000726 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000727 arg1=ArgOption("undefined");
728 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
729 if (parse < 0)
730 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
731 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000732 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000733 break;
734 }
anthonyb1d483a2012-04-14 12:53:56 +0000735 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
736 {
737 /* FUTURE: this is only used by CompareImages() which is used
738 only by the "compare" CLI program at this time. */
739 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
740 if (IfMagickFalse(IsGeometry(arg1)))
741 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
742 (void) SetImageOption(_image_info,option+1,arg1);
743 break;
744 }
anthonyafa3dfc2012-03-03 11:31:30 +0000745 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000746 {
anthony92c93bd2012-03-19 14:02:47 +0000747 /* _image_info attr (on/off), _quantize_info attr (on/off)
748 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000749 FUTURE: merge the duality of the dithering options
750 */
anthony92c93bd2012-03-19 14:02:47 +0000751 _image_info->dither = _quantize_info->dither = ArgBoolean;
752 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
753 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000754 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000755 if (_quantize_info->dither_method == NoDitherMethod)
756 _image_info->dither = _quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000757 break;
758 }
anthonyebb73a22012-03-22 14:25:52 +0000759 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000760 }
761 case 'e':
762 {
anthonyafa3dfc2012-03-03 11:31:30 +0000763 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000764 {
anthony92c93bd2012-03-19 14:02:47 +0000765 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
766 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000767 break;
768 }
anthonyafa3dfc2012-03-03 11:31:30 +0000769 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000770 {
anthony92c93bd2012-03-19 14:02:47 +0000771 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000772 arg1 = ArgOption("undefined");
773 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
774 if (parse < 0)
775 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
776 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000777 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000778 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000779 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000780 break;
781 }
anthonyafa3dfc2012-03-03 11:31:30 +0000782 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000783 {
anthony92c93bd2012-03-19 14:02:47 +0000784 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000785 break;
786 }
anthonyebb73a22012-03-22 14:25:52 +0000787 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000788 }
789 case 'f':
790 {
anthonyafa3dfc2012-03-03 11:31:30 +0000791 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000792 {
anthony92c93bd2012-03-19 14:02:47 +0000793 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000794 break;
795 }
anthonyafa3dfc2012-03-03 11:31:30 +0000796 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000797 {
anthony92c93bd2012-03-19 14:02:47 +0000798 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000799 The original fill color is preserved if a fill-pattern is given.
800 That way it does not effect other operations that directly using
801 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000802 */
anthony72feaa62012-01-17 06:46:23 +0000803 MagickBooleanType
804 status;
anthony6dc09cd2011-10-12 08:56:49 +0000805
806 ExceptionInfo
807 *sans;
808
anthonyfd706f92012-01-19 04:22:02 +0000809 PixelInfo
810 color;
811
anthony2a0ec8c2012-03-24 04:35:56 +0000812 arg1 = ArgOption("none"); /* +fill turns it off! */
813 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000814 if (_draw_info->fill_pattern != (Image *) NULL)
815 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000816
817 /* is it a color or a image? -- ignore exceptions */
818 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +0000819 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000820 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000821
anthony7bcfe7f2012-03-30 14:01:22 +0000822 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +0000823 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000824 else
anthony92c93bd2012-03-19 14:02:47 +0000825 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000826 break;
827 }
anthonyafa3dfc2012-03-03 11:31:30 +0000828 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000829 {
anthony72feaa62012-01-17 06:46:23 +0000830 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +0000831 arg1 = ArgOption("undefined");
832 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
833 if (parse < 0)
834 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
835 option,arg1);
836 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000837 break;
838 }
anthonyafa3dfc2012-03-03 11:31:30 +0000839 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000840 {
anthony92c93bd2012-03-19 14:02:47 +0000841 (void) CloneString(&_draw_info->font,ArgOption(NULL));
842 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000843 break;
844 }
anthonyafa3dfc2012-03-03 11:31:30 +0000845 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000846 {
anthonydcf510d2011-10-30 13:51:40 +0000847 /* FUTURE: why the ping test, you could set ping after this! */
848 /*
anthony805a2d42011-09-25 08:25:12 +0000849 register const char
850 *q;
851
anthony24aa8822012-03-11 00:56:06 +0000852 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000853 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000854 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000855 */
anthony92c93bd2012-03-19 14:02:47 +0000856 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000857 break;
858 }
anthonyafa3dfc2012-03-03 11:31:30 +0000859 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000860 {
anthony72feaa62012-01-17 06:46:23 +0000861 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000862 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000863 SyncImageSettings() used to set per-image attribute.
864
anthony2a0ec8c2012-03-24 04:35:56 +0000865 FUTURE: Can't find anything else using _image_info->fuzz directly!
866 remove direct sttribute from image_info
anthony6613bf32011-10-15 07:24:44 +0000867 */
anthony2a0ec8c2012-03-24 04:35:56 +0000868 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000869 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +0000870 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
871 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +0000872 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +0000873 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000874 break;
875 }
anthonyebb73a22012-03-22 14:25:52 +0000876 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000877 }
878 case 'g':
879 {
anthonyafa3dfc2012-03-03 11:31:30 +0000880 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000881 {
anthony72feaa62012-01-17 06:46:23 +0000882 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000883 arg1 = ArgOption("none");
884 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
885 if (parse < 0)
886 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
887 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +0000888 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +0000889 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000890 break;
891 }
anthonyafa3dfc2012-03-03 11:31:30 +0000892 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000893 {
anthonydcf510d2011-10-30 13:51:40 +0000894 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000895 SyncImageSettings() used to set per-image attribute.
896 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000897 */
anthonyf42014d2012-03-25 09:53:06 +0000898 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000899 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000900 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000901 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000902 break;
903 }
anthonyebb73a22012-03-22 14:25:52 +0000904 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000905 }
anthonyb1d483a2012-04-14 12:53:56 +0000906 case 'h':
907 {
908 if (LocaleCompare("highlight-color",option+1) == 0)
909 {
910 /* FUTURE: this is only used by CompareImages() which is used
911 only by the "compare" CLI program at this time. */
912 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
913 break;
914 }
915 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
916 }
anthony805a2d42011-09-25 08:25:12 +0000917 case 'i':
918 {
anthonyafa3dfc2012-03-03 11:31:30 +0000919 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000920 {
anthony72feaa62012-01-17 06:46:23 +0000921 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000922 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000923 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000924 */
anthonyfe1aa782012-03-24 13:43:04 +0000925 arg1 = ArgOption("indefined");
926 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
927 if (parse < 0)
928 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
929 option,arg1);
930 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000931 break;
932 }
anthonyafa3dfc2012-03-03 11:31:30 +0000933 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000934 {
anthony92c93bd2012-03-19 14:02:47 +0000935 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000936 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000937 */
anthonyfe1aa782012-03-24 13:43:04 +0000938 arg1 = ArgOption("undefined");
939 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
940 if (parse < 0)
941 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
942 option,arg1);
943 _image_info->interlace=(InterlaceType) parse;
944 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000945 break;
946 }
anthonyafa3dfc2012-03-03 11:31:30 +0000947 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000948 {
anthony7bcfe7f2012-03-30 14:01:22 +0000949 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000950 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000951 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
952 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +0000953 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000954 break;
955 }
anthonyafa3dfc2012-03-03 11:31:30 +0000956 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000957 {
anthonyfd706f92012-01-19 04:22:02 +0000958 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000959 arg1 = ArgOption("undefined");
960 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
961 if (parse < 0)
962 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
963 option,arg1);
964 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000965 break;
966 }
anthonyafa3dfc2012-03-03 11:31:30 +0000967 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000968 {
anthony7bcfe7f2012-03-30 14:01:22 +0000969 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000970 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000971 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
972 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000973 break;
974 }
anthonyebb73a22012-03-22 14:25:52 +0000975 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000976 }
977 case 'k':
978 {
anthonyafa3dfc2012-03-03 11:31:30 +0000979 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000980 {
anthony7bcfe7f2012-03-30 14:01:22 +0000981 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000982 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000983 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
984 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000985 break;
986 }
anthonyebb73a22012-03-22 14:25:52 +0000987 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000988 }
989 case 'l':
990 {
anthonyafa3dfc2012-03-03 11:31:30 +0000991 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000992 {
anthony72feaa62012-01-17 06:46:23 +0000993 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +0000994 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000995 break;
996 }
anthony756cd0d2012-04-08 12:41:44 +0000997 if (LocaleCompare("limit",option+1) == 0)
998 {
999 MagickSizeType
1000 limit;
1001
1002 limit=MagickResourceInfinity;
1003 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1004 if ( parse < 0 )
1005 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1006 option,arg1);
1007 if (LocaleCompare("unlimited",arg2) != 0)
1008 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1009 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1010 break;
1011 }
anthonyafa3dfc2012-03-03 11:31:30 +00001012 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001013 {
anthonyfe1aa782012-03-24 13:43:04 +00001014 if (IfSetOption) {
1015 if ((strchr(arg1,'%') == (char *) NULL))
1016 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001017 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001018 }
anthony805a2d42011-09-25 08:25:12 +00001019 break;
1020 }
anthony975a8d72012-04-12 13:54:36 +00001021 if (LocaleCompare("lowlight-color",option+1) == 0)
1022 {
anthonyb1d483a2012-04-14 12:53:56 +00001023 /* FUTURE: this is only used by CompareImages() which is used
1024 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001025 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1026 break;
1027 }
anthonyafa3dfc2012-03-03 11:31:30 +00001028 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001029 {
anthony72feaa62012-01-17 06:46:23 +00001030 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001031 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001032 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001033 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1034 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001035 break;
1036 }
anthonyebb73a22012-03-22 14:25:52 +00001037 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001038 }
1039 case 'm':
1040 {
anthonyafa3dfc2012-03-03 11:31:30 +00001041 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001042 {
anthony72feaa62012-01-17 06:46:23 +00001043 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001044 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001045 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001046 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001047 break;
anthonycd358fc2012-04-16 13:59:03 +00001048 }
anthonyb1d483a2012-04-14 12:53:56 +00001049 if (LocaleCompare("metric",option+1) == 0)
1050 {
1051 /* FUTURE: this is only used by CompareImages() which is used
1052 only by the "compare" CLI program at this time. */
1053 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1054 if ( parse < 0 )
1055 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1056 option,arg1);
1057 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001058 break;
anthony805a2d42011-09-25 08:25:12 +00001059 }
anthonyafa3dfc2012-03-03 11:31:30 +00001060 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001061 {
anthony92c93bd2012-03-19 14:02:47 +00001062 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001063 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001064 break;
1065 }
anthonyafa3dfc2012-03-03 11:31:30 +00001066 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001067 {
anthony24aa8822012-03-11 00:56:06 +00001068 /* Setting (used by some input coders!) -- why?
1069 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001070 */
anthony92c93bd2012-03-19 14:02:47 +00001071 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001072 break;
1073 }
anthonyebb73a22012-03-22 14:25:52 +00001074 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001075 }
1076 case 'o':
1077 {
anthonyafa3dfc2012-03-03 11:31:30 +00001078 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001079 {
anthony72feaa62012-01-17 06:46:23 +00001080 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001081 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001082 FUTURE: make set meta-data operator instead.
1083 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001084 */
anthony7bc87992012-03-25 02:32:51 +00001085 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1086 ArgOption("undefined"));
1087 if (parse < 0)
1088 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1089 option,arg1);
1090 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001091 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001092 break;
1093 }
anthonyebb73a22012-03-22 14:25:52 +00001094 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001095 }
1096 case 'p':
1097 {
anthonyafa3dfc2012-03-03 11:31:30 +00001098 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001099 {
anthony7bc87992012-03-25 02:32:51 +00001100 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001101 SyncImageSettings() used to set per-image attribute. ?????
1102 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001103 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001104 */
anthony805a2d42011-09-25 08:25:12 +00001105 char
1106 *canonical_page,
1107 page[MaxTextExtent];
1108
1109 const char
1110 *image_option;
1111
1112 MagickStatusType
1113 flags;
1114
1115 RectangleInfo
1116 geometry;
1117
anthonydcf510d2011-10-30 13:51:40 +00001118 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001119 {
anthony92c93bd2012-03-19 14:02:47 +00001120 (void) DeleteImageOption(_image_info,option+1);
1121 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001122 break;
1123 }
1124 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001125 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001126 if (image_option != (const char *) NULL)
1127 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001128 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001129 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1130 canonical_page=DestroyString(canonical_page);
1131 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1132 (unsigned long) geometry.width,(unsigned long) geometry.height);
1133 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1134 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1135 (unsigned long) geometry.width,(unsigned long) geometry.height,
1136 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001137 (void) SetImageOption(_image_info,option+1,page);
1138 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001139 break;
1140 }
anthonyafa3dfc2012-03-03 11:31:30 +00001141 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001142 {
anthony92c93bd2012-03-19 14:02:47 +00001143 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001144 break;
1145 }
anthonyafa3dfc2012-03-03 11:31:30 +00001146 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001147 {
anthonyf42014d2012-03-25 09:53:06 +00001148 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001149 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001150 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1151 _image_info->pointsize =
1152 _draw_info->pointsize =
1153 StringToDouble(arg1,(char **) NULL);
1154 }
1155 else {
1156 _image_info->pointsize=0.0; /* unset pointsize */
1157 _draw_info->pointsize=12.0;
1158 }
anthony805a2d42011-09-25 08:25:12 +00001159 break;
1160 }
anthonyafa3dfc2012-03-03 11:31:30 +00001161 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001162 {
anthonyf42014d2012-03-25 09:53:06 +00001163 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001164 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001165 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1166 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001167 break;
1168 }
anthonydcf510d2011-10-30 13:51:40 +00001169 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001170 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001171 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001172 {
anthony92c93bd2012-03-19 14:02:47 +00001173 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001174 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001175 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001176 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001177 break;
1178 }
anthonydcf510d2011-10-30 13:51:40 +00001179 */
anthonyebb73a22012-03-22 14:25:52 +00001180 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001181 }
1182 case 'q':
1183 {
anthonyafa3dfc2012-03-03 11:31:30 +00001184 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001185 {
anthony7bcfe7f2012-03-30 14:01:22 +00001186 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001187 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001188 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1189 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001190 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001191 break;
1192 }
anthonyafa3dfc2012-03-03 11:31:30 +00001193 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001194 {
anthony92c93bd2012-03-19 14:02:47 +00001195 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001196 arg1=ArgOption("undefined");
1197 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1198 if (parse < 0)
1199 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1200 option,arg1);
1201 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001202 break;
1203 }
anthonyafa3dfc2012-03-03 11:31:30 +00001204 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001205 {
anthonyf42014d2012-03-25 09:53:06 +00001206 /* FUTURE: if two -quiet is performed you can not do +quiet!
1207 This needs to be checked over thoughly.
1208 */
anthony805a2d42011-09-25 08:25:12 +00001209 static WarningHandler
1210 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001211
anthonyafbaed72011-10-26 12:05:04 +00001212 WarningHandler
1213 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001214
anthonyafbaed72011-10-26 12:05:04 +00001215 if ( tmp != (WarningHandler) NULL)
1216 warning_handler = tmp; /* remember the old handler */
1217 if (!IfSetOption) /* set the old handler */
1218 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001219 break;
1220 }
anthonyebb73a22012-03-22 14:25:52 +00001221 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001222 }
1223 case 'r':
1224 {
anthonyafa3dfc2012-03-03 11:31:30 +00001225 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001226 {
anthonydcf510d2011-10-30 13:51:40 +00001227 /* Image chromaticity X,Y NB: Y=X if Y not defined
1228 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001229 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001230 */
anthonyf42014d2012-03-25 09:53:06 +00001231 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001232 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001233 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001234 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001235 break;
1236 }
cristyb0f7a182012-04-06 23:33:11 +00001237 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001238 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001239 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001240 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001241 {
anthony92c93bd2012-03-19 14:02:47 +00001242 /* _draw_info only setting */
1243 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001244 break;
1245 }
anthony756cd0d2012-04-08 12:41:44 +00001246 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1247 {
1248 /* link image and setting stacks - option is itself saved on stack! */
1249 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1250 break;
1251 }
anthonyebb73a22012-03-22 14:25:52 +00001252 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001253 }
1254 case 's':
1255 {
anthonyafa3dfc2012-03-03 11:31:30 +00001256 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001257 {
anthonyafbaed72011-10-26 12:05:04 +00001258 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001259 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001260 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001261 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001262 break;
1263 }
anthonyafa3dfc2012-03-03 11:31:30 +00001264 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001265 {
anthonyf42014d2012-03-25 09:53:06 +00001266 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001267 What ??? Why ????
1268 */
anthony7bcfe7f2012-03-30 14:01:22 +00001269 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001270 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001271 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1272 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001273 break;
1274 }
anthonyafa3dfc2012-03-03 11:31:30 +00001275 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001276 {
anthony7bcfe7f2012-03-30 14:01:22 +00001277 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001278 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001279 SetRandomSecretKey(
anthony24aa8822012-03-11 00:56:06 +00001280 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001281 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001282 break;
1283 }
anthonyafa3dfc2012-03-03 11:31:30 +00001284 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001285 {
anthony92c93bd2012-03-19 14:02:47 +00001286 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001287 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001288 */
anthony92c93bd2012-03-19 14:02:47 +00001289 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001290 break;
1291 }
anthonyafa3dfc2012-03-03 11:31:30 +00001292 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001293 {
anthonyf42014d2012-03-25 09:53:06 +00001294 arg1=ArgOption("undefined");
1295 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1296 if (parse < 0)
1297 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1298 option,arg1);
1299 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001300 break;
1301 }
anthonyafa3dfc2012-03-03 11:31:30 +00001302 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001303 {
anthonyafbaed72011-10-26 12:05:04 +00001304 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001305 UPDATE: ensure stroke color is not destroyed is a pattern
1306 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001307 */
anthony72feaa62012-01-17 06:46:23 +00001308 MagickBooleanType
1309 status;
anthonyafbaed72011-10-26 12:05:04 +00001310
1311 ExceptionInfo
1312 *sans;
1313
anthonyfd706f92012-01-19 04:22:02 +00001314 PixelInfo
1315 color;
1316
anthony2a0ec8c2012-03-24 04:35:56 +00001317 arg1 = ArgOption("none"); /* +fill turns it off! */
1318 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001319 if (_draw_info->stroke_pattern != (Image *) NULL)
1320 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001321
1322 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001323 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001324 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001325 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001326
anthony7bcfe7f2012-03-30 14:01:22 +00001327 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001328 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001329 else
anthony92c93bd2012-03-19 14:02:47 +00001330 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001331 break;
1332 }
anthonyafa3dfc2012-03-03 11:31:30 +00001333 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001334 {
anthony7bcfe7f2012-03-30 14:01:22 +00001335 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001336 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001337 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1338 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001339 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001340 break;
1341 }
anthonyafa3dfc2012-03-03 11:31:30 +00001342 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001343 {
anthonyf42014d2012-03-25 09:53:06 +00001344 arg1=ArgOption("undefined");
1345 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1346 if (parse < 0)
1347 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1348 option,arg1);
1349 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001350 break;
1351 }
anthonycd358fc2012-04-16 13:59:03 +00001352#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001353 if (LocaleCompare("subimage-search",option+1) == 0)
1354 {
1355 /* FUTURE: this is only used by CompareImages() which is used
1356 only by the "compare" CLI program at this time. */
1357 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1358 break;
1359 }
anthonycd358fc2012-04-16 13:59:03 +00001360#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001361 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001362 {
anthonyf42014d2012-03-25 09:53:06 +00001363 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001364 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001365 break;
1366 }
anthonyebb73a22012-03-22 14:25:52 +00001367 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001368 }
1369 case 't':
1370 {
anthonyafa3dfc2012-03-03 11:31:30 +00001371 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001372 {
anthony72feaa62012-01-17 06:46:23 +00001373 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001374 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001375 break;
1376 }
anthonyafa3dfc2012-03-03 11:31:30 +00001377 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001378 {
anthony52bef752012-03-27 13:54:47 +00001379 /* FUTURE: move _image_info string to option splay-tree
1380 Other than "montage" what uses "texture" ????
1381 */
anthony92c93bd2012-03-19 14:02:47 +00001382 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001383 break;
1384 }
anthonyafa3dfc2012-03-03 11:31:30 +00001385 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001386 {
anthony92c93bd2012-03-19 14:02:47 +00001387 _draw_info->fill_pattern=IfSetOption
1388 ?GetImageCache(_image_info,arg1,_exception)
1389 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001390 break;
1391 }
anthonyafa3dfc2012-03-03 11:31:30 +00001392 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001393 {
anthony72feaa62012-01-17 06:46:23 +00001394 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001395 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001396 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001397 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1398 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001399 break;
1400 }
anthonyafa3dfc2012-03-03 11:31:30 +00001401 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001402 {
anthony92c93bd2012-03-19 14:02:47 +00001403 /* FUTURE: both _image_info attribute & ImageOption in use!
1404 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001405 SyncImageSettings() used to set per-image attribute.
1406
anthonyafbaed72011-10-26 12:05:04 +00001407 Note that +transparent-color, means fall-back to image
1408 attribute so ImageOption is deleted, not set to a default.
1409 */
anthony7bcfe7f2012-03-30 14:01:22 +00001410 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001411 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001412 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001413 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001414 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001415 break;
1416 }
anthonyafa3dfc2012-03-03 11:31:30 +00001417 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001418 {
anthony92c93bd2012-03-19 14:02:47 +00001419 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1420 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001421 break;
1422 }
anthonyafa3dfc2012-03-03 11:31:30 +00001423 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001424 {
anthony72feaa62012-01-17 06:46:23 +00001425 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001426 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1427 ArgOption("undefined"));
1428 if (parse < 0)
1429 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1430 option,arg1);
1431 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001432 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001433 break;
1434 }
anthonyebb73a22012-03-22 14:25:52 +00001435 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001436 }
1437 case 'u':
1438 {
anthonyafa3dfc2012-03-03 11:31:30 +00001439 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001440 {
anthony92c93bd2012-03-19 14:02:47 +00001441 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001442 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001443 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001444 break;
1445 }
anthonyafa3dfc2012-03-03 11:31:30 +00001446 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001447 {
anthony72feaa62012-01-17 06:46:23 +00001448 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001449 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001450 FUTURE: this probably should be part of the density setting
1451 */
anthony52bef752012-03-27 13:54:47 +00001452 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1453 ArgOption("undefined"));
1454 if (parse < 0)
1455 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1456 option,arg1);
1457 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001458 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001459 break;
1460 }
anthonyebb73a22012-03-22 14:25:52 +00001461 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001462 }
1463 case 'v':
1464 {
anthonyafa3dfc2012-03-03 11:31:30 +00001465 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001466 {
anthony24aa8822012-03-11 00:56:06 +00001467 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001468 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001469 */
anthony92c93bd2012-03-19 14:02:47 +00001470 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1471 _image_info->verbose= ArgBoolean;
1472 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001473 break;
1474 }
anthonyafa3dfc2012-03-03 11:31:30 +00001475 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001476 {
anthony92c93bd2012-03-19 14:02:47 +00001477 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001478 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001479 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001480 */
anthony92c93bd2012-03-19 14:02:47 +00001481 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001482 break;
1483 }
anthonyafa3dfc2012-03-03 11:31:30 +00001484 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001485 {
anthonyfd706f92012-01-19 04:22:02 +00001486 /* SyncImageSettings() used to set per-image attribute.
1487 This is VERY deep in the image caching structure.
1488 */
anthony52bef752012-03-27 13:54:47 +00001489 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1490 ArgOption("undefined"));
1491 if (parse < 0)
1492 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1493 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001494 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001495 break;
1496 }
anthonyebb73a22012-03-22 14:25:52 +00001497 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001498 }
1499 case 'w':
1500 {
anthonyafa3dfc2012-03-03 11:31:30 +00001501 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001502 {
anthony72feaa62012-01-17 06:46:23 +00001503 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001504 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001505 */
anthony52bef752012-03-27 13:54:47 +00001506 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001507 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001508 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001509 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001510 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001511 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001512 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001513 if (_draw_info->weight <= 800)
1514 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001515 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001516 if (_draw_info->weight >= 100)
1517 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001518 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001519 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001520 break;
1521 }
anthonyafa3dfc2012-03-03 11:31:30 +00001522 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001523 {
anthony72feaa62012-01-17 06:46:23 +00001524 /* Used as a image chromaticity setting
1525 SyncImageSettings() used to set per-image attribute.
1526 */
anthony52bef752012-03-27 13:54:47 +00001527 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001528 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001529 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1530 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001531 break;
1532 }
anthonyebb73a22012-03-22 14:25:52 +00001533 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001534 }
1535 default:
anthonyebb73a22012-03-22 14:25:52 +00001536 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001537 }
anthony24aa8822012-03-11 00:56:06 +00001538
anthony92c93bd2012-03-19 14:02:47 +00001539#undef _image_info
1540#undef _exception
1541#undef _draw_info
1542#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001543#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001544#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001545#undef ArgBooleanNot
1546#undef ArgBooleanString
1547#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001548
anthony31f1bf72012-01-30 12:37:22 +00001549 return;
anthony805a2d42011-09-25 08:25:12 +00001550}
1551
1552/*
1553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554% %
1555% %
1556% %
anthony43f425d2012-02-26 12:58:58 +00001557+ 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 +00001558% %
1559% %
1560% %
1561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562%
anthony31f1bf72012-01-30 12:37:22 +00001563% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001564% the images in the CLI wand, with the settings that was previously saved in
1565% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001566%
1567% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001568% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001569%
anthonyd1447672012-01-19 05:33:53 +00001570% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001571%
anthony43f425d2012-02-26 12:58:58 +00001572% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001573% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001574%
1575% A description of each parameter follows:
1576%
anthony43f425d2012-02-26 12:58:58 +00001577% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001578%
anthonyfd706f92012-01-19 04:22:02 +00001579% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001580%
anthonyfd706f92012-01-19 04:22:02 +00001581% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001582%
anthony805a2d42011-09-25 08:25:12 +00001583*/
anthony31f1bf72012-01-30 12:37:22 +00001584
1585/*
1586 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001587 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001588
1589 The image in the list may be modified in three different ways...
1590 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1591 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1592 * one image replace by a list of images (-separate and -crop only!)
1593
anthonyafa3dfc2012-03-03 11:31:30 +00001594 In each case the result replaces the single original image in the list, as
1595 well as the pointer to the modified image (last image added if replaced by a
1596 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001597
1598 As the image pointed to may be replaced, the first image in the list may
1599 also change. GetFirstImageInList() should be used by caller if they wish
1600 return the Image pointer to the first image in list.
1601*/
anthony43f425d2012-02-26 12:58:58 +00001602static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001603 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001604{
1605 Image *
1606 new_image;
1607
anthony805a2d42011-09-25 08:25:12 +00001608 GeometryInfo
1609 geometry_info;
1610
1611 RectangleInfo
1612 geometry;
1613
1614 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001615 flags;
1616
anthony92c93bd2012-03-19 14:02:47 +00001617 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001618 parse;
anthony92c93bd2012-03-19 14:02:47 +00001619
anthony2e4501b2012-03-30 04:41:54 +00001620#define _image_info (cli_wand->wand.image_info)
1621#define _image (cli_wand->wand.images)
1622#define _exception (cli_wand->wand.exception)
1623#define _draw_info (cli_wand->draw_info)
1624#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001625#define IfNormalOp (*option=='-')
1626#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00001627#define normal_op IsMagickTrue(IfNormalOp)
1628#define plus_alt_op IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001629
anthony43f425d2012-02-26 12:58:58 +00001630 assert(cli_wand != (MagickCLI *) NULL);
1631 assert(cli_wand->signature == WandSignature);
1632 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001633 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001634 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001635 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001636
anthony805a2d42011-09-25 08:25:12 +00001637 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001638
anthony5330ae02012-03-20 14:17:01 +00001639 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001640
anthonyfd706f92012-01-19 04:22:02 +00001641 /* FUTURE: We may need somthing a little more optimized than this!
1642 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1643 */
anthonyafa3dfc2012-03-03 11:31:30 +00001644 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001645 {
1646 case 'a':
1647 {
anthonyafa3dfc2012-03-03 11:31:30 +00001648 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001649 {
anthonyfd706f92012-01-19 04:22:02 +00001650 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001651 if ((flags & (RhoValue|SigmaValue)) == 0)
1652 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001653 if ((flags & SigmaValue) == 0)
1654 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001655 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001656 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001657 break;
1658 }
anthonyafa3dfc2012-03-03 11:31:30 +00001659 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001660 {
anthonyfe1aa782012-03-24 13:43:04 +00001661 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001662 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001663 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1664 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1665 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001666 _exception);
anthony805a2d42011-09-25 08:25:12 +00001667 break;
1668 }
anthonyafa3dfc2012-03-03 11:31:30 +00001669 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001670 {
anthonyfd706f92012-01-19 04:22:02 +00001671 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001672 if ((flags & (RhoValue|SigmaValue)) == 0)
1673 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001674 if ((flags & SigmaValue) == 0)
1675 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001676 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001677 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001678 break;
1679 }
anthonyafa3dfc2012-03-03 11:31:30 +00001680 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001681 {
anthony2a0ec8c2012-03-24 04:35:56 +00001682 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1683 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001684 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1685 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001686 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1687 _exception);
anthony805a2d42011-09-25 08:25:12 +00001688 break;
1689 }
anthonyafa3dfc2012-03-03 11:31:30 +00001690 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001691 {
1692 char
1693 *text,
1694 geometry[MaxTextExtent];
1695
anthony805a2d42011-09-25 08:25:12 +00001696 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001697 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001698 if ((flags & RhoValue) == 0)
1699 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001700 if ((flags & SigmaValue) == 0)
1701 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001702 text=InterpretImageProperties(_image_info,_image,arg2,
1703 _exception);
anthony805a2d42011-09-25 08:25:12 +00001704 if (text == (char *) NULL)
1705 break;
anthony92c93bd2012-03-19 14:02:47 +00001706 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001707 text=DestroyString(text);
1708 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1709 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001710 (void) CloneString(&_draw_info->geometry,geometry);
1711 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001712 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001713 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001714 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001715 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001716 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001717 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001718 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001719 (void) AnnotateImage(_image,_draw_info,_exception);
1720 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001721 break;
1722 }
anthonyafa3dfc2012-03-03 11:31:30 +00001723 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001724 {
anthony92c93bd2012-03-19 14:02:47 +00001725 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001726 break;
1727 }
anthonyafa3dfc2012-03-03 11:31:30 +00001728 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001729 {
anthony92c93bd2012-03-19 14:02:47 +00001730 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001731 break;
1732 }
anthonyafa3dfc2012-03-03 11:31:30 +00001733 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001734 {
anthony5330ae02012-03-20 14:17:01 +00001735 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001736 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001737 {
1738 case TopRightOrientation:
1739 {
anthony92c93bd2012-03-19 14:02:47 +00001740 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001741 break;
1742 }
1743 case BottomRightOrientation:
1744 {
anthony92c93bd2012-03-19 14:02:47 +00001745 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001746 break;
1747 }
1748 case BottomLeftOrientation:
1749 {
anthony92c93bd2012-03-19 14:02:47 +00001750 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001751 break;
1752 }
1753 case LeftTopOrientation:
1754 {
anthony92c93bd2012-03-19 14:02:47 +00001755 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001756 break;
1757 }
1758 case RightTopOrientation:
1759 {
anthony92c93bd2012-03-19 14:02:47 +00001760 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001761 break;
1762 }
1763 case RightBottomOrientation:
1764 {
anthony92c93bd2012-03-19 14:02:47 +00001765 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001766 break;
1767 }
1768 case LeftBottomOrientation:
1769 {
anthony92c93bd2012-03-19 14:02:47 +00001770 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001771 break;
1772 }
1773 default:
1774 break;
1775 }
1776 if (new_image != (Image *) NULL)
1777 new_image->orientation=TopLeftOrientation;
1778 break;
1779 }
anthonyebb73a22012-03-22 14:25:52 +00001780 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001781 }
1782 case 'b':
1783 {
anthonyafa3dfc2012-03-03 11:31:30 +00001784 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001785 {
anthony7bcfe7f2012-03-30 14:01:22 +00001786 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001787 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001788 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001789 break;
1790 }
anthonyafa3dfc2012-03-03 11:31:30 +00001791 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001792 {
anthony805a2d42011-09-25 08:25:12 +00001793 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001794 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001795 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001796 if ((flags & RhoValue) == 0)
1797 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001798 }
anthony92c93bd2012-03-19 14:02:47 +00001799 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001800 break;
1801 }
anthonyafa3dfc2012-03-03 11:31:30 +00001802 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001803 {
anthonyfd706f92012-01-19 04:22:02 +00001804 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001805 if ((flags & (RhoValue|SigmaValue)) == 0)
1806 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001807 if ((flags & SigmaValue) == 0)
1808 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001809 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1810 _exception);
anthony805a2d42011-09-25 08:25:12 +00001811 break;
1812 }
anthonyafa3dfc2012-03-03 11:31:30 +00001813 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001814 {
anthony31f1bf72012-01-30 12:37:22 +00001815 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001816 compose;
1817
1818 const char*
anthony5f867ae2011-10-09 10:28:34 +00001819 value;
1820
anthony22de2722012-04-19 14:43:00 +00001821 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
1822 if ((flags & RhoValue) == 0)
anthony5330ae02012-03-20 14:17:01 +00001823 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony22de2722012-04-19 14:43:00 +00001824 if ((flags & SigmaValue) == 0)
1825 geometry.height=geometry.width;
anthony5330ae02012-03-20 14:17:01 +00001826
anthony92c93bd2012-03-19 14:02:47 +00001827 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001828 if (value != (const char *) NULL)
1829 compose=(CompositeOperator) ParseCommandOption(
1830 MagickComposeOptions,MagickFalse,value);
1831 else
anthony92c93bd2012-03-19 14:02:47 +00001832 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001833
anthony92c93bd2012-03-19 14:02:47 +00001834 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001835 break;
1836 }
anthonyafa3dfc2012-03-03 11:31:30 +00001837 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001838 {
1839 double
1840 brightness,
1841 contrast;
1842
1843 GeometryInfo
1844 geometry_info;
1845
1846 MagickStatusType
1847 flags;
1848
anthonyfd706f92012-01-19 04:22:02 +00001849 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001850 if ((flags & RhoValue) == 0)
1851 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001852 brightness=geometry_info.rho;
1853 contrast=0.0;
1854 if ((flags & SigmaValue) != 0)
1855 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001856 (void) BrightnessContrastImage(_image,brightness,contrast,
1857 _exception);
anthony805a2d42011-09-25 08:25:12 +00001858 break;
1859 }
anthonyebb73a22012-03-22 14:25:52 +00001860 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001861 }
1862 case 'c':
1863 {
anthonyafa3dfc2012-03-03 11:31:30 +00001864 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001865 {
1866 char
1867 *color_correction_collection;
1868
1869 /*
1870 Color correct with a color decision list.
1871 */
anthony92c93bd2012-03-19 14:02:47 +00001872 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001873 if (color_correction_collection == (char *) NULL)
1874 break;
anthony92c93bd2012-03-19 14:02:47 +00001875 (void) ColorDecisionListImage(_image,color_correction_collection,
1876 _exception);
anthony805a2d42011-09-25 08:25:12 +00001877 break;
1878 }
anthonyafa3dfc2012-03-03 11:31:30 +00001879 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001880 {
anthonyfd706f92012-01-19 04:22:02 +00001881 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001882 if ((flags & (RhoValue|SigmaValue)) == 0)
1883 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001884 if ((flags & SigmaValue) == 0)
1885 geometry_info.sigma=1.0;
1886 if ((flags & XiValue) == 0)
1887 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001888 new_image=CharcoalImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001889 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001890 break;
1891 }
anthonyafa3dfc2012-03-03 11:31:30 +00001892 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001893 {
anthony7bcfe7f2012-03-30 14:01:22 +00001894 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001895 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001896 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1897 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001898 break;
1899 }
anthonyafa3dfc2012-03-03 11:31:30 +00001900 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001901 {
anthony92c93bd2012-03-19 14:02:47 +00001902 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001903 break;
1904 }
anthonyafa3dfc2012-03-03 11:31:30 +00001905 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001906 {
anthonyafa3dfc2012-03-03 11:31:30 +00001907 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001908 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001909 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001910 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001911 break;
1912 }
anthonyafa3dfc2012-03-03 11:31:30 +00001913 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001914 {
1915 CacheView
1916 *mask_view;
1917
1918 Image
1919 *mask_image;
1920
1921 register Quantum
1922 *restrict q;
1923
1924 register ssize_t
1925 x;
1926
1927 ssize_t
1928 y;
1929
anthonyafa3dfc2012-03-03 11:31:30 +00001930 if (IfPlusOp) {
1931 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001932 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00001933 break;
1934 }
anthony92c93bd2012-03-19 14:02:47 +00001935 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001936 if (mask_image == (Image *) NULL)
1937 break;
anthony7bcfe7f2012-03-30 14:01:22 +00001938 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00001939 break;
anthony5330ae02012-03-20 14:17:01 +00001940 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00001941 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristydb070952012-04-20 14:33:00 +00001942 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001943 for (y=0; y < (ssize_t) mask_image->rows; y++)
1944 {
1945 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00001946 _exception);
anthony805a2d42011-09-25 08:25:12 +00001947 if (q == (Quantum *) NULL)
1948 break;
1949 for (x=0; x < (ssize_t) mask_image->columns; x++)
1950 {
anthony7bcfe7f2012-03-30 14:01:22 +00001951 if (IfMagickFalse(mask_image->matte))
anthony805a2d42011-09-25 08:25:12 +00001952 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1953 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1954 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1955 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1956 q+=GetPixelChannels(mask_image);
1957 }
anthony7bcfe7f2012-03-30 14:01:22 +00001958 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00001959 break;
1960 }
anthonyfd706f92012-01-19 04:22:02 +00001961 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001962 mask_view=DestroyCacheView(mask_view);
1963 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00001964 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001965 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001966 break;
1967 }
anthonyafa3dfc2012-03-03 11:31:30 +00001968 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001969 {
anthony92c93bd2012-03-19 14:02:47 +00001970 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00001971 break;
1972 }
anthonyafa3dfc2012-03-03 11:31:30 +00001973 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001974 {
anthony7bcfe7f2012-03-30 14:01:22 +00001975 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001976 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001977 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00001978 break;
1979 }
anthonyafa3dfc2012-03-03 11:31:30 +00001980 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001981 {
1982 KernelInfo
1983 *kernel;
1984
anthonyfd706f92012-01-19 04:22:02 +00001985 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001986 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00001987 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001988 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00001989 kernel=DestroyKernelInfo(kernel);
1990 break;
1991 }
anthonyafa3dfc2012-03-03 11:31:30 +00001992 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001993 {
anthony5330ae02012-03-20 14:17:01 +00001994 /* Reduce the number of colors in the image.
1995 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00001996 */
anthony92c93bd2012-03-19 14:02:47 +00001997 _quantize_info->number_colors=StringToUnsignedLong(arg1);
1998 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00001999 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002000 if ((_image->storage_class == DirectClass) ||
2001 _image->colors > _quantize_info->number_colors)
2002 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002003 else
anthony92c93bd2012-03-19 14:02:47 +00002004 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002005 break;
2006 }
anthonyafa3dfc2012-03-03 11:31:30 +00002007 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002008 {
anthony5330ae02012-03-20 14:17:01 +00002009 /* WARNING: this is both a image_info setting (already done)
2010 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002011
2012 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002013 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002014
anthonyd2cdc862011-10-07 14:07:17 +00002015 Note that +colorspace sets "undefined" or no effect on
2016 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002017 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002018 */
anthony92c93bd2012-03-19 14:02:47 +00002019 (void) TransformImageColorspace(_image,
2020 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2021 _exception);
anthony805a2d42011-09-25 08:25:12 +00002022 break;
2023 }
anthonyafa3dfc2012-03-03 11:31:30 +00002024 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002025 {
anthony464f1c42012-04-22 08:51:01 +00002026 CLIWandWarnReplaced(normal_op?"-level":"+level");
anthony92c93bd2012-03-19 14:02:47 +00002027 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002028 break;
2029 }
anthonyafa3dfc2012-03-03 11:31:30 +00002030 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002031 {
2032 double
2033 black_point,
2034 white_point;
2035
2036 MagickStatusType
2037 flags;
2038
anthonyfd706f92012-01-19 04:22:02 +00002039 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002040 if ((flags & RhoValue) == 0)
2041 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002042 black_point=geometry_info.rho;
2043 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2044 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002045 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002046 black_point*=(double) _image->columns*_image->rows/100.0;
2047 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002048 }
anthony92c93bd2012-03-19 14:02:47 +00002049 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002050 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002051 (void) ContrastStretchImage(_image,black_point,white_point,
2052 _exception);
anthony805a2d42011-09-25 08:25:12 +00002053 break;
2054 }
anthonyafa3dfc2012-03-03 11:31:30 +00002055 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002056 {
2057 KernelInfo
2058 *kernel_info;
2059
anthonyfd706f92012-01-19 04:22:02 +00002060 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002061 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002062 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony22de2722012-04-19 14:43:00 +00002063 new_image=MorphologyImage(_image,ConvolveMorphology,1,kernel_info,
2064 _exception);
anthony805a2d42011-09-25 08:25:12 +00002065 kernel_info=DestroyKernelInfo(kernel_info);
2066 break;
2067 }
anthonyafa3dfc2012-03-03 11:31:30 +00002068 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002069 {
anthony31f1bf72012-01-30 12:37:22 +00002070 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002071 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002072 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002073 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002074 break;
2075 }
anthonyafa3dfc2012-03-03 11:31:30 +00002076 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002077 {
anthony7bcfe7f2012-03-30 14:01:22 +00002078 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002079 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002080 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2081 _exception);
anthony805a2d42011-09-25 08:25:12 +00002082 break;
2083 }
anthonyebb73a22012-03-22 14:25:52 +00002084 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002085 }
2086 case 'd':
2087 {
anthonyafa3dfc2012-03-03 11:31:30 +00002088 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002089 {
2090 StringInfo
2091 *passkey;
2092
anthony92c93bd2012-03-19 14:02:47 +00002093 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002094 if (passkey == (StringInfo *) NULL)
2095 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2096
2097 (void) PasskeyDecipherImage(_image,passkey,_exception);
2098 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002099 break;
2100 }
anthonyafa3dfc2012-03-03 11:31:30 +00002101 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002102 {
anthony92c93bd2012-03-19 14:02:47 +00002103 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002104 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002105
anthonydcf510d2011-10-30 13:51:40 +00002106 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2107 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002108
anthonyfd706f92012-01-19 04:22:02 +00002109 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002110 */
anthony92c93bd2012-03-19 14:02:47 +00002111 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002112 break;
2113 }
anthonyafa3dfc2012-03-03 11:31:30 +00002114 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002115 {
2116 double
2117 threshold;
2118
anthonyebb73a22012-03-22 14:25:52 +00002119 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002120 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002121 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002122 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002123 }
anthonyafa3dfc2012-03-03 11:31:30 +00002124 else
2125 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002126 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002127 break;
2128 }
anthonyafa3dfc2012-03-03 11:31:30 +00002129 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002130 {
anthony92c93bd2012-03-19 14:02:47 +00002131 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002132 break;
2133 }
anthonyafa3dfc2012-03-03 11:31:30 +00002134 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002135 {
2136 char
anthonyb1d483a2012-04-14 12:53:56 +00002137 *arg;
anthony805a2d42011-09-25 08:25:12 +00002138
anthony805a2d42011-09-25 08:25:12 +00002139 double
anthonyb1d483a2012-04-14 12:53:56 +00002140 *args;
anthony805a2d42011-09-25 08:25:12 +00002141
anthonyb1d483a2012-04-14 12:53:56 +00002142 ssize_t
2143 count;
anthony805a2d42011-09-25 08:25:12 +00002144
anthony2a0ec8c2012-03-24 04:35:56 +00002145 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2146 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002147 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2148 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002149 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002150 {
anthony80c37752012-01-16 01:03:11 +00002151 double
2152 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002153 /* Special Case - Argument is actually a resize geometry!
2154 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002155 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002156 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002157 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002158 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2159 option,arg2);
2160 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002161 resize_args[0]=(double) geometry.width;
2162 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002163 new_image=DistortImage(_image,(DistortImageMethod) parse,
2164 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002165 break;
2166 }
anthonyb1d483a2012-04-14 12:53:56 +00002167 /* allow percent escapes in argument string */
2168 arg=InterpretImageProperties(_image_info,_image,arg2,_exception);
2169 if (arg == (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00002170 break;
anthonyb1d483a2012-04-14 12:53:56 +00002171 /* convert argument string into an array of doubles */
2172 args = StringToArrayOfDoubles(arg,&count,_exception);
2173 arg=DestroyString(arg);
2174 if (args == (double *)NULL )
2175 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2176
2177 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
2178 plus_alt_op,_exception);
2179 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002180 break;
2181 }
anthonyafa3dfc2012-03-03 11:31:30 +00002182 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002183 {
anthony92c93bd2012-03-19 14:02:47 +00002184 (void) CloneString(&_draw_info->primitive,arg1);
2185 (void) DrawImage(_image,_draw_info,_exception);
2186 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002187 break;
2188 }
anthonyebb73a22012-03-22 14:25:52 +00002189 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002190 }
2191 case 'e':
2192 {
anthonyafa3dfc2012-03-03 11:31:30 +00002193 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002194 {
anthonyfd706f92012-01-19 04:22:02 +00002195 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002196 if ((flags & (RhoValue|SigmaValue)) == 0)
2197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002198 if ((flags & SigmaValue) == 0)
2199 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002200 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2201 _exception);
anthony805a2d42011-09-25 08:25:12 +00002202 break;
2203 }
anthonyafa3dfc2012-03-03 11:31:30 +00002204 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002205 {
anthonyfd706f92012-01-19 04:22:02 +00002206 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002207 if ((flags & (RhoValue|SigmaValue)) == 0)
2208 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002209 if ((flags & SigmaValue) == 0)
2210 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002211 new_image=EmbossImage(_image,geometry_info.rho,
2212 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002213 break;
2214 }
anthonyafa3dfc2012-03-03 11:31:30 +00002215 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002216 {
2217 StringInfo
2218 *passkey;
2219
anthony92c93bd2012-03-19 14:02:47 +00002220 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002221 if (passkey != (StringInfo *) NULL)
2222 {
anthony92c93bd2012-03-19 14:02:47 +00002223 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002224 passkey=DestroyStringInfo(passkey);
2225 }
2226 break;
2227 }
anthonyafa3dfc2012-03-03 11:31:30 +00002228 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002229 {
anthony92c93bd2012-03-19 14:02:47 +00002230 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002231 break;
2232 }
anthonyafa3dfc2012-03-03 11:31:30 +00002233 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002234 {
anthony92c93bd2012-03-19 14:02:47 +00002235 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002236 break;
2237 }
anthonyafa3dfc2012-03-03 11:31:30 +00002238 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002239 {
2240 double
2241 constant;
2242
anthony2a0ec8c2012-03-24 04:35:56 +00002243 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2244 if ( parse < 0 )
2245 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2246 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002247 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002248 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002249 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002250 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2251 _exception);
anthony805a2d42011-09-25 08:25:12 +00002252 break;
2253 }
anthonyafa3dfc2012-03-03 11:31:30 +00002254 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002255 {
anthony7bcfe7f2012-03-30 14:01:22 +00002256 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002257 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002258 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002259 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002260 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002261 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002262 geometry.height=_image->rows;
2263 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002264 break;
2265 }
anthonyebb73a22012-03-22 14:25:52 +00002266 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002267 }
2268 case 'f':
2269 {
anthonyafa3dfc2012-03-03 11:31:30 +00002270 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002271 {
anthony31f1bf72012-01-30 12:37:22 +00002272 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002273 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002274 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002275 break;
2276 }
anthony92c93bd2012-03-19 14:02:47 +00002277 (void) SetImageArtifact(_image,"identify:features","true");
2278 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002279 break;
2280 }
anthonyafa3dfc2012-03-03 11:31:30 +00002281 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002282 {
anthony92c93bd2012-03-19 14:02:47 +00002283 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002284 break;
2285 }
anthonyafa3dfc2012-03-03 11:31:30 +00002286 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002287 {
anthony92c93bd2012-03-19 14:02:47 +00002288 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002289 break;
2290 }
anthonyafa3dfc2012-03-03 11:31:30 +00002291 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002292 {
2293 PixelInfo
2294 target;
2295
anthony7bcfe7f2012-03-30 14:01:22 +00002296 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002297 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002298 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2299 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2300 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2301 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002302 break;
2303 }
anthonyafa3dfc2012-03-03 11:31:30 +00002304 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002305 {
2306 FrameInfo
2307 frame_info;
2308
anthony31f1bf72012-01-30 12:37:22 +00002309 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002310 compose;
2311
2312 const char*
2313 value;
2314
anthony92c93bd2012-03-19 14:02:47 +00002315 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002316 if (value != (const char *) NULL)
2317 compose=(CompositeOperator) ParseCommandOption(
2318 MagickComposeOptions,MagickFalse,value);
2319 else
anthony92c93bd2012-03-19 14:02:47 +00002320 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002321
anthony7bcfe7f2012-03-30 14:01:22 +00002322 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002323 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002324 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002325 frame_info.width=geometry.width;
2326 frame_info.height=geometry.height;
2327 if ((flags & HeightValue) == 0)
2328 frame_info.height=geometry.width;
2329 frame_info.outer_bevel=geometry.x;
2330 frame_info.inner_bevel=geometry.y;
2331 frame_info.x=(ssize_t) frame_info.width;
2332 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002333 frame_info.width=_image->columns+2*frame_info.width;
2334 frame_info.height=_image->rows+2*frame_info.height;
2335 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002336 break;
2337 }
anthonyafa3dfc2012-03-03 11:31:30 +00002338 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002339 {
2340 char
anthonyb1d483a2012-04-14 12:53:56 +00002341 *arg;
anthony805a2d42011-09-25 08:25:12 +00002342
2343 double
anthonyb1d483a2012-04-14 12:53:56 +00002344 *args;
anthony805a2d42011-09-25 08:25:12 +00002345
anthonyb1d483a2012-04-14 12:53:56 +00002346 ssize_t
2347 count;
anthony805a2d42011-09-25 08:25:12 +00002348
anthony2a0ec8c2012-03-24 04:35:56 +00002349 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2350 if ( parse < 0 )
2351 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2352 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002353 /* allow percent escapes in argument string */
2354 arg=InterpretImageProperties(_image_info,_image,arg2,_exception);
2355 if (arg == (char *) NULL)
2356 break;
2357 /* convert argument string into an array of doubles */
2358 args = StringToArrayOfDoubles(arg,&count,_exception);
2359 arg=DestroyString(arg);
2360 if (args == (double *)NULL )
2361 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2362
2363 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2364 _exception);
2365 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002366 break;
2367 }
anthonyebb73a22012-03-22 14:25:52 +00002368 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002369 }
2370 case 'g':
2371 {
anthonyafa3dfc2012-03-03 11:31:30 +00002372 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002373 {
anthony7bcfe7f2012-03-30 14:01:22 +00002374 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002375 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002376 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002377 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2378 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002379 else
anthony92c93bd2012-03-19 14:02:47 +00002380 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002381 break;
2382 }
anthony975a8d72012-04-12 13:54:36 +00002383 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002384 {
anthonyfd706f92012-01-19 04:22:02 +00002385 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002386 if ((flags & (RhoValue|SigmaValue)) == 0)
2387 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002388 if ((flags & SigmaValue) == 0)
2389 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002390 new_image=GaussianBlurImage(_image,geometry_info.rho,
2391 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002392 break;
2393 }
anthony975a8d72012-04-12 13:54:36 +00002394 if (LocaleCompare("gaussian",option+1) == 0)
2395 {
anthony464f1c42012-04-22 08:51:01 +00002396 CLIWandWarnReplaced("-gaussian-blur");
anthony975a8d72012-04-12 13:54:36 +00002397 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2398 }
anthonyafa3dfc2012-03-03 11:31:30 +00002399 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002400 {
anthonyfd706f92012-01-19 04:22:02 +00002401 /*
anthony31f1bf72012-01-30 12:37:22 +00002402 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002403 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002404 FUTURE: Why if no 'offset' does this resize ALL images?
2405 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002406 */
anthonyafa3dfc2012-03-03 11:31:30 +00002407 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002408 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002409 if (_image->geometry != (char *) NULL)
2410 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002411 break;
2412 }
anthony7bcfe7f2012-03-30 14:01:22 +00002413 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002414 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002415 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002416 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002417 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002418 else
anthony92c93bd2012-03-19 14:02:47 +00002419 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002420 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002421 break;
2422 }
anthonyebb73a22012-03-22 14:25:52 +00002423 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002424 }
anthony805a2d42011-09-25 08:25:12 +00002425 case 'i':
2426 {
anthonyafa3dfc2012-03-03 11:31:30 +00002427 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002428 {
anthony31f1bf72012-01-30 12:37:22 +00002429 const char
2430 *format,
anthony805a2d42011-09-25 08:25:12 +00002431 *text;
2432
anthony92c93bd2012-03-19 14:02:47 +00002433 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002434 if (format == (char *) NULL)
2435 {
anthony92c93bd2012-03-19 14:02:47 +00002436 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2437 _exception);
anthony805a2d42011-09-25 08:25:12 +00002438 break;
2439 }
anthony92c93bd2012-03-19 14:02:47 +00002440 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002441 if (text == (char *) NULL)
2442 break;
2443 (void) fputs(text,stdout);
2444 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002445 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002446 break;
2447 }
anthonyafa3dfc2012-03-03 11:31:30 +00002448 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002449 {
anthonyb1e21ed2012-04-20 12:43:12 +00002450 flags=ParseGeometry(arg1,&geometry_info);
2451 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002452 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002453 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2454 _exception);
anthony805a2d42011-09-25 08:25:12 +00002455 break;
2456 }
anthonyafa3dfc2012-03-03 11:31:30 +00002457 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002458 {
anthonyfe1aa782012-03-24 13:43:04 +00002459 /* FUTURE: New to IMv7
2460 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002461 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002462 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002463 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2464 new_image=InterpolativeResizeImage(_image,geometry.width,
2465 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002466 break;
2467 }
anthonyebb73a22012-03-22 14:25:52 +00002468 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002469 }
2470 case 'l':
2471 {
anthonyafa3dfc2012-03-03 11:31:30 +00002472 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002473 {
anthonyfd706f92012-01-19 04:22:02 +00002474 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002475 if ((flags & (RhoValue|SigmaValue)) == 0)
2476 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002477 if ((flags & PercentValue) != 0)
2478 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002479 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002480 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002481 _exception);
anthony805a2d42011-09-25 08:25:12 +00002482 break;
2483 }
anthonyafa3dfc2012-03-03 11:31:30 +00002484 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002485 {
2486 MagickRealType
2487 black_point,
2488 gamma,
2489 white_point;
2490
2491 MagickStatusType
2492 flags;
2493
anthonyfd706f92012-01-19 04:22:02 +00002494 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002495 if ((flags & RhoValue) == 0)
2496 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002497 black_point=geometry_info.rho;
2498 white_point=(MagickRealType) QuantumRange;
2499 if ((flags & SigmaValue) != 0)
2500 white_point=geometry_info.sigma;
2501 gamma=1.0;
2502 if ((flags & XiValue) != 0)
2503 gamma=geometry_info.xi;
2504 if ((flags & PercentValue) != 0)
2505 {
2506 black_point*=(MagickRealType) (QuantumRange/100.0);
2507 white_point*=(MagickRealType) (QuantumRange/100.0);
2508 }
2509 if ((flags & SigmaValue) == 0)
2510 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002511 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002512 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002513 else
anthony92c93bd2012-03-19 14:02:47 +00002514 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002515 break;
2516 }
anthonyafa3dfc2012-03-03 11:31:30 +00002517 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002518 {
2519 char
2520 token[MaxTextExtent];
2521
2522 const char
2523 *p;
2524
2525 PixelInfo
2526 black_point,
2527 white_point;
2528
anthonyfd706f92012-01-19 04:22:02 +00002529 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002530 GetMagickToken(p,&p,token); /* get black point color */
2531 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002532 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002533 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002534 else
cristy269c9412011-10-13 23:41:15 +00002535 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002536 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002537 if (isalpha((int) token[0]) || (token[0] == '#'))
2538 GetMagickToken(p,&p,token);
2539 if (*token == '\0')
2540 white_point=black_point; /* set everything to that color */
2541 else
2542 {
2543 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2544 GetMagickToken(p,&p,token); /* Get white point color. */
2545 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002546 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002547 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002548 else
cristy269c9412011-10-13 23:41:15 +00002549 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002550 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002551 }
anthony92c93bd2012-03-19 14:02:47 +00002552 (void) LevelImageColors(_image,&black_point,&white_point,
2553 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002554 break;
2555 }
anthonyafa3dfc2012-03-03 11:31:30 +00002556 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002557 {
2558 double
2559 black_point,
2560 white_point;
2561
2562 MagickStatusType
2563 flags;
2564
anthonyfd706f92012-01-19 04:22:02 +00002565 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002566 if ((flags & RhoValue) == 0)
2567 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002568 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002569 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002570 if ((flags & SigmaValue) != 0)
2571 white_point=geometry_info.sigma;
2572 if ((flags & PercentValue) != 0)
2573 {
anthony92c93bd2012-03-19 14:02:47 +00002574 black_point*=(double) _image->columns*_image->rows/100.0;
2575 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002576 }
2577 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002578 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002579 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002580 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002581 break;
2582 }
anthonyafa3dfc2012-03-03 11:31:30 +00002583 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002584 {
anthonyfe1aa782012-03-24 13:43:04 +00002585 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002586 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002588 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002589 if ((flags & XValue) == 0)
2590 geometry.x=1;
2591 if ((flags & YValue) == 0)
2592 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002593 new_image=LiquidRescaleImage(_image,geometry.width,
2594 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002595 break;
2596 }
anthonyebb73a22012-03-22 14:25:52 +00002597 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002598 }
2599 case 'm':
2600 {
anthonyafa3dfc2012-03-03 11:31:30 +00002601 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002602 {
anthony464f1c42012-04-22 08:51:01 +00002603 CLIWandWarnReplaced("-remap");
anthony975a8d72012-04-12 13:54:36 +00002604 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
anthony805a2d42011-09-25 08:25:12 +00002605 break;
2606 }
anthonyafa3dfc2012-03-03 11:31:30 +00002607 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002608 {
2609 Image
2610 *mask;
2611
anthonyafa3dfc2012-03-03 11:31:30 +00002612 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002613 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002614 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002615 break;
2616 }
anthony5330ae02012-03-20 14:17:01 +00002617 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002618 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002619 if (mask == (Image *) NULL)
2620 break;
anthony92c93bd2012-03-19 14:02:47 +00002621 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002622 mask=DestroyImage(mask);
2623 break;
2624 }
anthonyafa3dfc2012-03-03 11:31:30 +00002625 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002626 {
anthony464f1c42012-04-22 08:51:01 +00002627 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
anthony92c93bd2012-03-19 14:02:47 +00002628 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2629 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002630 break;
2631 }
anthonya3ef4ed2012-03-17 06:52:53 +00002632 if (LocaleCompare("median",option+1) == 0)
2633 {
anthony464f1c42012-04-22 08:51:01 +00002634 CLIWandWarnReplaced("-statistic Median");
anthonya3ef4ed2012-03-17 06:52:53 +00002635 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2636 break;
2637 }
anthonyafa3dfc2012-03-03 11:31:30 +00002638 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002639 {
anthony975a8d72012-04-12 13:54:36 +00002640 /* FUTURE: note this is also a special "montage" option */
anthony464f1c42012-04-22 08:51:01 +00002641 CLIWandWarnReplaced("-statistic Mode");
anthony975a8d72012-04-12 13:54:36 +00002642 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
anthony805a2d42011-09-25 08:25:12 +00002643 break;
2644 }
anthonyafa3dfc2012-03-03 11:31:30 +00002645 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002646 {
anthony7bcfe7f2012-03-30 14:01:22 +00002647 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002648 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002649 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002650 break;
2651 }
anthonyafa3dfc2012-03-03 11:31:30 +00002652 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002653 {
anthony92c93bd2012-03-19 14:02:47 +00002654 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002655 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002656 break;
2657 }
anthonyafa3dfc2012-03-03 11:31:30 +00002658 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002659 {
anthony92c93bd2012-03-19 14:02:47 +00002660 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002661 break;
2662 }
anthonyafa3dfc2012-03-03 11:31:30 +00002663 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002664 {
2665 char
2666 token[MaxTextExtent];
2667
2668 const char
2669 *p;
2670
2671 KernelInfo
2672 *kernel;
2673
anthony805a2d42011-09-25 08:25:12 +00002674 ssize_t
2675 iterations;
2676
anthonyfd706f92012-01-19 04:22:02 +00002677 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002678 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002679 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2680 if ( parse < 0 )
2681 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2682 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002683 iterations=1L;
2684 GetMagickToken(p,&p,token);
2685 if ((*p == ':') || (*p == ','))
2686 GetMagickToken(p,&p,token);
2687 if ((*p != '\0'))
2688 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002689 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002690 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002691 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2692 option,arg2);
2693 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2694 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002695 kernel=DestroyKernelInfo(kernel);
2696 break;
2697 }
anthonyafa3dfc2012-03-03 11:31:30 +00002698 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002699 {
anthonyfd706f92012-01-19 04:22:02 +00002700 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002701 if ((flags & (RhoValue|SigmaValue)) == 0)
2702 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002703 if ((flags & SigmaValue) == 0)
2704 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002705 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002706 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002707 break;
2708 }
anthonyebb73a22012-03-22 14:25:52 +00002709 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002710 }
2711 case 'n':
2712 {
anthonyafa3dfc2012-03-03 11:31:30 +00002713 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002714 {
anthony92c93bd2012-03-19 14:02:47 +00002715 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002716 break;
2717 }
anthonyafa3dfc2012-03-03 11:31:30 +00002718 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002719 {
anthony975a8d72012-04-12 13:54:36 +00002720 double
2721 attenuate;
2722
2723 const char*
2724 value;
2725
anthonyafa3dfc2012-03-03 11:31:30 +00002726 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002727 {
anthony464f1c42012-04-22 08:51:01 +00002728 CLIWandWarnReplaced("-statistic NonPeak");
anthony975a8d72012-04-12 13:54:36 +00002729 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2730 break;
anthony805a2d42011-09-25 08:25:12 +00002731 }
anthony975a8d72012-04-12 13:54:36 +00002732 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2733 if ( parse < 0 )
2734 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2735 option,arg1);
2736 attenuate=1.0;
2737 value=GetImageOption(_image_info,"attenuate");
2738 if (value != (const char *) NULL)
2739 attenuate=StringToDouble(value,(char **) NULL);
2740 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2741 _exception);
anthony805a2d42011-09-25 08:25:12 +00002742 break;
2743 }
anthonyafa3dfc2012-03-03 11:31:30 +00002744 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002745 {
anthony92c93bd2012-03-19 14:02:47 +00002746 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002747 break;
2748 }
anthonyebb73a22012-03-22 14:25:52 +00002749 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002750 }
2751 case 'o':
2752 {
anthonyafa3dfc2012-03-03 11:31:30 +00002753 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002754 {
2755 PixelInfo
2756 target;
2757
anthony92c93bd2012-03-19 14:02:47 +00002758 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2759 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2760 _exception);
anthony805a2d42011-09-25 08:25:12 +00002761 break;
2762 }
anthonyafa3dfc2012-03-03 11:31:30 +00002763 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002764 {
anthony92c93bd2012-03-19 14:02:47 +00002765 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002766 break;
2767 }
anthonyebb73a22012-03-22 14:25:52 +00002768 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002769 }
2770 case 'p':
2771 {
anthonyafa3dfc2012-03-03 11:31:30 +00002772 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002773 {
anthony22de2722012-04-19 14:43:00 +00002774 flags=ParseGeometry(arg1,&geometry_info);
2775 if ((flags & (RhoValue|SigmaValue)) == 0)
2776 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002777 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2778 _exception);
anthony805a2d42011-09-25 08:25:12 +00002779 break;
2780 }
anthonyafa3dfc2012-03-03 11:31:30 +00002781 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002782 {
cristye9e3d382011-12-14 01:50:13 +00002783 const char
2784 *caption;
2785
anthony805a2d42011-09-25 08:25:12 +00002786 double
2787 angle;
2788
anthony7bc87992012-03-25 02:32:51 +00002789 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002790 RandomInfo
2791 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002792
anthonyf42014d2012-03-25 09:53:06 +00002793 random_info=AcquireRandomInfo();
2794 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2795 random_info=DestroyRandomInfo(random_info);
2796 }
anthony7bc87992012-03-25 02:32:51 +00002797 else {
anthonyf42014d2012-03-25 09:53:06 +00002798 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002799 if ((flags & RhoValue) == 0)
2800 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002801 angle=geometry_info.rho;
2802 }
anthony92c93bd2012-03-19 14:02:47 +00002803 caption=GetImageProperty(_image,"caption",_exception);
2804 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2805 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002806 break;
2807 }
anthonyafa3dfc2012-03-03 11:31:30 +00002808 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002809 {
anthony22de2722012-04-19 14:43:00 +00002810 flags=ParseGeometry(arg1,&geometry_info);
2811 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002812 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002813 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2814 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00002815 break;
2816 }
anthonyafa3dfc2012-03-03 11:31:30 +00002817 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002818 {
anthony31f1bf72012-01-30 12:37:22 +00002819 /* FUTURE: should be a 'Genesis' option?
2820 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002821 Why???
cristy947cb4c2011-10-20 18:41:46 +00002822 */
anthony7bc87992012-03-25 02:32:51 +00002823 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2824 if ( parse < 0 )
2825 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2826 option,arg1);
2827 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002828 break;
2829 }
anthonyafa3dfc2012-03-03 11:31:30 +00002830 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002831 {
2832 const char
2833 *name;
2834
2835 const StringInfo
2836 *profile;
2837
2838 Image
2839 *profile_image;
2840
2841 ImageInfo
2842 *profile_info;
2843
anthonyafa3dfc2012-03-03 11:31:30 +00002844 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002845 { /* Remove a profile from the _image. */
2846 (void) ProfileImage(_image,arg1,(const unsigned char *)
2847 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002848 break;
2849 }
anthony92c93bd2012-03-19 14:02:47 +00002850 /* Associate a profile with the _image. */
2851 profile_info=CloneImageInfo(_image_info);
2852 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002853 if (profile != (StringInfo *) NULL)
2854 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002855 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002856 profile_info=DestroyImageInfo(profile_info);
2857 if (profile_image == (Image *) NULL)
2858 {
2859 StringInfo
2860 *profile;
2861
anthony92c93bd2012-03-19 14:02:47 +00002862 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002863 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002864 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002865 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002866 if (profile != (StringInfo *) NULL)
2867 {
anthony92c93bd2012-03-19 14:02:47 +00002868 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002869 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002870 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002871 profile=DestroyStringInfo(profile);
2872 }
2873 profile_info=DestroyImageInfo(profile_info);
2874 break;
2875 }
2876 ResetImageProfileIterator(profile_image);
2877 name=GetNextImageProfile(profile_image);
2878 while (name != (const char *) NULL)
2879 {
2880 profile=GetImageProfile(profile_image,name);
2881 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002882 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2883 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002884 name=GetNextImageProfile(profile_image);
2885 }
2886 profile_image=DestroyImage(profile_image);
2887 break;
2888 }
anthonyebb73a22012-03-22 14:25:52 +00002889 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002890 }
anthony805a2d42011-09-25 08:25:12 +00002891 case 'r':
2892 {
anthonyafa3dfc2012-03-03 11:31:30 +00002893 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002894 {
anthonyfd706f92012-01-19 04:22:02 +00002895 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002896 if ((flags & RhoValue) == 0)
2897 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyaa2c16c2012-03-25 22:21:35 +00002898 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002899 break;
2900 }
anthonyafa3dfc2012-03-03 11:31:30 +00002901 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002902 {
anthony7bcfe7f2012-03-30 14:01:22 +00002903 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002904 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002905 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002906 if ((flags & SigmaValue) == 0)
2907 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00002908 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002909 break;
2910 }
anthonyafa3dfc2012-03-03 11:31:30 +00002911 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002912 {
anthony7bcfe7f2012-03-30 14:01:22 +00002913 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002914 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002915 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002916 break;
2917 }
anthony975a8d72012-04-12 13:54:36 +00002918 if (LocaleCompare("recolor",option+1) == 0)
2919 {
anthony464f1c42012-04-22 08:51:01 +00002920 CLIWandWarnReplaced("-color-matrix");
anthony975a8d72012-04-12 13:54:36 +00002921 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2922 }
anthonyafa3dfc2012-03-03 11:31:30 +00002923 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002924 {
2925 Image
2926 *remap_image;
2927
anthony92c93bd2012-03-19 14:02:47 +00002928 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002929 if (remap_image == (Image *) NULL)
2930 break;
anthony92c93bd2012-03-19 14:02:47 +00002931 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002932 remap_image=DestroyImage(remap_image);
2933 break;
2934 }
anthonyafa3dfc2012-03-03 11:31:30 +00002935 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002936 {
anthonyafa3dfc2012-03-03 11:31:30 +00002937 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00002938 {
anthony7bcfe7f2012-03-30 14:01:22 +00002939 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00002940 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
2941 arg1);
2942 (void) ResetImagePage(_image,arg1);
2943 }
anthony31f1bf72012-01-30 12:37:22 +00002944 else
anthony92c93bd2012-03-19 14:02:47 +00002945 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00002946 break;
2947 }
anthonyafa3dfc2012-03-03 11:31:30 +00002948 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002949 {
anthonyf46d4262012-03-26 03:30:34 +00002950 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00002951 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002952 if ((flags & (RhoValue|SigmaValue)) == 0)
2953 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002954 if ((flags & SigmaValue) == 0)
2955 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002956 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002957 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002958 break;
2959 }
anthonyafa3dfc2012-03-03 11:31:30 +00002960 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002961 {
anthony7bcfe7f2012-03-30 14:01:22 +00002962 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002963 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002964 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2965 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002966 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002967 break;
2968 }
anthonyafa3dfc2012-03-03 11:31:30 +00002969 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002970 {
anthony7bcfe7f2012-03-30 14:01:22 +00002971 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002972 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002973 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2974 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002975 break;
2976 }
anthonyafa3dfc2012-03-03 11:31:30 +00002977 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002978 {
anthony22de2722012-04-19 14:43:00 +00002979 flags=ParseGeometry(arg1,&geometry_info);
2980 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00002981 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00002982 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00002983 break;
2984 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
2985 break;
anthony92c93bd2012-03-19 14:02:47 +00002986 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002987 break;
2988 }
anthonyebb73a22012-03-22 14:25:52 +00002989 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002990 }
2991 case 's':
2992 {
anthonyafa3dfc2012-03-03 11:31:30 +00002993 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002994 {
anthonyfe1aa782012-03-24 13:43:04 +00002995 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002996 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002997 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002998 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2999 new_image=SampleImage(_image,geometry.width,geometry.height,
3000 _exception);
anthony805a2d42011-09-25 08:25:12 +00003001 break;
3002 }
anthonyafa3dfc2012-03-03 11:31:30 +00003003 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003004 {
anthonyfe1aa782012-03-24 13:43:04 +00003005 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003006 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003007 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003008 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3009 new_image=ScaleImage(_image,geometry.width,geometry.height,
3010 _exception);
anthony805a2d42011-09-25 08:25:12 +00003011 break;
3012 }
anthonyf42014d2012-03-25 09:53:06 +00003013 if (LocaleCompare("segment",option+1) == 0)
3014 {
anthonyf42014d2012-03-25 09:53:06 +00003015 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003016 if ((flags & (RhoValue|SigmaValue)) == 0)
3017 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003018 if ((flags & SigmaValue) == 0)
3019 geometry_info.sigma=1.0;
3020 (void) SegmentImage(_image,_image->colorspace,
3021 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3022 _exception);
3023 break;
3024 }
anthonyafa3dfc2012-03-03 11:31:30 +00003025 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003026 {
anthonyfd706f92012-01-19 04:22:02 +00003027 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003028 if ((flags & (RhoValue|SigmaValue)) == 0)
3029 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3030 if ((flags & SigmaValue) == 0)
3031 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003032 if ((flags & PercentValue) != 0)
3033 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003034 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003035 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003036 break;
3037 }
anthonyafa3dfc2012-03-03 11:31:30 +00003038 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003039 {
anthony31f1bf72012-01-30 12:37:22 +00003040 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003041 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003042 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003043 break;
3044 }
anthonyafa3dfc2012-03-03 11:31:30 +00003045 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003046 {
anthony7bcfe7f2012-03-30 14:01:22 +00003047 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003048 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3049 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3050 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003051 break;
3052 }
anthonyafa3dfc2012-03-03 11:31:30 +00003053 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003054 {
3055 char
3056 *value;
3057
anthonyf42014d2012-03-25 09:53:06 +00003058 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003059 if (LocaleNCompare(arg1,"registry:",9) == 0)
3060 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003061 else
anthony31f1bf72012-01-30 12:37:22 +00003062 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003063 {
anthony92c93bd2012-03-19 14:02:47 +00003064 (void) DeleteImageOption(_image_info,arg1+7);
3065 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003066 }
3067 else
anthony92c93bd2012-03-19 14:02:47 +00003068 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003069 break;
3070 }
anthonyf42014d2012-03-25 09:53:06 +00003071 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003072 if (value == (char *) NULL)
3073 break;
anthonyfd706f92012-01-19 04:22:02 +00003074 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003075 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003076 else
anthonyfd706f92012-01-19 04:22:02 +00003077 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003078 {
anthony92c93bd2012-03-19 14:02:47 +00003079 (void) SetImageOption(_image_info,arg1+7,value);
3080 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003081 }
3082 else
anthony92c93bd2012-03-19 14:02:47 +00003083 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003084 value=DestroyString(value);
3085 break;
3086 }
anthonyafa3dfc2012-03-03 11:31:30 +00003087 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003088 {
anthonyfd706f92012-01-19 04:22:02 +00003089 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003090 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3091 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003092 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3093 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003094 break;
3095 }
anthonyafa3dfc2012-03-03 11:31:30 +00003096 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003097 {
anthonyfd706f92012-01-19 04:22:02 +00003098 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003099 if ((flags & (RhoValue|SigmaValue)) == 0)
3100 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003101 if ((flags & SigmaValue) == 0)
3102 geometry_info.sigma=1.0;
3103 if ((flags & XiValue) == 0)
3104 geometry_info.xi=4.0;
3105 if ((flags & PsiValue) == 0)
3106 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003107 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3108 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3109 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003110 break;
3111 }
anthonyafa3dfc2012-03-03 11:31:30 +00003112 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003113 {
anthonyfd706f92012-01-19 04:22:02 +00003114 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003115 if ((flags & (RhoValue|SigmaValue)) == 0)
3116 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003117 if ((flags & SigmaValue) == 0)
3118 geometry_info.sigma=1.0;
3119 if ((flags & XiValue) == 0)
3120 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003121 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3122 _exception);
anthony805a2d42011-09-25 08:25:12 +00003123 break;
3124 }
anthonyafa3dfc2012-03-03 11:31:30 +00003125 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003126 {
anthony7bcfe7f2012-03-30 14:01:22 +00003127 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003128 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003129 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3130 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003131 break;
3132 }
anthonyafa3dfc2012-03-03 11:31:30 +00003133 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003134 {
anthonyfd706f92012-01-19 04:22:02 +00003135 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003136 if ((flags & RhoValue) == 0)
3137 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003138 if ((flags & SigmaValue) == 0)
3139 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003140 new_image=ShearImage(_image,geometry_info.rho,
3141 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003142 break;
3143 }
anthonyafa3dfc2012-03-03 11:31:30 +00003144 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003145 {
anthonyfd706f92012-01-19 04:22:02 +00003146 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003147 if ((flags & RhoValue) == 0)
3148 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003149 if ((flags & SigmaValue) == 0)
3150 geometry_info.sigma=(double) QuantumRange/2.0;
3151 if ((flags & PercentValue) != 0)
3152 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3153 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003154 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003155 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003156 break;
3157 }
anthonyafa3dfc2012-03-03 11:31:30 +00003158 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003159 {
anthonyfd706f92012-01-19 04:22:02 +00003160 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003161 if ((flags & (RhoValue|SigmaValue)) == 0)
3162 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003163 if ((flags & SigmaValue) == 0)
3164 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003165 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003166 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003167 break;
3168 }
anthonyafa3dfc2012-03-03 11:31:30 +00003169 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003170 {
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) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3174 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003175 break;
3176 }
anthonyafa3dfc2012-03-03 11:31:30 +00003177 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003178 {
anthony805a2d42011-09-25 08:25:12 +00003179 char
3180 *arguments;
3181
anthonyf42014d2012-03-25 09:53:06 +00003182 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3183 if ( parse < 0 )
3184 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3185 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003186 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003187 if (arguments == (char *) NULL)
anthonyf42014d2012-03-25 09:53:06 +00003188 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3189 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3190 arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003191 arguments=DestroyString(arguments);
3192 break;
3193 }
anthonyafa3dfc2012-03-03 11:31:30 +00003194 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003195 {
anthony7bcfe7f2012-03-30 14:01:22 +00003196 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003198 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003199 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003200 break;
3201 }
anthonyafa3dfc2012-03-03 11:31:30 +00003202 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003203 {
anthonyb1e21ed2012-04-20 12:43:12 +00003204 flags=ParseGeometry(arg1,&geometry_info);
3205 if ((flags & RhoValue) == 0)
3206 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003207 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3208 _exception);
anthony805a2d42011-09-25 08:25:12 +00003209 break;
3210 }
anthonyafa3dfc2012-03-03 11:31:30 +00003211 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003212 {
anthony7bc87992012-03-25 02:32:51 +00003213 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3214 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003215 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003216 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003217 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003218 if ((flags & RhoValue) == 0)
3219 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003220 if ((flags & SigmaValue) == 0)
3221 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003222 new_image=StatisticImage(_image,(StatisticType)parse,
3223 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3224 _exception);
anthony805a2d42011-09-25 08:25:12 +00003225 break;
3226 }
anthonyafa3dfc2012-03-03 11:31:30 +00003227 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003228 {
anthony92c93bd2012-03-19 14:02:47 +00003229 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003230 break;
3231 }
anthonyafa3dfc2012-03-03 11:31:30 +00003232 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003233 {
anthonyb1e21ed2012-04-20 12:43:12 +00003234 flags=ParseGeometry(arg2,&geometry_info);
3235 if ((flags & RhoValue) == 0)
3236 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003237 new_image=SwirlImage(_image,geometry_info.rho,
3238 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003239 break;
3240 }
anthonyebb73a22012-03-22 14:25:52 +00003241 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003242 }
3243 case 't':
3244 {
anthonyafa3dfc2012-03-03 11:31:30 +00003245 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003246 {
3247 double
3248 threshold;
3249
anthony52bef752012-03-27 13:54:47 +00003250 threshold=(double) QuantumRange/2;
3251 if (normal_op) {
anthony7bcfe7f2012-03-30 14:01:22 +00003252 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003253 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003254 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003255 }
anthony92c93bd2012-03-19 14:02:47 +00003256 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003257 break;
3258 }
anthonyafa3dfc2012-03-03 11:31:30 +00003259 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003260 {
anthony7bcfe7f2012-03-30 14:01:22 +00003261 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003262 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003263 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3264 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3265 _exception);
anthony805a2d42011-09-25 08:25:12 +00003266 break;
3267 }
anthonyafa3dfc2012-03-03 11:31:30 +00003268 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003269 {
anthony7bcfe7f2012-03-30 14:01:22 +00003270 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003271 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003272 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003273 break;
3274 }
anthonyafa3dfc2012-03-03 11:31:30 +00003275 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003276 {
anthony464f1c42012-04-22 08:51:01 +00003277 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003278 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003279 break;
3280 }
anthonyafa3dfc2012-03-03 11:31:30 +00003281 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003282 {
3283 PixelInfo
3284 target;
3285
anthony92c93bd2012-03-19 14:02:47 +00003286 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3287 (void) TransparentPaintImage(_image,&target,(Quantum)
3288 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003289 break;
3290 }
anthonyafa3dfc2012-03-03 11:31:30 +00003291 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003292 {
anthony92c93bd2012-03-19 14:02:47 +00003293 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003294 break;
3295 }
anthonyafa3dfc2012-03-03 11:31:30 +00003296 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003297 {
anthony92c93bd2012-03-19 14:02:47 +00003298 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003299 break;
3300 }
anthonyafa3dfc2012-03-03 11:31:30 +00003301 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003302 {
anthony92c93bd2012-03-19 14:02:47 +00003303 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003304 break;
3305 }
anthonyafa3dfc2012-03-03 11:31:30 +00003306 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003307 {
anthonyab3a50c2011-10-27 11:48:57 +00003308 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003309 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003310 break;
3311 }
anthonyebb73a22012-03-22 14:25:52 +00003312 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003313 }
3314 case 'u':
3315 {
anthonyafa3dfc2012-03-03 11:31:30 +00003316 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003317 {
anthony52bef752012-03-27 13:54:47 +00003318 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3319 Option is not documented, bt appears to be for "identify".
3320 We may need a identify specific verbose!
3321 */
3322 if (plus_alt_op) {
anthony92c93bd2012-03-19 14:02:47 +00003323 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003324 break;
3325 }
anthony92c93bd2012-03-19 14:02:47 +00003326 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3327 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003328 break;
3329 }
anthonyafa3dfc2012-03-03 11:31:30 +00003330 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003331 {
anthony92c93bd2012-03-19 14:02:47 +00003332 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003333 break;
3334 }
anthonyafa3dfc2012-03-03 11:31:30 +00003335 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003336 {
anthonyfd706f92012-01-19 04:22:02 +00003337 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003338 if ((flags & (RhoValue|SigmaValue)) == 0)
3339 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003340 if ((flags & SigmaValue) == 0)
3341 geometry_info.sigma=1.0;
3342 if ((flags & XiValue) == 0)
3343 geometry_info.xi=1.0;
3344 if ((flags & PsiValue) == 0)
3345 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003346 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3347 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003348 break;
3349 }
anthonyebb73a22012-03-22 14:25:52 +00003350 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003351 }
3352 case 'v':
3353 {
anthonyafa3dfc2012-03-03 11:31:30 +00003354 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003355 {
anthonyafa3dfc2012-03-03 11:31:30 +00003356 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003357 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003358 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003359 */
anthony92c93bd2012-03-19 14:02:47 +00003360 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003361 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003362 break;
3363 }
anthonyafa3dfc2012-03-03 11:31:30 +00003364 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003365 {
anthonyfd706f92012-01-19 04:22:02 +00003366 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003367 if ((flags & (RhoValue|SigmaValue)) == 0)
3368 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003369 if ((flags & SigmaValue) == 0)
3370 geometry_info.sigma=1.0;
3371 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003372 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003373 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003374 geometry_info.psi=0.1*_image->rows;
3375 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003376 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3377 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003378 break;
3379 }
anthonyebb73a22012-03-22 14:25:52 +00003380 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003381 }
3382 case 'w':
3383 {
anthonyafa3dfc2012-03-03 11:31:30 +00003384 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003385 {
anthonyfd706f92012-01-19 04:22:02 +00003386 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003387 if ((flags & (RhoValue|SigmaValue)) == 0)
3388 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003389 if ((flags & SigmaValue) == 0)
3390 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003391 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3392 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003393 break;
3394 }
anthonyafa3dfc2012-03-03 11:31:30 +00003395 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003396 {
anthony7bcfe7f2012-03-30 14:01:22 +00003397 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003398 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003399 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003400 break;
3401 }
anthonyebb73a22012-03-22 14:25:52 +00003402 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003403 }
3404 default:
anthonyebb73a22012-03-22 14:25:52 +00003405 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003406 }
3407 /*
3408 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003409 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003410 */
3411 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003412 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003413
anthony31f1bf72012-01-30 12:37:22 +00003414 return;
anthony92c93bd2012-03-19 14:02:47 +00003415#undef _image_info
3416#undef _draw_info
3417#undef _quantize_info
3418#undef _image
3419#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003420#undef IfNormalOp
3421#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003422#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003423#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003424}
anthonyfd706f92012-01-19 04:22:02 +00003425
anthony43f425d2012-02-26 12:58:58 +00003426WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003427 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003428{
3429 size_t
anthony43f425d2012-02-26 12:58:58 +00003430 n,
anthony31f1bf72012-01-30 12:37:22 +00003431 i;
3432
anthony43f425d2012-02-26 12:58:58 +00003433 assert(cli_wand != (MagickCLI *) NULL);
3434 assert(cli_wand->signature == WandSignature);
3435 assert(cli_wand->wand.signature == WandSignature);
3436 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003437 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003438 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003439
anthonyafa3dfc2012-03-03 11:31:30 +00003440#if !USE_WAND_METHODS
3441 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003442 i=0;
anthony43f425d2012-02-26 12:58:58 +00003443 n=GetImageListLength(cli_wand->wand.images);
3444 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003445 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003446 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003447 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003448 if ( cli_wand->wand.images->next == (Image *) NULL )
3449 break;
3450 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003451 }
anthony43f425d2012-02-26 12:58:58 +00003452 assert( i == n );
3453 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003454#else
3455 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003456 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003457 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3458 MagickResetIterator(&cli_wand->wand);
3459#endif
anthony31f1bf72012-01-30 12:37:22 +00003460 return;
anthony805a2d42011-09-25 08:25:12 +00003461}
3462
3463/*
3464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3465% %
3466% %
3467% %
anthony43f425d2012-02-26 12:58:58 +00003468+ 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 +00003469% %
3470% %
3471% %
3472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3473%
anthony43f425d2012-02-26 12:58:58 +00003474% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003475% entire image list as a whole. The result is often a complete replacment
3476% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003477%
3478% The format of the MogrifyImage method is:
3479%
anthony43f425d2012-02-26 12:58:58 +00003480% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003481% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003482%
3483% A description of each parameter follows:
3484%
anthony43f425d2012-02-26 12:58:58 +00003485% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003486%
anthony36a8c2c2012-02-10 00:08:44 +00003487% o option: The option string for the operation
3488%
anthony31f1bf72012-01-30 12:37:22 +00003489% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003490% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003491%
anthony805a2d42011-09-25 08:25:12 +00003492*/
anthony43f425d2012-02-26 12:58:58 +00003493WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +00003494 const char *option,const char *arg1, const char *magick_unused(arg2))
anthony805a2d42011-09-25 08:25:12 +00003495{
anthony2a0ec8c2012-03-24 04:35:56 +00003496 ssize_t
3497 parse;
3498
anthony31f1bf72012-01-30 12:37:22 +00003499 Image
3500 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003501
anthony2e4501b2012-03-30 04:41:54 +00003502#define _image_info (cli_wand->wand.image_info)
3503#define _images (cli_wand->wand.images)
3504#define _exception (cli_wand->wand.exception)
3505#define _draw_info (cli_wand->draw_info)
3506#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003507#define IfNormalOp (*option=='-')
3508#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00003509#define normal_op IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003510
anthony43f425d2012-02-26 12:58:58 +00003511 assert(cli_wand != (MagickCLI *) NULL);
3512 assert(cli_wand->signature == WandSignature);
3513 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003514 assert(_images != (Image *) NULL); /* _images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003515 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003516 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003517
anthony31f1bf72012-01-30 12:37:22 +00003518 new_images=NewImageList();
3519
anthonyafa3dfc2012-03-03 11:31:30 +00003520 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003521 {
3522 case 'a':
3523 {
anthonyafa3dfc2012-03-03 11:31:30 +00003524 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003525 {
anthony92c93bd2012-03-19 14:02:47 +00003526 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003527 break;
3528 }
anthonyafa3dfc2012-03-03 11:31:30 +00003529 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003530 {
anthony464f1c42012-04-22 08:51:01 +00003531 CLIWandWarnReplaced("-evaluate-sequence Mean");
anthonyafa3dfc2012-03-03 11:31:30 +00003532 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003533 break;
3534 }
anthonyebb73a22012-03-22 14:25:52 +00003535 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003536 }
3537 case 'c':
3538 {
cristy5f257b22012-03-07 00:27:29 +00003539 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003540 {
anthony92c93bd2012-03-19 14:02:47 +00003541 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003542 break;
3543 }
anthonyafa3dfc2012-03-03 11:31:30 +00003544 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003545 {
anthony805a2d42011-09-25 08:25:12 +00003546 Image
anthony31f1bf72012-01-30 12:37:22 +00003547 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003548
anthonyafa3dfc2012-03-03 11:31:30 +00003549 /* FUTURE - make this a compose option, and thus can be used
3550 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003551 _images.
cristy87c02f42012-02-24 00:19:10 +00003552 */
anthony92c93bd2012-03-19 14:02:47 +00003553 new_images=RemoveFirstImageFromList(&_images);
3554 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003555 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003556 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003557 break;
cristye52fb5e2012-04-06 23:30:20 +00003558 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003559 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003560 break;
3561 }
anthonyafa3dfc2012-03-03 11:31:30 +00003562 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003563 {
anthony92c93bd2012-03-19 14:02:47 +00003564 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003565 break;
3566 }
anthonyafa3dfc2012-03-03 11:31:30 +00003567 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003568 {
anthony43f425d2012-02-26 12:58:58 +00003569 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003570 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003571 break;
3572 }
anthonyafa3dfc2012-03-03 11:31:30 +00003573 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003574 {
cristyfeb3e962012-03-29 17:25:55 +00003575 CompositeOperator
3576 compose;
3577
3578 const char*
3579 value;
3580
3581 MagickBooleanType
3582 clip_to_self;
3583
anthony805a2d42011-09-25 08:25:12 +00003584 Image
3585 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003586 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003587
3588 RectangleInfo
3589 geometry;
3590
anthony7bcfe7f2012-03-30 14:01:22 +00003591 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003592 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003593 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003594 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003595 else
3596 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3597 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003598
anthony7bcfe7f2012-03-30 14:01:22 +00003599 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003600 value=GetImageOption(_image_info,"compose:clip-to-self");
3601 if (value == (const char *) NULL)
3602 clip_to_self=MagickTrue;
3603 else
3604 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3605 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003606 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003607 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003608 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003609 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003610 }
3611
anthony92c93bd2012-03-19 14:02:47 +00003612 new_images=RemoveFirstImageFromList(&_images);
3613 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003614 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003615 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003616
anthony31f1bf72012-01-30 12:37:22 +00003617 /* FUTURE - this should not be here! - should be part of -geometry */
3618 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003619 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003620
anthony31f1bf72012-01-30 12:37:22 +00003621 SetGeometry(source_image,&geometry);
3622 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3623 GravityAdjustGeometry(new_images->columns,new_images->rows,
3624 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003625
anthony92c93bd2012-03-19 14:02:47 +00003626 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003627 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003628 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003629 if ((compose == DisplaceCompositeOp) ||
anthony7bcfe7f2012-03-30 14:01:22 +00003630 (compose == DistortCompositeOp)) {
3631 /* Merge Y displacement into X displace/distort map. */
3632 (void) CompositeImage(source_image,mask_image,
3633 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3634 mask_image=DestroyImage(mask_image);
3635 }
3636 else {
3637 /* Set a blending mask for the composition. */
3638 (void) NegateImage(mask_image,MagickFalse,_exception);
3639 (void) SetImageMask(new_images,mask_image,_exception);
3640 mask_image=DestroyImage(mask_image);
3641 }
anthony805a2d42011-09-25 08:25:12 +00003642 }
cristyfeb3e962012-03-29 17:25:55 +00003643 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3644 geometry.x,geometry.y,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003645 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003646 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003647 break;
3648 }
anthonyebb73a22012-03-22 14:25:52 +00003649 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003650 }
3651 case 'd':
3652 {
anthonyafa3dfc2012-03-03 11:31:30 +00003653 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003654 {
anthony464f1c42012-04-22 08:51:01 +00003655 CLIWandWarnReplaced("-layer CompareAny");
anthonyafa3dfc2012-03-03 11:31:30 +00003656 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003657 break;
3658 }
anthonyafa3dfc2012-03-03 11:31:30 +00003659 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003660 {
anthonyafa3dfc2012-03-03 11:31:30 +00003661 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003662 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003663 else
anthony92c93bd2012-03-19 14:02:47 +00003664 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003665 break;
3666 }
anthonyafa3dfc2012-03-03 11:31:30 +00003667 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003668 {
anthonyafa3dfc2012-03-03 11:31:30 +00003669 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003670 {
3671 const char
3672 *p;
3673
3674 size_t
3675 number_duplicates;
3676
anthony7bcfe7f2012-03-30 14:01:22 +00003677 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003678 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3679 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003680 number_duplicates=(size_t) StringToLong(arg1);
3681 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003682 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003683 new_images=DuplicateImages(_images,number_duplicates,"-1",
3684 _exception);
anthony805a2d42011-09-25 08:25:12 +00003685 else
anthony92c93bd2012-03-19 14:02:47 +00003686 new_images=DuplicateImages(_images,number_duplicates,p,
3687 _exception);
anthony805a2d42011-09-25 08:25:12 +00003688 }
anthonyafa3dfc2012-03-03 11:31:30 +00003689 else
anthony92c93bd2012-03-19 14:02:47 +00003690 new_images=DuplicateImages(_images,1,"-1",_exception);
3691 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003692 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003693 break;
3694 }
anthonyebb73a22012-03-22 14:25:52 +00003695 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003696 }
3697 case 'e':
3698 {
anthonyafa3dfc2012-03-03 11:31:30 +00003699 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003700 {
anthony2a0ec8c2012-03-24 04:35:56 +00003701 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3702 if ( parse < 0 )
3703 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3704 option,arg1);
3705 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3706 _exception);
anthony805a2d42011-09-25 08:25:12 +00003707 break;
3708 }
anthonyebb73a22012-03-22 14:25:52 +00003709 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003710 }
3711 case 'f':
3712 {
anthonyafa3dfc2012-03-03 11:31:30 +00003713 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003714 {
anthony92c93bd2012-03-19 14:02:47 +00003715 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003716 break;
3717 }
anthonyafa3dfc2012-03-03 11:31:30 +00003718 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003719 {
anthony319dac62012-03-06 04:12:44 +00003720 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003721 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003722 break;
3723 }
anthonyafa3dfc2012-03-03 11:31:30 +00003724 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003725 {
anthony92c93bd2012-03-19 14:02:47 +00003726 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003727 break;
3728 }
anthonyebb73a22012-03-22 14:25:52 +00003729 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003730 }
3731 case 'h':
3732 {
anthonyafa3dfc2012-03-03 11:31:30 +00003733 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003734 {
anthony31f1bf72012-01-30 12:37:22 +00003735 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003736 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003737 */
anthony805a2d42011-09-25 08:25:12 +00003738 Image
anthony31f1bf72012-01-30 12:37:22 +00003739 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003740
anthony92c93bd2012-03-19 14:02:47 +00003741 new_images=RemoveFirstImageFromList(&_images);
3742 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003743 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003744 break;
anthony92c93bd2012-03-19 14:02:47 +00003745 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003746 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003747 break;
3748 }
anthonyebb73a22012-03-22 14:25:52 +00003749 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003750 }
3751 case 'i':
3752 {
anthonyafa3dfc2012-03-03 11:31:30 +00003753 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003754 {
3755 Image
anthony805a2d42011-09-25 08:25:12 +00003756 *magnitude_image,
3757 *phase_image;
3758
anthony92c93bd2012-03-19 14:02:47 +00003759 magnitude_image=RemoveFirstImageFromList(&_images);
3760 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003761 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003762 if (phase_image == (Image *) NULL)
3763 break;
3764 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003765 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003766 magnitude_image=DestroyImage(magnitude_image);
3767 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003768 break;
3769 }
anthonyafa3dfc2012-03-03 11:31:30 +00003770 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003771 {
3772 Image
anthony31f1bf72012-01-30 12:37:22 +00003773 *insert_image,
3774 *index_image;
3775
3776 ssize_t
3777 index;
anthony805a2d42011-09-25 08:25:12 +00003778
anthony7bcfe7f2012-03-30 14:01:22 +00003779 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00003780 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003781 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003782 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003783 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003784 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003785 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003786 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003787 PrependImageToList(&_images,insert_image);
3788 else if (index == (ssize_t) GetImageListLength(_images))
3789 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003790 else
anthony43f425d2012-02-26 12:58:58 +00003791 {
anthony92c93bd2012-03-19 14:02:47 +00003792 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003793 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003794 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003795 InsertImageInList(&index_image,insert_image);
3796 }
anthony92c93bd2012-03-19 14:02:47 +00003797 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003798 break;
3799 }
anthonyebb73a22012-03-22 14:25:52 +00003800 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003801 }
3802 case 'l':
3803 {
anthonyafa3dfc2012-03-03 11:31:30 +00003804 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003805 {
anthonyfe1aa782012-03-24 13:43:04 +00003806 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3807 if ( parse < 0 )
3808 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3809 option,arg1);
3810 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003811 {
3812 case CoalesceLayer:
3813 {
anthony92c93bd2012-03-19 14:02:47 +00003814 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003815 break;
3816 }
3817 case CompareAnyLayer:
3818 case CompareClearLayer:
3819 case CompareOverlayLayer:
3820 default:
3821 {
anthonyfe1aa782012-03-24 13:43:04 +00003822 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
3823 _exception);
anthony805a2d42011-09-25 08:25:12 +00003824 break;
3825 }
3826 case MergeLayer:
3827 case FlattenLayer:
3828 case MosaicLayer:
3829 case TrimBoundsLayer:
3830 {
anthonyfe1aa782012-03-24 13:43:04 +00003831 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
3832 _exception);
anthony805a2d42011-09-25 08:25:12 +00003833 break;
3834 }
3835 case DisposeLayer:
3836 {
anthony92c93bd2012-03-19 14:02:47 +00003837 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003838 break;
3839 }
3840 case OptimizeImageLayer:
3841 {
anthony92c93bd2012-03-19 14:02:47 +00003842 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003843 break;
3844 }
3845 case OptimizePlusLayer:
3846 {
anthony92c93bd2012-03-19 14:02:47 +00003847 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003848 break;
3849 }
3850 case OptimizeTransLayer:
3851 {
anthony92c93bd2012-03-19 14:02:47 +00003852 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003853 break;
3854 }
3855 case RemoveDupsLayer:
3856 {
anthony92c93bd2012-03-19 14:02:47 +00003857 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003858 break;
3859 }
3860 case RemoveZeroLayer:
3861 {
anthony92c93bd2012-03-19 14:02:47 +00003862 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003863 break;
3864 }
3865 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003866 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003867 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003868 if (new_images == (Image *) NULL)
3869 break;
anthony92c93bd2012-03-19 14:02:47 +00003870 _images=DestroyImageList(_images);
3871 _images=OptimizeImageLayers(new_images,_exception);
3872 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003873 break;
3874 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003875 OptimizeImageTransparency(_images,_exception);
3876 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3877 _exception);
anthony805a2d42011-09-25 08:25:12 +00003878 break;
3879 }
3880 case CompositeLayer:
3881 {
anthony805a2d42011-09-25 08:25:12 +00003882 Image
3883 *source;
3884
3885 RectangleInfo
3886 geometry;
3887
anthony31f1bf72012-01-30 12:37:22 +00003888 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003889 compose;
3890
3891 const char*
3892 value;
3893
anthony92c93bd2012-03-19 14:02:47 +00003894 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003895 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003896 if (value != (const char *) NULL)
3897 compose=(CompositeOperator) ParseCommandOption(
3898 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003899
anthony31f1bf72012-01-30 12:37:22 +00003900 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00003901 source=_images;
anthony805a2d42011-09-25 08:25:12 +00003902 while (source != (Image *) NULL)
3903 {
3904 source=GetNextImageInList(source);
3905 if ((source != (Image *) NULL) &&
3906 (LocaleCompare(source->magick,"NULL") == 0))
3907 break;
3908 }
3909 if (source != (Image *) NULL)
3910 {
3911 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3912 (GetNextImageInList(source) == (Image *) NULL))
3913 source=(Image *) NULL;
3914 else
anthony31f1bf72012-01-30 12:37:22 +00003915 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003916 source=SplitImageList(source->previous);
3917 DeleteImageFromList(&source);
3918 }
3919 }
3920 if (source == (Image *) NULL)
3921 {
anthony92c93bd2012-03-19 14:02:47 +00003922 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00003923 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003924 break;
3925 }
anthony31f1bf72012-01-30 12:37:22 +00003926 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00003927 SetGeometry(_images,&geometry);
3928 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003929 geometry.width=source->page.width != 0 ?
3930 source->page.width : source->columns;
3931 geometry.height=source->page.height != 0 ?
3932 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00003933 GravityAdjustGeometry(_images->page.width != 0 ?
3934 _images->page.width : _images->columns,
3935 _images->page.height != 0 ? _images->page.height :
3936 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003937
anthony31f1bf72012-01-30 12:37:22 +00003938 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00003939 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
3940 _exception);
anthony805a2d42011-09-25 08:25:12 +00003941 source=DestroyImageList(source);
3942 break;
3943 }
3944 }
anthony805a2d42011-09-25 08:25:12 +00003945 break;
3946 }
anthonyebb73a22012-03-22 14:25:52 +00003947 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003948 }
3949 case 'm':
3950 {
anthonyafa3dfc2012-03-03 11:31:30 +00003951 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003952 {
anthony464f1c42012-04-22 08:51:01 +00003953 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00003954 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003955 break;
3956 }
anthonyafa3dfc2012-03-03 11:31:30 +00003957 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003958 {
3959 Image
3960 *morph_image;
3961
anthony7bcfe7f2012-03-30 14:01:22 +00003962 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00003963 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003964 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
3965 _exception);
anthony805a2d42011-09-25 08:25:12 +00003966 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003967 break;
anthony92c93bd2012-03-19 14:02:47 +00003968 _images=DestroyImageList(_images);
3969 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00003970 break;
3971 }
anthonyafa3dfc2012-03-03 11:31:30 +00003972 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003973 {
anthony319dac62012-03-06 04:12:44 +00003974 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00003975 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003976 break;
3977 }
anthonyebb73a22012-03-22 14:25:52 +00003978 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003979 }
3980 case 'p':
3981 {
anthonyafa3dfc2012-03-03 11:31:30 +00003982 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003983 {
3984 char
3985 *string;
3986
anthony92c93bd2012-03-19 14:02:47 +00003987 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003988 if (string == (char *) NULL)
3989 break;
3990 (void) FormatLocaleFile(stdout,"%s",string);
3991 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00003992 break;
anthony805a2d42011-09-25 08:25:12 +00003993 }
anthonyafa3dfc2012-03-03 11:31:30 +00003994 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003995 {
anthonyb1d483a2012-04-14 12:53:56 +00003996 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00003997 char
3998 **arguments;
3999
4000 int
4001 j,
4002 number_arguments;
4003
anthony31f1bf72012-01-30 12:37:22 +00004004 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004005 if (arguments == (char **) NULL)
4006 break;
anthony31f1bf72012-01-30 12:37:22 +00004007 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004008 {
4009 char
4010 breaker,
4011 quote,
4012 *token;
4013
4014 const char
4015 *arguments;
4016
4017 int
4018 next,
4019 status;
4020
4021 size_t
4022 length;
4023
4024 TokenInfo
4025 *token_info;
4026
4027 /*
anthony24aa8822012-03-11 00:56:06 +00004028 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004029 */
anthony31f1bf72012-01-30 12:37:22 +00004030 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004031 token=(char *) NULL;
4032 if (~length >= (MaxTextExtent-1))
4033 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4034 sizeof(*token));
4035 if (token == (char *) NULL)
4036 break;
4037 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004038 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004039 token_info=AcquireTokenInfo();
4040 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4041 "\"",'\0',&breaker,&next,&quote);
4042 token_info=DestroyTokenInfo(token_info);
4043 if (status == 0)
4044 {
4045 const char
4046 *argv;
4047
4048 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004049 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4050 _exception);
anthony805a2d42011-09-25 08:25:12 +00004051 }
4052 token=DestroyString(token);
4053 break;
4054 }
4055 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004056 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4057 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004058 for (j=0; j < number_arguments; j++)
4059 arguments[j]=DestroyString(arguments[j]);
4060 arguments=(char **) RelinquishMagickMemory(arguments);
4061 break;
4062 }
anthonyebb73a22012-03-22 14:25:52 +00004063 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004064 }
4065 case 'r':
4066 {
anthonyafa3dfc2012-03-03 11:31:30 +00004067 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004068 {
anthony92c93bd2012-03-19 14:02:47 +00004069 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004070 break;
4071 }
anthonyafa3dfc2012-03-03 11:31:30 +00004072 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004073 {
anthony92c93bd2012-03-19 14:02:47 +00004074 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004075 break;
4076 }
anthonyebb73a22012-03-22 14:25:52 +00004077 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004078 }
4079 case 's':
4080 {
anthonyafa3dfc2012-03-03 11:31:30 +00004081 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004082 {
anthonycd358fc2012-04-16 13:59:03 +00004083 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004084 ssize_t
4085 offset;
4086
anthony7bcfe7f2012-03-30 14:01:22 +00004087 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004088 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004089 offset=(ssize_t) StringToLong(arg1);
anthonycd358fc2012-04-16 13:59:03 +00004090 new_images=SmushImages(_images,normal_op,offset,_exception);
4091 break;
4092 }
4093 if (LocaleCompare("subimage",option+1) == 0)
4094 {
4095 Image
4096 *base_image,
4097 *compare_image;
4098
4099 const char *
4100 value;
4101
4102 MetricType
4103 metric;
4104
4105 double
4106 similarity;
4107
4108 RectangleInfo
4109 offset;
4110
4111 base_image=GetImageFromList(_images,0);
4112 compare_image=GetImageFromList(_images,1);
4113
4114 /* Comparision Metric */
4115 metric=UndefinedMetric;
4116 value=GetImageOption(_image_info,"metric");
4117 if (value != (const char *) NULL)
4118 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4119 MagickFalse,value);
4120
4121 new_images=SimilarityImage(base_image,compare_image,metric,
4122 &offset,&similarity,_exception);
4123
4124 if ( new_images != (Image *)NULL ) {
4125 char
4126 result[MaxTextExtent];
4127
4128 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4129 (void) SetImageProperty(new_images,"subimage:similarity",result,
4130 _exception);
4131 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4132 (long) offset.x);
4133 (void) SetImageProperty(new_images,"subimage:x",result,
4134 _exception);
4135 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4136 (long) offset.y);
4137 (void) SetImageProperty(new_images,"subimage:y",result,
4138 _exception);
4139 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4140 (unsigned long) offset.width,(unsigned long) offset.height,
4141 (long) offset.x,(long) offset.y);
4142 (void) SetImageProperty(new_images,"subimage:offset",result,
4143 _exception);
4144 }
anthony805a2d42011-09-25 08:25:12 +00004145 break;
4146 }
anthony0ea037a2012-04-03 12:14:39 +00004147 if (LocaleCompare("swap",option+1) == 0) {
4148 Image
4149 *p,
4150 *q,
4151 *swap;
anthony805a2d42011-09-25 08:25:12 +00004152
anthony0ea037a2012-04-03 12:14:39 +00004153 ssize_t
4154 index,
4155 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004156
anthony0ea037a2012-04-03 12:14:39 +00004157 index=-1;
4158 swap_index=-2;
4159 if (IfNormalOp) {
4160 GeometryInfo
4161 geometry_info;
4162
4163 MagickStatusType
4164 flags;
4165
4166 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004167 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00004168 if ((flags & RhoValue) != 0)
4169 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004170 index=(ssize_t) geometry_info.rho;
4171 if ((flags & SigmaValue) != 0)
4172 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004173 }
anthony0ea037a2012-04-03 12:14:39 +00004174 p=GetImageFromList(_images,index);
4175 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004176 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4177 if (IfNormalOp)
4178 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4179 else
4180 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4181 }
anthony0ea037a2012-04-03 12:14:39 +00004182 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004183 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004184 swap=CloneImage(p,0,0,MagickTrue,_exception);
4185 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4186 ReplaceImageInList(&q,swap);
4187 _images=GetFirstImageInList(q);
4188 break;
4189 }
anthonyebb73a22012-03-22 14:25:52 +00004190 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004191 }
anthony805a2d42011-09-25 08:25:12 +00004192 default:
anthonyebb73a22012-03-22 14:25:52 +00004193 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004194 }
anthony31f1bf72012-01-30 12:37:22 +00004195 if (new_images == (Image *) NULL)
4196 return;
anthony805a2d42011-09-25 08:25:12 +00004197
anthony92c93bd2012-03-19 14:02:47 +00004198 if (_images != (Image *) NULL)
4199 _images=DestroyImageList(_images);
4200 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004201 return;
4202
anthony92c93bd2012-03-19 14:02:47 +00004203#undef _image_info
4204#undef _images
4205#undef _exception
4206#undef _draw_info
4207#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004208#undef IfNormalOp
4209#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004210#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004211}
anthony43f425d2012-02-26 12:58:58 +00004212
4213/*
4214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4215% %
4216% %
4217% %
4218+ C L I S p e c i a l O p e r a t i o n s %
4219% %
4220% %
4221% %
4222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4223%
anthony464f1c42012-04-22 08:51:01 +00004224% CLINoImageOperator() Applies operations that may not actually need images
anthony756cd0d2012-04-08 12:41:44 +00004225% in an image list wen it is applied.
anthony43f425d2012-02-26 12:58:58 +00004226%
anthony756cd0d2012-04-08 12:41:44 +00004227% The classic operators of this type is -read, which actually creates images
4228% even when no images are present. Or image stack operators, which can be
4229% applied to empty image lists.
anthonyafa3dfc2012-03-03 11:31:30 +00004230%
4231% Note: unlike other Operators, these may involve other special 'option'
4232% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004233%
anthony464f1c42012-04-22 08:51:01 +00004234% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004235%
anthony464f1c42012-04-22 08:51:01 +00004236% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4237% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004238%
4239% A description of each parameter follows:
4240%
4241% o cli_wand: the main CLI Wand to use.
4242%
4243% o option: The special option (with any switch char) to process
4244%
anthony464f1c42012-04-22 08:51:01 +00004245% o arg1 & arg2: Argument for option, if required
4246% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004247%
4248*/
anthony464f1c42012-04-22 08:51:01 +00004249WandExport void CLINoImageOperator(MagickCLI *cli_wand,
4250 const char *option, const char *arg1, const char *magick_unused(arg2))
anthony43f425d2012-02-26 12:58:58 +00004251{
anthony8226e722012-04-05 14:25:46 +00004252#define _image_info (cli_wand->wand.image_info)
4253#define _images (cli_wand->wand.images)
4254#define _exception (cli_wand->wand.exception)
4255#define IfNormalOp (*option=='-')
4256#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004257
4258 assert(cli_wand != (MagickCLI *) NULL);
4259 assert(cli_wand->signature == WandSignature);
4260 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +00004261 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00004262 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4263
anthony52bef752012-03-27 13:54:47 +00004264 /*
anthony756cd0d2012-04-08 12:41:44 +00004265 No-op options (ignore these)
anthony52bef752012-03-27 13:54:47 +00004266 */
anthony756cd0d2012-04-08 12:41:44 +00004267 if (LocaleCompare("noop",option+1) == 0) /* no argument */
anthony52bef752012-03-27 13:54:47 +00004268 return;
anthony756cd0d2012-04-08 12:41:44 +00004269 if (LocaleCompare("sans",option+1) == 0) /* one argument */
anthony52bef752012-03-27 13:54:47 +00004270 return;
anthony756cd0d2012-04-08 12:41:44 +00004271 if (LocaleCompare("sans0",option+1) == 0) /* no argument */
anthony52bef752012-03-27 13:54:47 +00004272 return;
anthony756cd0d2012-04-08 12:41:44 +00004273 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
anthony52bef752012-03-27 13:54:47 +00004274 return;
4275 /*
4276 Image Reading
4277 */
4278 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthony0ea037a2012-04-03 12:14:39 +00004279 ( LocaleCompare("--",option) == 0 ) ) {
4280 int
4281 argc;
4282 char
4283 **argv;
anthony52bef752012-03-27 13:54:47 +00004284
anthony0ea037a2012-04-03 12:14:39 +00004285 ssize_t
4286 i;
4287
4288 /* Expand the filename argument (meta-characters or "@filelist" ) */
4289 argc = 1;
cristye71f2942012-04-04 11:07:05 +00004290 argv = (char **) &arg1;
anthony0ea037a2012-04-03 12:14:39 +00004291 MagickBooleanType
4292 status=ExpandFilenames(&argc,&argv);
4293
4294 if (IfMagickFalse(status))
4295 CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed",
4296 option,GetExceptionMessage(errno));
4297
4298 /* loop over expanded list reading images */
4299 for (i=0; i<argc; i++) {
anthony52bef752012-03-27 13:54:47 +00004300#if !USE_WAND_METHODS
4301 Image *
4302 new_images;
anthony8226e722012-04-05 14:25:46 +00004303 if (IfMagickTrue(_image_info->ping))
4304 new_images=PingImages(_image_info,argv[i],_exception);
anthony52bef752012-03-27 13:54:47 +00004305 else
anthony8226e722012-04-05 14:25:46 +00004306 new_images=ReadImages(_image_info,argv[i],_exception);
4307 AppendImageToList(&_images, new_images);
anthony52bef752012-03-27 13:54:47 +00004308#else
4309 /* read images using MagickWand method - no ping */
4310 /* This is not working! - it locks up in a CPU loop! */
4311 MagickSetLastIterator(&cli_wand->wand);
4312 MagickReadImage(&cli_wand->wand,arg1);
4313 MagickSetFirstIterator(&cli_wand->wand);
4314#endif
anthony52bef752012-03-27 13:54:47 +00004315 }
anthony0ea037a2012-04-03 12:14:39 +00004316 /* FUTURE: how do I free the expanded filename arguments??? */
4317
4318 return;
4319 }
anthony52bef752012-03-27 13:54:47 +00004320 /*
anthony756cd0d2012-04-08 12:41:44 +00004321 Image Writing (no-images present is valid in specific cases)
anthony8226e722012-04-05 14:25:46 +00004322 */
4323 if (LocaleCompare("write",option+1) == 0) {
4324 char
4325 key[MaxTextExtent];
4326
4327 Image
4328 *write_images;
4329
4330 ImageInfo
4331 *write_info;
4332
4333 /* Need images, unless a "null:" output coder is used */
4334 if ( cli_wand->wand.images == (Image *) NULL ) {
anthonya9e4f5d2012-04-12 06:44:02 +00004335 if ( LocaleCompare(arg1,"null:") == 0 )
anthony8226e722012-04-05 14:25:46 +00004336 return;
4337 CLIWandExceptArgReturn(OptionError,"NoImagesForWrite",option,arg1);
4338 }
4339
4340 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4341 (void) DeleteImageRegistry(key);
4342 write_images=_images;
4343 if (IfPlusOp)
4344 write_images=CloneImageList(_images,_exception);
4345 write_info=CloneImageInfo(_image_info);
4346 (void) WriteImages(write_info,write_images,arg1,_exception);
4347 write_info=DestroyImageInfo(write_info);
4348 if (IfPlusOp)
4349 write_images=DestroyImageList(write_images);
4350 return;
4351 }
4352 /*
anthony52bef752012-03-27 13:54:47 +00004353 Parenthesis and Brace operations
4354 */
anthonyce8dcb32012-03-21 13:20:31 +00004355 if (LocaleCompare("(",option) == 0) {
anthony8226e722012-04-05 14:25:46 +00004356 /* stack 'push' images */
4357 Stack
4358 *node;
anthony43f425d2012-02-26 12:58:58 +00004359
anthony8226e722012-04-05 14:25:46 +00004360 size_t
4361 size;
anthony43f425d2012-02-26 12:58:58 +00004362
anthony8226e722012-04-05 14:25:46 +00004363 size=0;
4364 node=cli_wand->image_list_stack;
4365 for ( ; node != (Stack *)NULL; node=node->next)
4366 size++;
4367 if ( size >= MAX_STACK_DEPTH )
4368 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
4369 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4370 if (node == (Stack *) NULL)
4371 CLIWandExceptionReturn(ResourceLimitFatalError,
4372 "MemoryAllocationFailed",option);
4373 node->data = (void *)cli_wand->wand.images;
4374 cli_wand->wand.images = NewImageList();
4375 node->next = cli_wand->image_list_stack;
4376 cli_wand->image_list_stack = node;
anthony43f425d2012-02-26 12:58:58 +00004377
anthony8226e722012-04-05 14:25:46 +00004378 /* handle respect-parenthesis */
4379 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4380 "respect-parenthesis"))))
4381 option="{"; /* fall-thru so as to push image settings too */
4382 else
anthony43f425d2012-02-26 12:58:58 +00004383 return;
anthony8226e722012-04-05 14:25:46 +00004384 }
4385 if (LocaleCompare("{",option) == 0) {
4386 /* stack 'push' of image_info settings */
4387 Stack
4388 *node;
anthony43f425d2012-02-26 12:58:58 +00004389
anthony8226e722012-04-05 14:25:46 +00004390 size_t
4391 size;
anthony43f425d2012-02-26 12:58:58 +00004392
anthony8226e722012-04-05 14:25:46 +00004393 size=0;
4394 node=cli_wand->image_info_stack;
4395 for ( ; node != (Stack *)NULL; node=node->next)
4396 size++;
4397 if ( size >= MAX_STACK_DEPTH )
4398 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
4399 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4400 if (node == (Stack *) NULL)
4401 CLIWandExceptionReturn(ResourceLimitFatalError,
4402 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004403
anthony8226e722012-04-05 14:25:46 +00004404 node->data = (void *)cli_wand->wand.image_info;
4405 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4406 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4407 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4408 option);
anthony43f425d2012-02-26 12:58:58 +00004409 cli_wand->wand.image_info = (ImageInfo *)node->data;
4410 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004411 return;
4412 }
anthony8226e722012-04-05 14:25:46 +00004413
4414 node->next = cli_wand->image_info_stack;
4415 cli_wand->image_info_stack = node;
4416
4417 return;
4418 }
4419 if (LocaleCompare(")",option) == 0) {
4420 /* pop images from stack */
4421 Stack
4422 *node;
4423
4424 node = (Stack *)cli_wand->image_list_stack;
4425 if ( node == (Stack *)NULL)
4426 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
4427 cli_wand->image_list_stack = node->next;
4428
4429 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4430 cli_wand->wand.images= (Image *)node->data;
4431 node = (Stack *)RelinquishMagickMemory(node);
4432
4433 /* handle respect-parenthesis - of the previous 'pushed' settings */
4434 node = cli_wand->image_info_stack;
4435 if ( node != (Stack *)NULL)
4436 {
4437 if (IfMagickTrue(IsStringTrue(GetImageOption(
4438 cli_wand->wand.image_info,"respect-parenthesis"))))
4439 option="}"; /* fall-thru so as to pop image settings too */
4440 else
4441 return;
4442 }
4443 else
4444 return;
4445 }
4446 if (LocaleCompare("}",option) == 0) {
4447 /* pop image_info settings from stack */
4448 Stack
4449 *node;
4450
4451 node = (Stack *)cli_wand->image_info_stack;
4452 if ( node == (Stack *)NULL)
4453 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
4454 cli_wand->image_info_stack = node->next;
4455
4456 (void) DestroyImageInfo(cli_wand->wand.image_info);
4457 cli_wand->wand.image_info = (ImageInfo *)node->data;
4458 node = (Stack *)RelinquishMagickMemory(node);
4459
4460 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4461 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4462 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4463
4464 return;
4465 }
anthonyce8dcb32012-03-21 13:20:31 +00004466 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004467 Image
4468 *new_images;
4469
4470 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004471 arg1="-1";
anthony7bcfe7f2012-03-30 14:01:22 +00004472 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
anthony92c93bd2012-03-19 14:02:47 +00004473 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004474 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004475 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004476 new_images = (Image *)cli_wand->image_list_stack->data;
4477 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004478 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4479 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004480 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004481 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony8226e722012-04-05 14:25:46 +00004482 AppendImageToList(&_images,new_images);
anthony43f425d2012-02-26 12:58:58 +00004483 return;
4484 }
anthony52bef752012-03-27 13:54:47 +00004485 /*
4486 Informational Operations
4487 */
anthony0ea037a2012-04-03 12:14:39 +00004488 if (LocaleCompare("version",option+1) == 0) {
anthony8226e722012-04-05 14:25:46 +00004489 (void) FormatLocaleFile(stdout,"Version: %s\n",
4490 GetMagickVersion((size_t *) NULL));
4491 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4492 GetMagickCopyright());
4493 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4494 GetMagickFeatures());
4495 return;
4496 }
anthonyce8dcb32012-03-21 13:20:31 +00004497 if (LocaleCompare("list",option+1) == 0) {
anthony8226e722012-04-05 14:25:46 +00004498 /* FUTURE: This should really be built into the MagickCore
4499 It does not actually require a cli-wand or and images!
4500 */
4501 ssize_t
4502 list;
anthony43f425d2012-02-26 12:58:58 +00004503
anthony8226e722012-04-05 14:25:46 +00004504 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4505 if ( list < 0 ) {
4506 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004507 return;
4508 }
anthony8226e722012-04-05 14:25:46 +00004509 switch (list)
4510 {
4511 case MagickCoderOptions:
4512 {
4513 (void) ListCoderInfo((FILE *) NULL,_exception);
4514 break;
4515 }
4516 case MagickColorOptions:
4517 {
4518 (void) ListColorInfo((FILE *) NULL,_exception);
4519 break;
4520 }
4521 case MagickConfigureOptions:
4522 {
4523 (void) ListConfigureInfo((FILE *) NULL,_exception);
4524 break;
4525 }
4526 case MagickDelegateOptions:
4527 {
4528 (void) ListDelegateInfo((FILE *) NULL,_exception);
4529 break;
4530 }
4531 case MagickFontOptions:
4532 {
4533 (void) ListTypeInfo((FILE *) NULL,_exception);
4534 break;
4535 }
4536 case MagickFormatOptions:
4537 (void) ListMagickInfo((FILE *) NULL,_exception);
4538 break;
4539 case MagickLocaleOptions:
4540 (void) ListLocaleInfo((FILE *) NULL,_exception);
4541 break;
4542 case MagickLogOptions:
4543 (void) ListLogInfo((FILE *) NULL,_exception);
4544 break;
4545 case MagickMagicOptions:
4546 (void) ListMagicInfo((FILE *) NULL,_exception);
4547 break;
4548 case MagickMimeOptions:
4549 (void) ListMimeInfo((FILE *) NULL,_exception);
4550 break;
4551 case MagickModuleOptions:
4552 (void) ListModuleInfo((FILE *) NULL,_exception);
4553 break;
4554 case MagickPolicyOptions:
4555 (void) ListPolicyInfo((FILE *) NULL,_exception);
4556 break;
4557 case MagickResourceOptions:
4558 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4559 break;
4560 case MagickThresholdOptions:
4561 (void) ListThresholdMaps((FILE *) NULL,_exception);
4562 break;
4563 default:
4564 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4565 _exception);
4566 break;
4567 }
4568 return;
4569 }
anthony43f425d2012-02-26 12:58:58 +00004570
4571#if 0
anthony43f425d2012-02-26 12:58:58 +00004572 // Other 'special' options this should handle
anthony5216f822012-04-10 13:02:37 +00004573 // "region" "reset" "arg"
anthony43f425d2012-02-26 12:58:58 +00004574 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004575#endif
anthonyebb73a22012-03-22 14:25:52 +00004576 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004577
anthony8226e722012-04-05 14:25:46 +00004578#undef _image_info
4579#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004580#undef _exception
anthony8226e722012-04-05 14:25:46 +00004581#undef IfNormalOp
4582#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004583}
anthony464f1c42012-04-22 08:51:01 +00004584
4585/*
4586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4587% %
4588% %
4589% %
4590+ C L I O p t i o n O p e r a t i o n s %
4591% %
4592% %
4593% %
4594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4595%
4596% CLIOption() Processes the given option using the given CLI Magick Wand.
4597%
4598% If the cli_wand->command pointer is non-null, then it is assumed that the
4599% option has already been search for up from the CommandOptions[] table in
4600% "MagickCore/options.c" using GetCommandOptionInfo(), so that any command
4601% specific options (such as "magick" scripting options, or "display" settings)
4602% can be handled separatally.
4603%
4604% The format of the CLIOption method is:
4605%
4606% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4607%
4608% A description of each parameter follows:
4609%
4610% o cli_wand: the main CLI Wand to use.
4611%
4612% o option: The special option (with any switch char) to process
4613%
4614% o args: any required arguments for an option
4615%
4616% Example Usage...
4617%
4618% CLIoption(cli_wand,"-read","rose:");
4619% CLIoption(cli_wand,"-virtual-pixel","transparent");
4620% CLIoption(cli_wand,"-distort","SRT:","30");
4621% CLIoption(cli_wand,"-write","rotated_rose.png");
4622%
4623*/
4624WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4625{
4626 const char
4627 *arg1,
4628 *arg2;
4629
4630 CommandOptionFlags
4631 option_type;
4632
4633 assert(cli_wand != (MagickCLI *) NULL);
4634 assert(cli_wand->signature == WandSignature);
4635 assert(cli_wand->wand.signature == WandSignature);
4636 if (IfMagickTrue(cli_wand->wand.debug))
4637 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4638
4639 if ( cli_wand->command == (const OptionInfo *) NULL )
4640 cli_wand->command = GetCommandOptionInfo(option);
4641#if 0
4642 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4643 option, cli_wand->command->mnemonic );
4644#endif
4645
4646 option_type=(CommandOptionFlags) cli_wand->command->flags;
4647
4648 if ( option_type == UndefinedOptionFlag )
4649 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
4650
4651 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
4652
4653 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4654 CLIWandExceptionReturn(OptionFatalError,"InvalidUseOfOption",option);
4655
4656 if ( (option_type & DeprecateOptionFlag) != 0 )
4657 CLIWandExceptionReturn(OptionError,"DeprecatedOptionNoCode",option);
4658
4659 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
4660 return;
4661
4662
4663 { size_t
4664 count = cli_wand->command->type;
4665
4666 va_list
4667 operands;
4668
4669 va_start(operands,option);
4670
4671 arg1=arg2=NULL;
4672 if ( count >= 1 )
4673 arg1=(const char *) va_arg(operands, const char *);
4674 if ( count >= 2 )
4675 arg2=(const char *) va_arg(operands, const char *);
4676
4677 va_end(operands);
4678
anthony52cb3df2012-04-24 03:29:32 +00004679#if 0
anthony464f1c42012-04-22 08:51:01 +00004680 (void) FormatLocaleFile(stderr,
cristy9ffd20e2012-04-22 16:45:20 +00004681 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4682 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00004683#endif
4684 }
4685
4686 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
4687
4688
4689 /*
4690 Call the appropriate option handler
4691 */
4692
4693 /* FUTURE: this is temporary - get 'settings' to handle
4694 distribution of settings to images attributes,proprieties,artifacts */
4695 if ( cli_wand->wand.images != (Image *)NULL )
4696 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4697 cli_wand->wand.exception);
4698
4699 if ( (option_type & SettingOptionFlags) != 0 ) {
4700 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4701 // FUTURE: Sync Specific Settings into Image Properities (not global)
4702 }
4703
4704 if ( (option_type & NoImageOperatorFlag) != 0)
4705 CLINoImageOperator(cli_wand, option, arg1, arg2);
4706
4707 /* FUTURE: The not a setting part below is a temporary hack due to
4708 * some options being both a Setting and a Simple operator.
4709 * Specifically -monitor, -depth, and -colorspace */
4710 if ( cli_wand->wand.images == (Image *)NULL ) {
4711 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
4712 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
4713 CLIWandException(OptionError,"NoImagesFound",option);
4714 return; /* on its own this is not an error */
4715 }
4716
4717 if ( (option_type & SimpleOperatorFlag) != 0)
4718 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
4719
4720 if ( (option_type & ListOperatorFlag) != 0 )
4721 CLIListOperatorImages(cli_wand, option, arg1, arg2);
4722
4723}