blob: 58a53c54c7e6554a294f4aea59653f84bfa01bf7 [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"
anthonyfd706f92012-01-19 04:22:02 +000053#include "MagickWand/operation.h"
anthony805a2d42011-09-25 08:25:12 +000054#include "MagickCore/monitor-private.h"
55#include "MagickCore/thread-private.h"
56#include "MagickCore/string-private.h"
57
58/*
59 Define declarations.
60*/
61#define UndefinedCompressionQuality 0UL
62/*
63 Constant declaration. (temporary exports)
64*/
65static const char
66 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000067 BorderColor[] = "#dfdfdf", /* sRGB gray */
68 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony805a2d42011-09-25 08:25:12 +000069
70/*
71** Function to report on the progress of image operations
72*/
73static MagickBooleanType MonitorProgress(const char *text,
74 const MagickOffsetType offset,const MagickSizeType extent,
75 void *wand_unused(client_data))
76{
77 char
78 message[MaxTextExtent],
79 tag[MaxTextExtent];
80
81 const char
82 *locale_message;
83
84 register char
85 *p;
86
87 if (extent < 2)
88 return(MagickTrue);
89 (void) CopyMagickMemory(tag,text,MaxTextExtent);
90 p=strrchr(tag,'/');
91 if (p != (char *) NULL)
92 *p='\0';
93 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
94 locale_message=GetLocaleMessage(message);
95 if (locale_message == message)
96 locale_message=tag;
97 if (p == (char *) NULL)
98 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
99 locale_message,(long) offset,(unsigned long) extent,(long)
100 (100L*offset/(extent-1)));
101 else
102 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
103 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
104 (100L*offset/(extent-1)));
105 if (offset == (MagickOffsetType) (extent-1))
106 (void) FormatLocaleFile(stderr,"\n");
107 (void) fflush(stderr);
108 return(MagickTrue);
109}
110
111/*
112** GetImageCache() will read an image into a image cache if not already
113** present then return the image that is in the cache under that filename.
114*/
115static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
116 ExceptionInfo *exception)
117{
118 char
119 key[MaxTextExtent];
120
121 ExceptionInfo
122 *sans_exception;
123
124 Image
125 *image;
126
127 ImageInfo
128 *read_info;
129
130 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
131 sans_exception=AcquireExceptionInfo();
132 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
133 sans_exception=DestroyExceptionInfo(sans_exception);
134 if (image != (Image *) NULL)
135 return(image);
136 read_info=CloneImageInfo(image_info);
137 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
138 image=ReadImage(read_info,exception);
139 read_info=DestroyImageInfo(read_info);
140 if (image != (Image *) NULL)
141 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
142 return(image);
143}
144
145/*
anthonya89dd172011-10-04 13:29:35 +0000146 SparseColorOption() parse the complex -sparse-color argument into an
147 an array of floating point values than call SparseColorImage().
148 Argument is a complex mix of floating-point pixel coodinates, and color
149 specifications (or direct floating point numbers). The number of floats
150 needed to represent a color varies depending on teh current channel
151 setting.
anthony805a2d42011-09-25 08:25:12 +0000152*/
153static Image *SparseColorOption(const Image *image,
154 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000155 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000156{
157 char
158 token[MaxTextExtent];
159
160 const char
161 *p;
162
163 double
164 *sparse_arguments;
165
166 Image
167 *sparse_image;
168
169 PixelInfo
170 color;
171
172 MagickBooleanType
173 error;
174
175 register size_t
176 x;
177
178 size_t
179 number_arguments,
180 number_colors;
181
182 assert(image != (Image *) NULL);
183 assert(image->signature == MagickSignature);
184 if (image->debug != MagickFalse)
185 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
186 assert(exception != (ExceptionInfo *) NULL);
187 assert(exception->signature == MagickSignature);
188 /*
189 Limit channels according to image - and add up number of color channel.
190 */
191 number_colors=0;
192 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
193 number_colors++;
194 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
195 number_colors++;
196 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
197 number_colors++;
198 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
199 (image->colorspace == CMYKColorspace))
200 number_colors++;
201 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
202 (image->matte != MagickFalse))
203 number_colors++;
204
205 /*
206 Read string, to determine number of arguments needed,
207 */
208 p=arguments;
209 x=0;
210 while( *p != '\0' )
211 {
212 GetMagickToken(p,&p,token);
213 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000214 if ( isalpha((int) token[0]) || token[0] == '#' )
215 x += number_colors; /* color argument found */
anthony805a2d42011-09-25 08:25:12 +0000216 else {
217 x++; /* floating point argument */
218 }
219 }
220 error=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +0000221 /* control points and color values */
222 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
223 number_arguments=x;
anthony805a2d42011-09-25 08:25:12 +0000224 if ( error ) {
225 (void) ThrowMagickException(exception,GetMagickModule(),
226 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
227 "Invalid number of Arguments");
228 return( (Image *)NULL);
229 }
230
231 /* Allocate and fill in the floating point arguments */
232 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
233 sizeof(*sparse_arguments));
234 if (sparse_arguments == (double *) NULL) {
235 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
236 "MemoryAllocationFailed","%s","SparseColorOption");
237 return( (Image *)NULL);
238 }
239 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
240 sizeof(*sparse_arguments));
241 p=arguments;
242 x=0;
243 while( *p != '\0' && x < number_arguments ) {
244 /* X coordinate */
245 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
246 if ( token[0] == '\0' ) break;
247 if ( isalpha((int) token[0]) || token[0] == '#' ) {
248 (void) ThrowMagickException(exception,GetMagickModule(),
249 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
250 "Color found, instead of X-coord");
251 error = MagickTrue;
252 break;
253 }
cristydbdd0e32011-11-04 23:29:40 +0000254 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000255 /* Y coordinate */
256 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
257 if ( token[0] == '\0' ) break;
258 if ( isalpha((int) token[0]) || token[0] == '#' ) {
259 (void) ThrowMagickException(exception,GetMagickModule(),
260 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
261 "Color found, instead of Y-coord");
262 error = MagickTrue;
263 break;
264 }
cristydbdd0e32011-11-04 23:29:40 +0000265 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000266 /* color name or function given in string argument */
267 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
268 if ( token[0] == '\0' ) break;
269 if ( isalpha((int) token[0]) || token[0] == '#' ) {
270 /* Color string given */
271 (void) QueryColorCompliance(token,AllCompliance,&color,
272 exception);
273 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
274 sparse_arguments[x++] = QuantumScale*color.red;
275 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
276 sparse_arguments[x++] = QuantumScale*color.green;
277 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
278 sparse_arguments[x++] = QuantumScale*color.blue;
279 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
280 (image->colorspace == CMYKColorspace))
281 sparse_arguments[x++] = QuantumScale*color.black;
282 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
283 (image->matte != MagickFalse))
284 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000285 }
anthony31f1bf72012-01-30 12:37:22 +0000286 else {
287 /* Colors given as a set of floating point values - experimental */
288 /* NB: token contains the first floating point value to use! */
289 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
290 {
291 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
292 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
293 break;
294 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
295 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000296 }
anthony31f1bf72012-01-30 12:37:22 +0000297 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
298 {
299 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
300 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
301 break;
302 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
303 token[0] = ','; /* used this token - get another */
304 }
305 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
306 {
307 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
308 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
309 break;
310 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
311 token[0] = ','; /* used this token - get another */
312 }
313 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
314 (image->colorspace == CMYKColorspace))
315 {
316 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
317 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
318 break;
319 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
320 token[0] = ','; /* used this token - get another */
321 }
322 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
323 (image->matte != MagickFalse))
324 {
325 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
326 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
327 break;
328 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
329 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000330 }
331 }
332 }
333 if ( number_arguments != x && !error ) {
334 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
335 "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
336 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
337 return( (Image *)NULL);
338 }
339 if ( error )
340 return( (Image *)NULL);
341
anthony31f1bf72012-01-30 12:37:22 +0000342 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000343 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
344 exception);
345 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
346 return( sparse_image );
347}
348
349/*
350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
351% %
352% %
353% %
anthony8b10b462012-02-08 12:32:44 +0000354+ W a n d S e t t i n g O p t i o n I n f o %
anthony805a2d42011-09-25 08:25:12 +0000355% %
356% %
357% %
358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359%
anthonyd1447672012-01-19 05:33:53 +0000360% WandSettingOptionInfo() applies a single settings option into a CLI wand
anthonydcf510d2011-10-30 13:51:40 +0000361% holding the image_info, draw_info, quantize_info structures that will be
anthonyfd706f92012-01-19 04:22:02 +0000362% used when processing the images also found within the wand.
anthony805a2d42011-09-25 08:25:12 +0000363%
anthony80c37752012-01-16 01:03:11 +0000364% These options do no require images to be present in the wand for them to be
anthony31f1bf72012-01-30 12:37:22 +0000365% able to be set, in which case they will be applied to
anthony80c37752012-01-16 01:03:11 +0000366%
367% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000368% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000369%
anthonyd1447672012-01-19 05:33:53 +0000370% The format of the WandSettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000371%
anthony31f1bf72012-01-30 12:37:22 +0000372% void WandSettingOptionInfo(MagickWand *wand,const char *option,
373% const char *arg)
anthony805a2d42011-09-25 08:25:12 +0000374%
375% A description of each parameter follows:
376%
anthony1afdc7a2011-10-05 11:54:28 +0000377% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000378%
anthonydcf510d2011-10-30 13:51:40 +0000379% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000380%
anthony72feaa62012-01-17 06:46:23 +0000381% o arg: The single argument used to set this option.
382% If NULL the setting is reset to its default value.
anthony31f1bf72012-01-30 12:37:22 +0000383% For boolean (no argument) settings false=NULL, true=any_string
anthonydcf510d2011-10-30 13:51:40 +0000384%
anthony72feaa62012-01-17 06:46:23 +0000385% Example usage...
386%
anthonyd1447672012-01-19 05:33:53 +0000387% WandSettingOptionInfo(wand, "background", MagickTrue, "Red");
388% WandSettingOptionInfo(wand, "adjoin", "true");
389% WandSettingOptionInfo(wand, "adjoin", NULL);
anthony72feaa62012-01-17 06:46:23 +0000390%
391% Or for handling command line arguments EG: +/-option ["arg"]
anthonydcf510d2011-10-30 13:51:40 +0000392%
393% argc,argv
394% i=index in argv
395%
396% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
397% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthonyfd706f92012-01-19 04:22:02 +0000398% if ( (flags & SettingOptionFlags) != 0 )
anthonyd1447672012-01-19 05:33:53 +0000399% WandSettingOptionInfo(wand, argv[i]+1,
anthonyfd706f92012-01-19 04:22:02 +0000400% (((*argv[i])!='-') ? (char *)NULL
401% : (count>0) ? argv[i+1] : "true") );
anthonydcf510d2011-10-30 13:51:40 +0000402% i += count+1;
403%
anthony805a2d42011-09-25 08:25:12 +0000404*/
anthony31f1bf72012-01-30 12:37:22 +0000405WandExport void WandSettingOptionInfo(MagickWand *wand,const char *option,
406 const char *arg)
anthony805a2d42011-09-25 08:25:12 +0000407{
anthony1afdc7a2011-10-05 11:54:28 +0000408 assert(wand != (MagickWand *) NULL);
409 assert(wand->signature == WandSignature);
410 assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
anthony1afdc7a2011-10-05 11:54:28 +0000411 if (wand->debug != MagickFalse)
412 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
anthony1afdc7a2011-10-05 11:54:28 +0000413
anthony72feaa62012-01-17 06:46:23 +0000414#define image_info (wand->image_info)
415#define draw_info (wand->draw_info)
416#define quantize_info (wand->quantize_info)
anthonyfd706f92012-01-19 04:22:02 +0000417#define exception (wand->exception)
anthony72feaa62012-01-17 06:46:23 +0000418#define IfSetOption (arg!=(char *)NULL)
419#define ArgOption(def) (IfSetOption?arg:(const char *)(def))
420#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
anthony74b1cfc2011-10-06 12:44:16 +0000421
422 switch (*option)
anthony805a2d42011-09-25 08:25:12 +0000423 {
424 case 'a':
425 {
anthony74b1cfc2011-10-06 12:44:16 +0000426 if (LocaleCompare("adjoin",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000427 {
anthony72feaa62012-01-17 06:46:23 +0000428 image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000429 break;
430 }
anthony74b1cfc2011-10-06 12:44:16 +0000431 if (LocaleCompare("affine",option) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000432 {
anthony31f1bf72012-01-30 12:37:22 +0000433 /* DEPRECIATED: draw_info setting only: for -draw and -transform */
anthony74b1cfc2011-10-06 12:44:16 +0000434 if (IfSetOption)
anthony72feaa62012-01-17 06:46:23 +0000435 (void) ParseAffineGeometry(arg,&draw_info->affine,exception);
anthony74b1cfc2011-10-06 12:44:16 +0000436 else
anthony72feaa62012-01-17 06:46:23 +0000437 GetAffineMatrix(&draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000438 break;
439 }
anthony74b1cfc2011-10-06 12:44:16 +0000440 if (LocaleCompare("antialias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000441 {
anthony1afdc7a2011-10-05 11:54:28 +0000442 image_info->antialias =
anthony72feaa62012-01-17 06:46:23 +0000443 draw_info->stroke_antialias =
444 draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000445 break;
446 }
anthony31f1bf72012-01-30 12:37:22 +0000447 if (LocaleCompare("attenuate",option+1) == 0)
448 {
449 (void) SetImageOption(image_info,option,ArgOption(NULL));
450 break;
451 }
anthony74b1cfc2011-10-06 12:44:16 +0000452 if (LocaleCompare("authenticate",option) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000453 {
anthony72feaa62012-01-17 06:46:23 +0000454 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000455 break;
456 }
457 break;
458 }
459 case 'b':
460 {
anthony74b1cfc2011-10-06 12:44:16 +0000461 if (LocaleCompare("background",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000462 {
anthony74b1cfc2011-10-06 12:44:16 +0000463 /* FUTURE: both image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000464 image_info only used directly for generating new images.
465 SyncImageSettings() used to set per-image attribute.
466
467 FUTURE: if image_info->background_color is not set then
468 we should fall back to image
469 Note that +background, means fall-back to image background
470 and only if not set fall back to BackgroundColor const.
anthony74b1cfc2011-10-06 12:44:16 +0000471 */
anthony72feaa62012-01-17 06:46:23 +0000472 (void) SetImageOption(image_info,option,ArgOption(NULL));
473 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
474 &image_info->background_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000475 break;
476 }
anthony74b1cfc2011-10-06 12:44:16 +0000477 if (LocaleCompare("bias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000478 {
anthony74b1cfc2011-10-06 12:44:16 +0000479 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000480 as it is actually rarely used except in direct convolve operations
481 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000482
483 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000484 */
anthony72feaa62012-01-17 06:46:23 +0000485 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000486 break;
487 }
anthony74b1cfc2011-10-06 12:44:16 +0000488 if (LocaleCompare("black-point-compensation",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000489 {
anthony72feaa62012-01-17 06:46:23 +0000490 /* Used as a image chromaticity setting
491 SyncImageSettings() used to set per-image attribute.
492 */
anthony74b1cfc2011-10-06 12:44:16 +0000493 (void) SetImageOption(image_info,option,
494 IfSetOption ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +0000495 break;
496 }
anthony74b1cfc2011-10-06 12:44:16 +0000497 if (LocaleCompare("blue-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000498 {
anthonyafbaed72011-10-26 12:05:04 +0000499 /* Image chromaticity X,Y NB: Y=X if Y not defined
500 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000501 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000502 */
anthony72feaa62012-01-17 06:46:23 +0000503 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000504 break;
505 }
anthony74b1cfc2011-10-06 12:44:16 +0000506 if (LocaleCompare("bordercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000507 {
anthony72feaa62012-01-17 06:46:23 +0000508 /* FUTURE: both image_info attribute & ImageOption in use!
509 SyncImageSettings() used to set per-image attribute.
510 */
anthony74b1cfc2011-10-06 12:44:16 +0000511 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000512 {
anthonydcf510d2011-10-30 13:51:40 +0000513 (void) SetImageOption(image_info,option,arg);
anthony72feaa62012-01-17 06:46:23 +0000514 (void) QueryColorCompliance(arg,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000515 &image_info->border_color,exception);
anthonydcf510d2011-10-30 13:51:40 +0000516 (void) QueryColorCompliance(arg,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000517 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000518 break;
519 }
anthony74b1cfc2011-10-06 12:44:16 +0000520 (void) DeleteImageOption(image_info,option);
521 (void) QueryColorCompliance(BorderColor,AllCompliance,
522 &image_info->border_color,exception);
523 (void) QueryColorCompliance(BorderColor,AllCompliance,
524 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000525 break;
526 }
anthony74b1cfc2011-10-06 12:44:16 +0000527 if (LocaleCompare("box",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000528 {
anthonyfd706f92012-01-19 04:22:02 +0000529 /* DEPRECIATED - now "undercolor" */
anthonyd1447672012-01-19 05:33:53 +0000530 WandSettingOptionInfo(wand,"undercolor",arg);
anthonyfd706f92012-01-19 04:22:02 +0000531 break;
anthony805a2d42011-09-25 08:25:12 +0000532 }
533 break;
534 }
535 case 'c':
536 {
anthony74b1cfc2011-10-06 12:44:16 +0000537 if (LocaleCompare("cache",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000538 {
539 MagickSizeType
540 limit;
541
542 limit=MagickResourceInfinity;
anthonydcf510d2011-10-30 13:51:40 +0000543 if (LocaleCompare("unlimited",arg) != 0)
cristy9b34e302011-11-05 02:15:45 +0000544 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg,100.0);
anthony805a2d42011-09-25 08:25:12 +0000545 (void) SetMagickResourceLimit(MemoryResource,limit);
546 (void) SetMagickResourceLimit(MapResource,2*limit);
547 break;
548 }
anthony74b1cfc2011-10-06 12:44:16 +0000549 if (LocaleCompare("caption",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000550 {
anthony72feaa62012-01-17 06:46:23 +0000551 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000552 break;
553 }
anthony74b1cfc2011-10-06 12:44:16 +0000554 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000555 {
anthony31f1bf72012-01-30 12:37:22 +0000556 /* This is applied to images in SimpleImageOperator!!!
557 FUTURE: move it to SyncImageSettings() - or alternative
558 */
anthony74b1cfc2011-10-06 12:44:16 +0000559 image_info->channel=(ChannelType) (
anthonydcf510d2011-10-30 13:51:40 +0000560 IfSetOption ? ParseChannelOption(arg) : DefaultChannels );
anthony805a2d42011-09-25 08:25:12 +0000561 break;
562 }
anthony74b1cfc2011-10-06 12:44:16 +0000563 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000564 {
anthonyafbaed72011-10-26 12:05:04 +0000565 /* Setting used for new images via AquireImage()
566 But also used as a SimpleImageOperator
567 Undefined colorspace means don't modify images on
568 read or as a operation */
anthony72feaa62012-01-17 06:46:23 +0000569 image_info->colorspace=(ColorspaceType) ParseCommandOption(
570 MagickColorspaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000571 break;
572 }
anthony74b1cfc2011-10-06 12:44:16 +0000573 if (LocaleCompare("comment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000574 {
anthony72feaa62012-01-17 06:46:23 +0000575 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000576 break;
577 }
anthony74b1cfc2011-10-06 12:44:16 +0000578 if (LocaleCompare("compose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000579 {
anthony72feaa62012-01-17 06:46:23 +0000580 /* FUTURE: image_info should be used,
581 SyncImageSettings() used to set per-image attribute. - REMOVE
582
anthonyafbaed72011-10-26 12:05:04 +0000583 This setting should NOT be used to set image 'compose'
anthony72feaa62012-01-17 06:46:23 +0000584 "-layer" operators shoud use image_info if defined otherwise
585 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000586 */
anthony72feaa62012-01-17 06:46:23 +0000587 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony965524b2011-10-07 12:34:14 +0000588 image_info->compose=(CompositeOperator) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000589 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000590 break;
591 }
anthony74b1cfc2011-10-06 12:44:16 +0000592 if (LocaleCompare("compress",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000593 {
anthony5f867ae2011-10-09 10:28:34 +0000594 /* FUTURE: What should be used? image_info or ImageOption ???
595 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000596 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000597
598 The coders appears to use image_info, not Image_Option
599 however the image attribute (for save) is set from the
600 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000601
602 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000603 */
anthony72feaa62012-01-17 06:46:23 +0000604 (void) SetImageOption(image_info,option,ArgOption(NULL));
605 image_info->compression=(CompressionType) ParseCommandOption(
606 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000607 break;
608 }
609 break;
610 }
611 case 'd':
612 {
anthony74b1cfc2011-10-06 12:44:16 +0000613 if (LocaleCompare("debug",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000614 {
anthony72feaa62012-01-17 06:46:23 +0000615 /* SyncImageSettings() used to set per-image attribute. */
616 (void) SetLogEventMask(ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000617 image_info->debug=IsEventLogging(); /* extract logging*/
618 wand->debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000619 break;
620 }
anthony74b1cfc2011-10-06 12:44:16 +0000621 if (LocaleCompare("define",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000622 {
anthony72feaa62012-01-17 06:46:23 +0000623 /* DefineImageOption() equals SetImageOption() but with '='
624 It does not however set individual image options.
625 -set will set individual image options as well!
anthony5f867ae2011-10-09 10:28:34 +0000626 */
anthonydcf510d2011-10-30 13:51:40 +0000627 if (LocaleNCompare(arg,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000628 {
anthony5f867ae2011-10-09 10:28:34 +0000629 if (IfSetOption)
anthonydcf510d2011-10-30 13:51:40 +0000630 (void) DefineImageRegistry(StringRegistryType,arg+9,
anthony5f867ae2011-10-09 10:28:34 +0000631 exception);
632 else
anthony72feaa62012-01-17 06:46:23 +0000633 (void) DeleteImageRegistry(arg+9);
anthony805a2d42011-09-25 08:25:12 +0000634 break;
635 }
anthony5f867ae2011-10-09 10:28:34 +0000636 if (IfSetOption)
anthony72feaa62012-01-17 06:46:23 +0000637 (void) DefineImageOption(image_info,arg);
anthony5f867ae2011-10-09 10:28:34 +0000638 else
anthony72feaa62012-01-17 06:46:23 +0000639 (void) DeleteImageOption(image_info,arg);
anthony805a2d42011-09-25 08:25:12 +0000640 break;
641 }
anthony74b1cfc2011-10-06 12:44:16 +0000642 if (LocaleCompare("delay",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000643 {
anthonyafbaed72011-10-26 12:05:04 +0000644 /* Only used for new images via AcquireImage()
645 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000646 */
anthony72feaa62012-01-17 06:46:23 +0000647 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000648 break;
649 }
anthony74b1cfc2011-10-06 12:44:16 +0000650 if (LocaleCompare("density",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000651 {
anthony72feaa62012-01-17 06:46:23 +0000652 /* FUTURE: strings used in image_info attr and draw_info!
653 Basically as density can be in a XxY form!
654
655 SyncImageSettings() used to set per-image attribute.
656 */
657 (void) SetImageOption(image_info,option,ArgOption(NULL));
658 (void) CloneString(&image_info->density,ArgOption(NULL));
659 (void) CloneString(&draw_info->density,image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000660 break;
661 }
anthony74b1cfc2011-10-06 12:44:16 +0000662 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000663 {
anthony72feaa62012-01-17 06:46:23 +0000664 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
665 SyncImageSettings() used to set per-image attribute.
666 */
anthonydcf510d2011-10-30 13:51:40 +0000667 image_info->depth=IfSetOption?StringToUnsignedLong(arg)
anthony5f867ae2011-10-09 10:28:34 +0000668 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000669 break;
670 }
anthony74b1cfc2011-10-06 12:44:16 +0000671 if (LocaleCompare("direction",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000672 {
anthony6dc09cd2011-10-12 08:56:49 +0000673 /* Image Option is only used to set draw_info */
anthony72feaa62012-01-17 06:46:23 +0000674 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony5f867ae2011-10-09 10:28:34 +0000675 draw_info->direction=(DirectionType) ParseCommandOption(
676 MagickDirectionOptions,MagickFalse,
anthony72feaa62012-01-17 06:46:23 +0000677 ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000678 break;
679 }
anthony74b1cfc2011-10-06 12:44:16 +0000680 if (LocaleCompare("display",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000681 {
anthony72feaa62012-01-17 06:46:23 +0000682 (void) CloneString(&image_info->server_name,ArgOption(NULL));
683 (void) CloneString(&draw_info->server_name,image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000684 break;
685 }
anthony74b1cfc2011-10-06 12:44:16 +0000686 if (LocaleCompare("dispose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000687 {
anthony72feaa62012-01-17 06:46:23 +0000688 /* only used in setting new images */
689 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000690 break;
691 }
anthony74b1cfc2011-10-06 12:44:16 +0000692 if (LocaleCompare("dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000693 {
anthony72feaa62012-01-17 06:46:23 +0000694 /* image_info attr (on/off), quantize_info attr (on/off)
695 but also ImageInfo and quantize_info method!
696 FUTURE: merge the duality of the dithering options
697 */
698 image_info->dither = quantize_info->dither = ArgBoolean;
699 (void) SetImageOption(image_info,option,ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000700 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000701 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000702 if (quantize_info->dither_method == NoDitherMethod)
anthony72feaa62012-01-17 06:46:23 +0000703 image_info->dither = quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000704 break;
705 }
706 break;
707 }
708 case 'e':
709 {
anthony74b1cfc2011-10-06 12:44:16 +0000710 if (LocaleCompare("encoding",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000711 {
anthony72feaa62012-01-17 06:46:23 +0000712 (void) CloneString(&draw_info->encoding,ArgOption("undefined"));
713 (void) SetImageOption(image_info,option,draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000714 break;
715 }
anthony74b1cfc2011-10-06 12:44:16 +0000716 if (LocaleCompare("endian",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000717 {
anthony72feaa62012-01-17 06:46:23 +0000718 /* Both image_info attr and ImageInfo */
719 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000720 image_info->endian=(EndianType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000721 MagickEndianOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000722 break;
723 }
anthony74b1cfc2011-10-06 12:44:16 +0000724 if (LocaleCompare("extract",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000725 {
anthony72feaa62012-01-17 06:46:23 +0000726 (void) CloneString(&image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000727 break;
728 }
729 break;
730 }
731 case 'f':
732 {
anthony72feaa62012-01-17 06:46:23 +0000733 if (LocaleCompare("family",option) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000734 {
anthony72feaa62012-01-17 06:46:23 +0000735 (void) CloneString(&draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000736 break;
737 }
anthony74b1cfc2011-10-06 12:44:16 +0000738 if (LocaleCompare("fill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000739 {
anthonyfd706f92012-01-19 04:22:02 +0000740 /* Set "fill" OR "fill-pattern" in draw_info
741 The original fill color is preserved if a fill-pattern is given.
742 That way it does not effect other operations that directly using
743 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000744 */
anthony6dc09cd2011-10-12 08:56:49 +0000745 const char
anthony72feaa62012-01-17 06:46:23 +0000746 *value;
747
748 MagickBooleanType
749 status;
anthony6dc09cd2011-10-12 08:56:49 +0000750
751 ExceptionInfo
752 *sans;
753
anthonyfd706f92012-01-19 04:22:02 +0000754 PixelInfo
755 color;
756
anthony72feaa62012-01-17 06:46:23 +0000757 value = ArgOption("none");
anthony6dc09cd2011-10-12 08:56:49 +0000758 (void) SetImageOption(image_info,option,value);
anthony6dc09cd2011-10-12 08:56:49 +0000759 if (draw_info->fill_pattern != (Image *) NULL)
760 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000761
762 /* is it a color or a image? -- ignore exceptions */
763 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +0000764 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000765 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000766
anthony6dc09cd2011-10-12 08:56:49 +0000767 if (status == MagickFalse)
anthony72feaa62012-01-17 06:46:23 +0000768 draw_info->fill_pattern=GetImageCache(image_info,value,exception);
anthonyfd706f92012-01-19 04:22:02 +0000769 else
770 draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000771 break;
772 }
anthony74b1cfc2011-10-06 12:44:16 +0000773 if (LocaleCompare("filter",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000774 {
anthony72feaa62012-01-17 06:46:23 +0000775 /* SyncImageSettings() used to set per-image attribute. */
776 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000777 break;
778 }
anthonydcf510d2011-10-30 13:51:40 +0000779 if (LocaleCompare("font",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000780 {
anthony72feaa62012-01-17 06:46:23 +0000781 (void) CloneString(&draw_info->font,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000782 (void) CloneString(&image_info->font,draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000783 break;
784 }
anthony74b1cfc2011-10-06 12:44:16 +0000785 if (LocaleCompare("format",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000786 {
anthonydcf510d2011-10-30 13:51:40 +0000787 /* FUTURE: why the ping test, you could set ping after this! */
788 /*
anthony805a2d42011-09-25 08:25:12 +0000789 register const char
790 *q;
791
anthonydcf510d2011-10-30 13:51:40 +0000792 for (q=strchr(arg,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000793 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
794 image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000795 */
anthony72feaa62012-01-17 06:46:23 +0000796 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000797 break;
798 }
anthony74b1cfc2011-10-06 12:44:16 +0000799 if (LocaleCompare("fuzz",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000800 {
anthony72feaa62012-01-17 06:46:23 +0000801 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000802 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000803 SyncImageSettings() used to set per-image attribute.
804
805 Can't find anything else using image_info->fuzz directly!
anthony6613bf32011-10-15 07:24:44 +0000806 */
807 if (IfSetOption)
cristy947cb4c2011-10-20 18:41:46 +0000808 {
anthony80c37752012-01-16 01:03:11 +0000809 image_info->fuzz=StringToDoubleInterval(arg,(double)
810 QuantumRange+1.0);
anthonydcf510d2011-10-30 13:51:40 +0000811 (void) SetImageOption(image_info,option,arg);
cristy947cb4c2011-10-20 18:41:46 +0000812 break;
813 }
814 image_info->fuzz=0.0;
815 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +0000816 break;
817 }
818 break;
819 }
820 case 'g':
821 {
anthony74b1cfc2011-10-06 12:44:16 +0000822 if (LocaleCompare("gravity",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000823 {
anthony72feaa62012-01-17 06:46:23 +0000824 /* SyncImageSettings() used to set per-image attribute. */
825 (void) SetImageOption(image_info,option,ArgOption("none"));
anthony6dc09cd2011-10-12 08:56:49 +0000826 draw_info->gravity=(GravityType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000827 MagickGravityOptions,MagickFalse,ArgOption("none"));
anthony805a2d42011-09-25 08:25:12 +0000828 break;
829 }
anthony74b1cfc2011-10-06 12:44:16 +0000830 if (LocaleCompare("green-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000831 {
anthonydcf510d2011-10-30 13:51:40 +0000832 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000833 SyncImageSettings() used to set per-image attribute.
834 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000835 */
anthony72feaa62012-01-17 06:46:23 +0000836 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000837 break;
838 }
839 break;
840 }
841 case 'i':
842 {
anthony74b1cfc2011-10-06 12:44:16 +0000843 if (LocaleCompare("intent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000844 {
anthony72feaa62012-01-17 06:46:23 +0000845 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000846 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000847 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000848 */
anthony72feaa62012-01-17 06:46:23 +0000849 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000850 break;
851 }
anthony74b1cfc2011-10-06 12:44:16 +0000852 if (LocaleCompare("interlace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000853 {
anthony72feaa62012-01-17 06:46:23 +0000854 /* image_info is directly used by coders (so why an image setting?)
855 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000856 */
anthony72feaa62012-01-17 06:46:23 +0000857 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000858 image_info->interlace=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000859 MagickInterlaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000860 break;
861 }
anthony74b1cfc2011-10-06 12:44:16 +0000862 if (LocaleCompare("interline-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000863 {
anthony72feaa62012-01-17 06:46:23 +0000864 (void) SetImageOption(image_info,option, ArgOption(NULL));
865 draw_info->interline_spacing=StringToDouble(ArgOption("0"),
866 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000867 break;
868 }
anthony74b1cfc2011-10-06 12:44:16 +0000869 if (LocaleCompare("interpolate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000870 {
anthonyfd706f92012-01-19 04:22:02 +0000871 /* SyncImageSettings() used to set per-image attribute. */
anthony72feaa62012-01-17 06:46:23 +0000872 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000873 break;
874 }
cristy947cb4c2011-10-20 18:41:46 +0000875 if (LocaleCompare("interword-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000876 {
anthony72feaa62012-01-17 06:46:23 +0000877 (void) SetImageOption(image_info,option, ArgOption(NULL));
878 draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000879 break;
880 }
881 break;
882 }
883 case 'k':
884 {
anthony74b1cfc2011-10-06 12:44:16 +0000885 if (LocaleCompare("kerning",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000886 {
anthony72feaa62012-01-17 06:46:23 +0000887 (void) SetImageOption(image_info,option,ArgOption(NULL));
888 draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000889 break;
890 }
891 break;
892 }
893 case 'l':
894 {
anthony74b1cfc2011-10-06 12:44:16 +0000895 if (LocaleCompare("label",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000896 {
anthony72feaa62012-01-17 06:46:23 +0000897 /* only used for new images - not in SyncImageOptions() */
898 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000899 break;
900 }
anthony74b1cfc2011-10-06 12:44:16 +0000901 if (LocaleCompare("list",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000902 {
903 ssize_t
904 list;
905
anthonye8f56492012-02-12 12:39:02 +0000906 /* FUTURE: This is not really a Setting Option, but a Special
907 * The bulk of this should be turned into a MagickCore function
908 */
anthony72feaa62012-01-17 06:46:23 +0000909 list=ParseCommandOption(MagickListOptions,MagickFalse,
910 ArgOption("list"));
anthony805a2d42011-09-25 08:25:12 +0000911 switch (list)
912 {
913 case MagickCoderOptions:
914 {
915 (void) ListCoderInfo((FILE *) NULL,exception);
916 break;
917 }
918 case MagickColorOptions:
919 {
920 (void) ListColorInfo((FILE *) NULL,exception);
921 break;
922 }
923 case MagickConfigureOptions:
924 {
925 (void) ListConfigureInfo((FILE *) NULL,exception);
926 break;
927 }
928 case MagickDelegateOptions:
929 {
930 (void) ListDelegateInfo((FILE *) NULL,exception);
931 break;
932 }
933 case MagickFontOptions:
934 {
935 (void) ListTypeInfo((FILE *) NULL,exception);
936 break;
937 }
938 case MagickFormatOptions:
939 {
940 (void) ListMagickInfo((FILE *) NULL,exception);
941 break;
942 }
943 case MagickLocaleOptions:
944 {
945 (void) ListLocaleInfo((FILE *) NULL,exception);
946 break;
947 }
948 case MagickLogOptions:
949 {
950 (void) ListLogInfo((FILE *) NULL,exception);
951 break;
952 }
953 case MagickMagicOptions:
954 {
955 (void) ListMagicInfo((FILE *) NULL,exception);
956 break;
957 }
958 case MagickMimeOptions:
959 {
960 (void) ListMimeInfo((FILE *) NULL,exception);
961 break;
962 }
963 case MagickModuleOptions:
964 {
965 (void) ListModuleInfo((FILE *) NULL,exception);
966 break;
967 }
968 case MagickPolicyOptions:
969 {
970 (void) ListPolicyInfo((FILE *) NULL,exception);
971 break;
972 }
973 case MagickResourceOptions:
974 {
975 (void) ListMagickResourceInfo((FILE *) NULL,exception);
976 break;
977 }
978 case MagickThresholdOptions:
979 {
980 (void) ListThresholdMaps((FILE *) NULL,exception);
981 break;
982 }
983 default:
984 {
985 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
986 exception);
987 break;
988 }
989 }
990 break;
991 }
anthony74b1cfc2011-10-06 12:44:16 +0000992 if (LocaleCompare("log",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000993 {
anthonydcf510d2011-10-30 13:51:40 +0000994 if (IfSetOption)
995 (void) SetLogFormat(arg);
anthony805a2d42011-09-25 08:25:12 +0000996 break;
997 }
anthony74b1cfc2011-10-06 12:44:16 +0000998 if (LocaleCompare("loop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000999 {
anthony72feaa62012-01-17 06:46:23 +00001000 /* SyncImageSettings() used to set per-image attribute. */
1001 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001002 break;
1003 }
1004 break;
1005 }
1006 case 'm':
1007 {
anthony74b1cfc2011-10-06 12:44:16 +00001008 if (LocaleCompare("mattecolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001009 {
anthony72feaa62012-01-17 06:46:23 +00001010 /* SyncImageSettings() used to set per-image attribute. */
1011 (void) SetImageOption(image_info,option,ArgOption(NULL));
1012 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1013 &image_info->matte_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001014 break;
1015 }
anthony74b1cfc2011-10-06 12:44:16 +00001016 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001017 {
anthony31f1bf72012-01-30 12:37:22 +00001018 (void) SetImageInfoProgressMonitor(image_info, IfSetOption?
1019 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001020 break;
1021 }
anthony74b1cfc2011-10-06 12:44:16 +00001022 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001023 {
anthony72feaa62012-01-17 06:46:23 +00001024 /* Setting (for some input coders)
1025 But also a special 'type' operator
1026 */
1027 image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001028 break;
1029 }
1030 break;
1031 }
1032 case 'o':
1033 {
anthony74b1cfc2011-10-06 12:44:16 +00001034 if (LocaleCompare("orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001035 {
anthony72feaa62012-01-17 06:46:23 +00001036 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001037 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001038 FUTURE: make set meta-data operator instead.
1039 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001040 */
anthony72feaa62012-01-17 06:46:23 +00001041 (void) SetImageOption(image_info,option, ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001042 image_info->orientation=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001043 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001044 break;
1045 }
1046 }
1047 case 'p':
1048 {
anthony74b1cfc2011-10-06 12:44:16 +00001049 if (LocaleCompare("page",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001050 {
anthony72feaa62012-01-17 06:46:23 +00001051 /* Only used for new images and image generators
1052 SyncImageSettings() used to set per-image attribute. ?????
1053 That last is WRONG!!!!
1054 */
anthony805a2d42011-09-25 08:25:12 +00001055 char
1056 *canonical_page,
1057 page[MaxTextExtent];
1058
1059 const char
1060 *image_option;
1061
1062 MagickStatusType
1063 flags;
1064
1065 RectangleInfo
1066 geometry;
1067
anthonydcf510d2011-10-30 13:51:40 +00001068 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001069 {
anthony74b1cfc2011-10-06 12:44:16 +00001070 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +00001071 (void) CloneString(&image_info->page,(char *) NULL);
1072 break;
1073 }
1074 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1075 image_option=GetImageOption(image_info,"page");
1076 if (image_option != (const char *) NULL)
1077 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthonydcf510d2011-10-30 13:51:40 +00001078 canonical_page=GetPageGeometry(arg);
anthony805a2d42011-09-25 08:25:12 +00001079 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1080 canonical_page=DestroyString(canonical_page);
1081 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1082 (unsigned long) geometry.width,(unsigned long) geometry.height);
1083 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1084 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1085 (unsigned long) geometry.width,(unsigned long) geometry.height,
1086 (long) geometry.x,(long) geometry.y);
anthony74b1cfc2011-10-06 12:44:16 +00001087 (void) SetImageOption(image_info,option,page);
anthony805a2d42011-09-25 08:25:12 +00001088 (void) CloneString(&image_info->page,page);
1089 break;
1090 }
anthony74b1cfc2011-10-06 12:44:16 +00001091 if (LocaleCompare("ping",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001092 {
anthony72feaa62012-01-17 06:46:23 +00001093 image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001094 break;
1095 }
anthony74b1cfc2011-10-06 12:44:16 +00001096 if (LocaleCompare("pointsize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001097 {
anthony72feaa62012-01-17 06:46:23 +00001098 image_info->pointsize=draw_info->pointsize=
1099 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001100 break;
1101 }
anthony74b1cfc2011-10-06 12:44:16 +00001102 if (LocaleCompare("precision",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001103 {
anthony72feaa62012-01-17 06:46:23 +00001104 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001105 break;
1106 }
anthonydcf510d2011-10-30 13:51:40 +00001107 /* FUTURE: Only the 'preview' coder appears to use this
1108 * Depreciate the coder? Leaving only the 'preview' operator.
anthony74b1cfc2011-10-06 12:44:16 +00001109 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001110 {
anthonydcf510d2011-10-30 13:51:40 +00001111 image_info->preview_type=UndefinedPreview;
1112 if (IfSetOption)
1113 image_info->preview_type=(PreviewType) ParseCommandOption(
1114 MagickPreviewOptions,MagickFalse,arg);
anthony805a2d42011-09-25 08:25:12 +00001115 break;
1116 }
anthonydcf510d2011-10-30 13:51:40 +00001117 */
anthony805a2d42011-09-25 08:25:12 +00001118 break;
1119 }
1120 case 'q':
1121 {
anthony74b1cfc2011-10-06 12:44:16 +00001122 if (LocaleCompare("quality",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001123 {
anthony72feaa62012-01-17 06:46:23 +00001124 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001125 image_info->quality=UndefinedCompressionQuality;
anthony72feaa62012-01-17 06:46:23 +00001126 if (IfSetOption)
1127 image_info->quality=StringToUnsignedLong(arg);
anthony805a2d42011-09-25 08:25:12 +00001128 break;
1129 }
anthonyafbaed72011-10-26 12:05:04 +00001130 if (LocaleCompare("quantize",option) == 0)
1131 {
anthony72feaa62012-01-17 06:46:23 +00001132 /* Just a set direct in quantize_info */
anthonyafbaed72011-10-26 12:05:04 +00001133 quantize_info->colorspace=UndefinedColorspace;
1134 if (IfSetOption)
1135 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthonydcf510d2011-10-30 13:51:40 +00001136 MagickColorspaceOptions,MagickFalse,arg);
anthonyafbaed72011-10-26 12:05:04 +00001137 break;
1138 }
anthony74b1cfc2011-10-06 12:44:16 +00001139 if (LocaleCompare("quiet",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001140 {
anthonydcf510d2011-10-30 13:51:40 +00001141 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001142 static WarningHandler
1143 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001144
anthonyafbaed72011-10-26 12:05:04 +00001145 WarningHandler
1146 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001147
anthonyafbaed72011-10-26 12:05:04 +00001148 if ( tmp != (WarningHandler) NULL)
1149 warning_handler = tmp; /* remember the old handler */
1150 if (!IfSetOption) /* set the old handler */
1151 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001152 break;
1153 }
1154 break;
1155 }
1156 case 'r':
1157 {
anthony74b1cfc2011-10-06 12:44:16 +00001158 if (LocaleCompare("red-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001159 {
anthonydcf510d2011-10-30 13:51:40 +00001160 /* Image chromaticity X,Y NB: Y=X if Y not defined
1161 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001162 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001163 */
anthony72feaa62012-01-17 06:46:23 +00001164 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001165 break;
1166 }
anthonyafbaed72011-10-26 12:05:04 +00001167 if (LocaleCompare("render",option) == 0)
1168 {
1169 /* draw_info only setting */
1170 draw_info->render= IfSetOption ? MagickFalse : MagickTrue;
1171 break;
1172 }
anthony805a2d42011-09-25 08:25:12 +00001173 break;
1174 }
1175 case 's':
1176 {
anthony74b1cfc2011-10-06 12:44:16 +00001177 if (LocaleCompare("sampling-factor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001178 {
anthonyafbaed72011-10-26 12:05:04 +00001179 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony72feaa62012-01-17 06:46:23 +00001180 (void) CloneString(&image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001181 break;
1182 }
anthony74b1cfc2011-10-06 12:44:16 +00001183 if (LocaleCompare("scene",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001184 {
anthony72feaa62012-01-17 06:46:23 +00001185 /* SyncImageSettings() used to set per-image attribute.
1186 What ??? Why ????
1187 */
1188 (void) SetImageOption(image_info,option,ArgOption(NULL));
1189 image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001190 break;
1191 }
anthony74b1cfc2011-10-06 12:44:16 +00001192 if (LocaleCompare("seed",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001193 {
anthonyafbaed72011-10-26 12:05:04 +00001194 SeedPseudoRandomGenerator(
anthonydcf510d2011-10-30 13:51:40 +00001195 IfSetOption ? (size_t) StringToUnsignedLong(arg)
anthonyafbaed72011-10-26 12:05:04 +00001196 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001197 break;
1198 }
anthony74b1cfc2011-10-06 12:44:16 +00001199 if (LocaleCompare("size",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001200 {
anthonyafbaed72011-10-26 12:05:04 +00001201 /* FUTURE: string in image_info -- convert to Option ???
1202 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001203 */
anthony72feaa62012-01-17 06:46:23 +00001204 (void) CloneString(&image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001205 break;
1206 }
1207 if (LocaleCompare("stretch",option) == 0)
1208 {
anthony72feaa62012-01-17 06:46:23 +00001209 draw_info->stretch=(StretchType) ParseCommandOption(
1210 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001211 break;
1212 }
anthony74b1cfc2011-10-06 12:44:16 +00001213 if (LocaleCompare("stroke",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001214 {
anthonyafbaed72011-10-26 12:05:04 +00001215 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001216 UPDATE: ensure stroke color is not destroyed is a pattern
1217 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001218 */
1219 const char
anthony72feaa62012-01-17 06:46:23 +00001220 *value;
1221
1222 MagickBooleanType
1223 status;
anthonyafbaed72011-10-26 12:05:04 +00001224
1225 ExceptionInfo
1226 *sans;
1227
anthonyfd706f92012-01-19 04:22:02 +00001228 PixelInfo
1229 color;
1230
anthony72feaa62012-01-17 06:46:23 +00001231 value = ArgOption("none");
anthonyafbaed72011-10-26 12:05:04 +00001232 (void) SetImageOption(image_info,option,value);
anthony72feaa62012-01-17 06:46:23 +00001233 if (draw_info->stroke_pattern != (Image *) NULL)
1234 draw_info->stroke_pattern=DestroyImage(draw_info->stroke_pattern);
1235
1236 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001237 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +00001238 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001239 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001240
anthonyafbaed72011-10-26 12:05:04 +00001241 if (status == MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00001242 draw_info->stroke_pattern=GetImageCache(image_info,value,exception);
1243 else
1244 draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001245 break;
1246 }
anthony74b1cfc2011-10-06 12:44:16 +00001247 if (LocaleCompare("strokewidth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001248 {
anthony72feaa62012-01-17 06:46:23 +00001249 (void) SetImageOption(image_info,option,ArgOption(NULL));
1250 draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1251 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001252 break;
1253 }
1254 if (LocaleCompare("style",option) == 0)
1255 {
anthony72feaa62012-01-17 06:46:23 +00001256 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1257 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001258 break;
1259 }
anthony74b1cfc2011-10-06 12:44:16 +00001260 if (LocaleCompare("synchronize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001261 {
anthony72feaa62012-01-17 06:46:23 +00001262 image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001263 break;
1264 }
1265 break;
1266 }
1267 case 't':
1268 {
anthony74b1cfc2011-10-06 12:44:16 +00001269 if (LocaleCompare("taint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001270 {
anthony72feaa62012-01-17 06:46:23 +00001271 /* SyncImageSettings() used to set per-image attribute. */
anthonyafbaed72011-10-26 12:05:04 +00001272 (void) SetImageOption(image_info,option,
1273 IfSetOption ? "true" : "false");
anthony805a2d42011-09-25 08:25:12 +00001274 break;
1275 }
anthony74b1cfc2011-10-06 12:44:16 +00001276 if (LocaleCompare("texture",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001277 {
anthonyafbaed72011-10-26 12:05:04 +00001278 /* FUTURE: move image_info string to option splay-tree */
anthony72feaa62012-01-17 06:46:23 +00001279 (void) CloneString(&image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001280 break;
1281 }
1282 if (LocaleCompare("tile",option) == 0)
1283 {
anthony72feaa62012-01-17 06:46:23 +00001284 draw_info->fill_pattern=IfSetOption
1285 ?GetImageCache(image_info,arg,exception)
1286 :DestroyImage(draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001287 break;
1288 }
anthony74b1cfc2011-10-06 12:44:16 +00001289 if (LocaleCompare("tile-offset",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001290 {
anthony72feaa62012-01-17 06:46:23 +00001291 /* SyncImageSettings() used to set per-image attribute. ??? */
1292 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001293 break;
1294 }
anthony74b1cfc2011-10-06 12:44:16 +00001295 if (LocaleCompare("transparent-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001296 {
anthonyafbaed72011-10-26 12:05:04 +00001297 /* FUTURE: both image_info attribute & ImageOption in use!
1298 image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001299 SyncImageSettings() used to set per-image attribute.
1300
anthonyafbaed72011-10-26 12:05:04 +00001301 Note that +transparent-color, means fall-back to image
1302 attribute so ImageOption is deleted, not set to a default.
1303 */
anthony72feaa62012-01-17 06:46:23 +00001304 (void) SetImageOption(image_info,option,ArgOption(NULL));
1305 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1306 &image_info->transparent_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001307 break;
1308 }
anthony31f1bf72012-01-30 12:37:22 +00001309 if (LocaleCompare("treedepth",option) == 0)
1310 {
1311 (void) SetImageOption(image_info,option,ArgOption(NULL));
1312 quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1313 break;
1314 }
anthony74b1cfc2011-10-06 12:44:16 +00001315 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001316 {
anthony72feaa62012-01-17 06:46:23 +00001317 /* SyncImageSettings() used to set per-image attribute. */
1318 (void) SetImageOption(image_info,option,ArgOption(NULL));
1319 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1320 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001321 break;
1322 }
1323 break;
1324 }
1325 case 'u':
1326 {
anthony74b1cfc2011-10-06 12:44:16 +00001327 if (LocaleCompare("undercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001328 {
anthony72feaa62012-01-17 06:46:23 +00001329 (void) SetImageOption(image_info,option,ArgOption(NULL));
1330 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1331 &draw_info->undercolor,exception);
anthony805a2d42011-09-25 08:25:12 +00001332 break;
1333 }
anthony74b1cfc2011-10-06 12:44:16 +00001334 if (LocaleCompare("units",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001335 {
anthony72feaa62012-01-17 06:46:23 +00001336 /* SyncImageSettings() used to set per-image attribute.
1337 Should this effect draw_info X and Y resolution?
1338 FUTURE: this probably should be part of the density setting
1339 */
1340 (void) SetImageOption(image_info,option,ArgOption(NULL));
1341 image_info->units=(ResolutionType) ParseCommandOption(
1342 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001343 break;
1344 }
1345 break;
1346 }
1347 case 'v':
1348 {
anthony74b1cfc2011-10-06 12:44:16 +00001349 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001350 {
anthonyab3a50c2011-10-27 11:48:57 +00001351 /* FUTURE: Also an image artifact, set in Simple Operators.
1352 But artifact is only used in verbose output.
1353 */
anthony31f1bf72012-01-30 12:37:22 +00001354 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001355 image_info->verbose= ArgBoolean;
anthonyab3a50c2011-10-27 11:48:57 +00001356 image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001357 break;
1358 }
anthony74b1cfc2011-10-06 12:44:16 +00001359 if (LocaleCompare("view",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001360 {
anthony72feaa62012-01-17 06:46:23 +00001361 /* FUTURE: Convert from image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001362 Only used by coder FPX
1363 */
anthony72feaa62012-01-17 06:46:23 +00001364 (void) CloneString(&image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001365 break;
1366 }
anthony74b1cfc2011-10-06 12:44:16 +00001367 if (LocaleCompare("virtual-pixel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001368 {
anthonyfd706f92012-01-19 04:22:02 +00001369 /* SyncImageSettings() used to set per-image attribute.
1370 This is VERY deep in the image caching structure.
1371 */
anthony72feaa62012-01-17 06:46:23 +00001372 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001373 break;
1374 }
1375 break;
1376 }
1377 case 'w':
1378 {
anthonydcf510d2011-10-30 13:51:40 +00001379 if (LocaleCompare("weight",option) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001380 {
anthony72feaa62012-01-17 06:46:23 +00001381 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001382 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001383 */
anthony72feaa62012-01-17 06:46:23 +00001384 if (!IfSetOption)
1385 break;
anthonydcf510d2011-10-30 13:51:40 +00001386 draw_info->weight=StringToUnsignedLong(arg);
1387 if (LocaleCompare(arg,"all") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001388 draw_info->weight=0;
anthonydcf510d2011-10-30 13:51:40 +00001389 if (LocaleCompare(arg,"bold") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001390 draw_info->weight=700;
anthonydcf510d2011-10-30 13:51:40 +00001391 if (LocaleCompare(arg,"bolder") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001392 if (draw_info->weight <= 800)
1393 draw_info->weight+=100;
anthonydcf510d2011-10-30 13:51:40 +00001394 if (LocaleCompare(arg,"lighter") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001395 if (draw_info->weight >= 100)
1396 draw_info->weight-=100;
anthonydcf510d2011-10-30 13:51:40 +00001397 if (LocaleCompare(arg,"normal") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001398 draw_info->weight=400;
1399 break;
1400 }
anthony74b1cfc2011-10-06 12:44:16 +00001401 if (LocaleCompare("white-point",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001402 {
anthony72feaa62012-01-17 06:46:23 +00001403 /* Used as a image chromaticity setting
1404 SyncImageSettings() used to set per-image attribute.
1405 */
1406 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001407 break;
1408 }
1409 break;
1410 }
1411 default:
1412 break;
1413 }
anthonyfd706f92012-01-19 04:22:02 +00001414#undef image_info
1415#undef draw_info
1416#undef quantize_info
1417#undef exception
1418#undef IfSetOption
1419#undef ArgOption
1420#undef ArgBoolean
1421
anthony31f1bf72012-01-30 12:37:22 +00001422 return;
anthony805a2d42011-09-25 08:25:12 +00001423}
1424
1425/*
1426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1427% %
1428% %
1429% %
anthony31f1bf72012-01-30 12:37:22 +00001430+ W a n d 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 +00001431% %
1432% %
1433% %
1434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435%
anthony31f1bf72012-01-30 12:37:22 +00001436% WandSimpleOperatorImages() applys one simple image operation given to all
1437% the images in the current wand, with the settings that are saved in the
1438% CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001439%
1440% It is assumed that any per-image settings are up-to-date with respect to
1441% extra settings that have been saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001442%
anthonyd1447672012-01-19 05:33:53 +00001443% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001444%
anthony31f1bf72012-01-30 12:37:22 +00001445% void WandSimpleOperatorImages(MagickWand *wand,
anthonyfd706f92012-01-19 04:22:02 +00001446% const MagickBooleanType plus_alt_op, const char *option,
1447% const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001448%
1449% A description of each parameter follows:
1450%
anthonydcf510d2011-10-30 13:51:40 +00001451% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00001452%
anthonyfd706f92012-01-19 04:22:02 +00001453% o plus_alt_op: request the 'plus' or alturnative form of the operation
anthony805a2d42011-09-25 08:25:12 +00001454%
anthonyfd706f92012-01-19 04:22:02 +00001455% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001456%
anthonyfd706f92012-01-19 04:22:02 +00001457% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001458%
anthony31f1bf72012-01-30 12:37:22 +00001459% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001460%
anthony31f1bf72012-01-30 12:37:22 +00001461% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001462%
anthony36a8c2c2012-02-10 00:08:44 +00001463% WandSimpleOperatorImages(wand, MagickFalse,"crop","100x100+20+30",NULL);
1464% WandSimpleOperatorImages(wand, MagickTrue, "repage",NULL,NULL);
1465% WandSimpleOperatorImages(wand, MagickTrue, "distort","SRT","45");
anthony31f1bf72012-01-30 12:37:22 +00001466% if ( wand->exception->severity != UndefinedException ) {
1467% CatchException(exception);
1468% exit(1);
1469% }
anthonyfd706f92012-01-19 04:22:02 +00001470%
1471% Or for handling command line arguments EG: +/-option ["arg"]
anthonydcf510d2011-10-30 13:51:40 +00001472%
1473% argc,argv
1474% i=index in argv
1475%
1476% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
1477% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthonye8f56492012-02-12 12:39:02 +00001478% if ( (flags & SimpleOperatorOptionFlag) != 0 )
anthony36a8c2c2012-02-10 00:08:44 +00001479% WandSimpleOperatorImages(wand,
1480% ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
anthonyfd706f92012-01-19 04:22:02 +00001481% count>=1 ? argv[i+1] : (char *)NULL,
1482% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001483% i += count+1;
1484%
anthony805a2d42011-09-25 08:25:12 +00001485*/
anthony31f1bf72012-01-30 12:37:22 +00001486
1487/*
1488 Internal subrountine to apply one simple image operation to the current
1489 image pointed to by the wand.
1490
1491 The image in the list may be modified in three different ways...
1492 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1493 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1494 * one image replace by a list of images (-separate and -crop only!)
1495
1496 In each case the result replaces the original image in the list, as well as
1497 the pointer to the modified image (last image added if replaced by a list
1498 of images) is returned.
1499
1500 As the image pointed to may be replaced, the first image in the list may
1501 also change. GetFirstImageInList() should be used by caller if they wish
1502 return the Image pointer to the first image in list.
1503*/
anthony36a8c2c2012-02-10 00:08:44 +00001504static void WandSimpleOperatorImage(MagickWand *wand,
1505 const MagickBooleanType plus_alt_op, const char *option,
1506 const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001507{
1508 Image *
1509 new_image;
1510
anthony805a2d42011-09-25 08:25:12 +00001511 GeometryInfo
1512 geometry_info;
1513
1514 RectangleInfo
1515 geometry;
1516
1517 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001518 flags;
1519
anthonyfd706f92012-01-19 04:22:02 +00001520#define image_info (wand->image_info)
1521#define draw_info (wand->draw_info)
1522#define quantize_info (wand->quantize_info)
anthony31f1bf72012-01-30 12:37:22 +00001523#define image (wand->images)
1524#define exception (wand->exception)
1525#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001526
anthony805a2d42011-09-25 08:25:12 +00001527 assert(image_info != (const ImageInfo *) NULL);
1528 assert(image_info->signature == MagickSignature);
anthony31f1bf72012-01-30 12:37:22 +00001529 assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
1530 assert(image != (Image *) NULL); /* there is an image */
1531 assert(image->signature == MagickSignature); /* and is a valid image */
anthonydcf510d2011-10-30 13:51:40 +00001532
1533 if (wand->debug != MagickFalse)
1534 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1535
anthony805a2d42011-09-25 08:25:12 +00001536 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001537
anthonydcf510d2011-10-30 13:51:40 +00001538 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001539
anthonyfd706f92012-01-19 04:22:02 +00001540 /* FUTURE: We may need somthing a little more optimized than this!
1541 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1542 */
anthony31f1bf72012-01-30 12:37:22 +00001543 (void) SyncImageSettings(image_info,image,exception);
anthonydcf510d2011-10-30 13:51:40 +00001544
1545 switch (*option)
anthony805a2d42011-09-25 08:25:12 +00001546 {
1547 case 'a':
1548 {
anthonydcf510d2011-10-30 13:51:40 +00001549 if (LocaleCompare("adaptive-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001550 {
anthonyfd706f92012-01-19 04:22:02 +00001551 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001552 if ((flags & SigmaValue) == 0)
1553 geometry_info.sigma=1.0;
1554 if ((flags & XiValue) == 0)
1555 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001556 new_image=AdaptiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001557 geometry_info.sigma,geometry_info.xi,exception);
1558 break;
1559 }
anthonydcf510d2011-10-30 13:51:40 +00001560 if (LocaleCompare("adaptive-resize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001561 {
anthony31f1bf72012-01-30 12:37:22 +00001562 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
1563 new_image=AdaptiveResizeImage(image,geometry.width,geometry.height,
anthonyfd706f92012-01-19 04:22:02 +00001564 exception);
anthony805a2d42011-09-25 08:25:12 +00001565 break;
1566 }
anthonydcf510d2011-10-30 13:51:40 +00001567 if (LocaleCompare("adaptive-sharpen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001568 {
anthonyfd706f92012-01-19 04:22:02 +00001569 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001570 if ((flags & SigmaValue) == 0)
1571 geometry_info.sigma=1.0;
1572 if ((flags & XiValue) == 0)
1573 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001574 new_image=AdaptiveSharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001575 geometry_info.sigma,geometry_info.xi,exception);
1576 break;
1577 }
anthonydcf510d2011-10-30 13:51:40 +00001578 if (LocaleCompare("alpha",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001579 {
1580 AlphaChannelType
1581 alpha_type;
1582
anthony805a2d42011-09-25 08:25:12 +00001583 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
anthonyfd706f92012-01-19 04:22:02 +00001584 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00001585 (void) SetImageAlphaChannel(image,alpha_type,exception);
anthony805a2d42011-09-25 08:25:12 +00001586 break;
1587 }
anthonydcf510d2011-10-30 13:51:40 +00001588 if (LocaleCompare("annotate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001589 {
1590 char
1591 *text,
1592 geometry[MaxTextExtent];
1593
anthony805a2d42011-09-25 08:25:12 +00001594 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001595 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001596 if ((flags & SigmaValue) == 0)
1597 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00001598 text=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00001599 exception);
1600 if (text == (char *) NULL)
1601 break;
1602 (void) CloneString(&draw_info->text,text);
1603 text=DestroyString(text);
1604 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1605 geometry_info.xi,geometry_info.psi);
1606 (void) CloneString(&draw_info->geometry,geometry);
1607 draw_info->affine.sx=cos(DegreesToRadians(
1608 fmod(geometry_info.rho,360.0)));
1609 draw_info->affine.rx=sin(DegreesToRadians(
1610 fmod(geometry_info.rho,360.0)));
1611 draw_info->affine.ry=(-sin(DegreesToRadians(
1612 fmod(geometry_info.sigma,360.0))));
1613 draw_info->affine.sy=cos(DegreesToRadians(
1614 fmod(geometry_info.sigma,360.0)));
anthony31f1bf72012-01-30 12:37:22 +00001615 (void) AnnotateImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00001616 GetAffineMatrix(&draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001617 break;
1618 }
anthonydcf510d2011-10-30 13:51:40 +00001619 if (LocaleCompare("auto-gamma",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001620 {
anthony31f1bf72012-01-30 12:37:22 +00001621 (void) AutoGammaImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001622 break;
1623 }
anthonydcf510d2011-10-30 13:51:40 +00001624 if (LocaleCompare("auto-level",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001625 {
anthony31f1bf72012-01-30 12:37:22 +00001626 (void) AutoLevelImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001627 break;
1628 }
anthonydcf510d2011-10-30 13:51:40 +00001629 if (LocaleCompare("auto-orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001630 {
anthony31f1bf72012-01-30 12:37:22 +00001631 switch (image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001632 {
1633 case TopRightOrientation:
1634 {
anthony31f1bf72012-01-30 12:37:22 +00001635 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001636 break;
1637 }
1638 case BottomRightOrientation:
1639 {
anthony31f1bf72012-01-30 12:37:22 +00001640 new_image=RotateImage(image,180.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001641 break;
1642 }
1643 case BottomLeftOrientation:
1644 {
anthony31f1bf72012-01-30 12:37:22 +00001645 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001646 break;
1647 }
1648 case LeftTopOrientation:
1649 {
anthony31f1bf72012-01-30 12:37:22 +00001650 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001651 break;
1652 }
1653 case RightTopOrientation:
1654 {
anthony31f1bf72012-01-30 12:37:22 +00001655 new_image=RotateImage(image,90.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001656 break;
1657 }
1658 case RightBottomOrientation:
1659 {
anthony31f1bf72012-01-30 12:37:22 +00001660 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001661 break;
1662 }
1663 case LeftBottomOrientation:
1664 {
anthony31f1bf72012-01-30 12:37:22 +00001665 new_image=RotateImage(image,270.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001666 break;
1667 }
1668 default:
1669 break;
1670 }
1671 if (new_image != (Image *) NULL)
1672 new_image->orientation=TopLeftOrientation;
1673 break;
1674 }
1675 break;
1676 }
1677 case 'b':
1678 {
anthonydcf510d2011-10-30 13:51:40 +00001679 if (LocaleCompare("black-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001680 {
anthony31f1bf72012-01-30 12:37:22 +00001681 (void) BlackThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001682 break;
1683 }
anthonydcf510d2011-10-30 13:51:40 +00001684 if (LocaleCompare("blue-shift",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001685 {
anthony805a2d42011-09-25 08:25:12 +00001686 geometry_info.rho=1.5;
anthonyfd706f92012-01-19 04:22:02 +00001687 if (plus_alt_op == MagickFalse)
1688 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00001689 new_image=BlueShiftImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00001690 break;
1691 }
anthonydcf510d2011-10-30 13:51:40 +00001692 if (LocaleCompare("blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001693 {
anthony74b1cfc2011-10-06 12:44:16 +00001694 /* FUTURE: use of "bias" in a blur is non-sensible */
anthonyfd706f92012-01-19 04:22:02 +00001695 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001696 if ((flags & SigmaValue) == 0)
1697 geometry_info.sigma=1.0;
1698 if ((flags & XiValue) == 0)
1699 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001700 new_image=BlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001701 geometry_info.sigma,geometry_info.xi,exception);
1702 break;
1703 }
anthonydcf510d2011-10-30 13:51:40 +00001704 if (LocaleCompare("border",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001705 {
anthony31f1bf72012-01-30 12:37:22 +00001706 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001707 compose;
1708
1709 const char*
anthony5f867ae2011-10-09 10:28:34 +00001710 value;
1711
1712 value=GetImageOption(image_info,"compose");
1713 if (value != (const char *) NULL)
1714 compose=(CompositeOperator) ParseCommandOption(
1715 MagickComposeOptions,MagickFalse,value);
1716 else
1717 compose=OverCompositeOp; /* use Over not image->compose */
1718
anthony31f1bf72012-01-30 12:37:22 +00001719 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001720 if ((flags & SigmaValue) == 0)
1721 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00001722 new_image=BorderImage(image,&geometry,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00001723 break;
1724 }
anthonydcf510d2011-10-30 13:51:40 +00001725 if (LocaleCompare("brightness-contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001726 {
1727 double
1728 brightness,
1729 contrast;
1730
1731 GeometryInfo
1732 geometry_info;
1733
1734 MagickStatusType
1735 flags;
1736
anthonyfd706f92012-01-19 04:22:02 +00001737 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001738 brightness=geometry_info.rho;
1739 contrast=0.0;
1740 if ((flags & SigmaValue) != 0)
1741 contrast=geometry_info.sigma;
anthony31f1bf72012-01-30 12:37:22 +00001742 (void) BrightnessContrastImage(image,brightness,contrast,
anthony805a2d42011-09-25 08:25:12 +00001743 exception);
anthony805a2d42011-09-25 08:25:12 +00001744 break;
1745 }
1746 break;
1747 }
1748 case 'c':
1749 {
anthonydcf510d2011-10-30 13:51:40 +00001750 if (LocaleCompare("cdl",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001751 {
1752 char
1753 *color_correction_collection;
1754
1755 /*
1756 Color correct with a color decision list.
1757 */
anthonyfd706f92012-01-19 04:22:02 +00001758 color_correction_collection=FileToString(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00001759 if (color_correction_collection == (char *) NULL)
1760 break;
anthony31f1bf72012-01-30 12:37:22 +00001761 (void) ColorDecisionListImage(image,color_correction_collection,
anthony805a2d42011-09-25 08:25:12 +00001762 exception);
anthony805a2d42011-09-25 08:25:12 +00001763 break;
1764 }
anthonydcf510d2011-10-30 13:51:40 +00001765 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001766 {
anthonyfd706f92012-01-19 04:22:02 +00001767 /* The "channel" setting has already been set
anthonyd1447672012-01-19 05:33:53 +00001768 FUTURE: This probably should be part of WandSettingOptionInfo()
anthonyfd706f92012-01-19 04:22:02 +00001769 or SyncImageSettings().
1770 */
anthony31f1bf72012-01-30 12:37:22 +00001771 SetPixelChannelMapMask(image,image_info->channel);
anthony805a2d42011-09-25 08:25:12 +00001772 break;
1773 }
anthonydcf510d2011-10-30 13:51:40 +00001774 if (LocaleCompare("charcoal",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001775 {
anthonyfd706f92012-01-19 04:22:02 +00001776 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001777 if ((flags & SigmaValue) == 0)
1778 geometry_info.sigma=1.0;
1779 if ((flags & XiValue) == 0)
1780 geometry_info.xi=1.0;
anthony31f1bf72012-01-30 12:37:22 +00001781 new_image=CharcoalImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001782 geometry_info.sigma,geometry_info.xi,exception);
1783 break;
1784 }
anthonydcf510d2011-10-30 13:51:40 +00001785 if (LocaleCompare("chop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001786 {
anthony31f1bf72012-01-30 12:37:22 +00001787 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
1788 new_image=ChopImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001789 break;
1790 }
anthonydcf510d2011-10-30 13:51:40 +00001791 if (LocaleCompare("clamp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001792 {
anthony31f1bf72012-01-30 12:37:22 +00001793 (void) ClampImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001794 break;
1795 }
anthonydcf510d2011-10-30 13:51:40 +00001796 if (LocaleCompare("clip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001797 {
anthonyfd706f92012-01-19 04:22:02 +00001798 if (plus_alt_op == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001799 (void) ClipImage(image,exception);
anthonyfd706f92012-01-19 04:22:02 +00001800 else /* "+clip" remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001801 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001802 break;
1803 }
anthonydcf510d2011-10-30 13:51:40 +00001804 if (LocaleCompare("clip-mask",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001805 {
1806 CacheView
1807 *mask_view;
1808
1809 Image
1810 *mask_image;
1811
1812 register Quantum
1813 *restrict q;
1814
1815 register ssize_t
1816 x;
1817
1818 ssize_t
1819 y;
1820
anthonyfd706f92012-01-19 04:22:02 +00001821 if (plus_alt_op != MagickFalse)
1822 { /* "+clip-mask" Remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001823 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001824 break;
1825 }
anthonyfd706f92012-01-19 04:22:02 +00001826 mask_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001827 if (mask_image == (Image *) NULL)
1828 break;
anthonyfd706f92012-01-19 04:22:02 +00001829 if (SetImageStorageClass(mask_image,DirectClass,exception)
1830 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001831 break;
1832 /* Create a write mask from clip-mask image */
anthonyfd706f92012-01-19 04:22:02 +00001833 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001834 mask_view=AcquireCacheView(mask_image);
1835 for (y=0; y < (ssize_t) mask_image->rows; y++)
1836 {
1837 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1838 exception);
1839 if (q == (Quantum *) NULL)
1840 break;
1841 for (x=0; x < (ssize_t) mask_image->columns; x++)
1842 {
1843 if (mask_image->matte == MagickFalse)
1844 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1845 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1846 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1847 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1848 q+=GetPixelChannels(mask_image);
1849 }
1850 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1851 break;
1852 }
anthonyfd706f92012-01-19 04:22:02 +00001853 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001854 mask_view=DestroyCacheView(mask_view);
1855 mask_image->matte=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00001856 (void) SetImageMask(image,mask_image,exception);
anthony805a2d42011-09-25 08:25:12 +00001857 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001858 break;
1859 }
anthonydcf510d2011-10-30 13:51:40 +00001860 if (LocaleCompare("clip-path",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001861 {
anthony31f1bf72012-01-30 12:37:22 +00001862 (void) ClipImagePath(image,arg1,
anthonyfd706f92012-01-19 04:22:02 +00001863 (MagickBooleanType)(!(int)plus_alt_op),exception);
anthony805a2d42011-09-25 08:25:12 +00001864 break;
1865 }
anthonydcf510d2011-10-30 13:51:40 +00001866 if (LocaleCompare("colorize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001867 {
anthony31f1bf72012-01-30 12:37:22 +00001868 new_image=ColorizeImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00001869 break;
1870 }
anthonydcf510d2011-10-30 13:51:40 +00001871 if (LocaleCompare("color-matrix",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001872 {
1873 KernelInfo
1874 *kernel;
1875
anthonyfd706f92012-01-19 04:22:02 +00001876 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001877 if (kernel == (KernelInfo *) NULL)
1878 break;
anthony31f1bf72012-01-30 12:37:22 +00001879 new_image=ColorMatrixImage(image,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00001880 kernel=DestroyKernelInfo(kernel);
1881 break;
1882 }
anthonydcf510d2011-10-30 13:51:40 +00001883 if (LocaleCompare("colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001884 {
anthonyfd706f92012-01-19 04:22:02 +00001885 /* Reduce the number of colors in the image.
1886 FUTURE: also provide 'plus version with image 'color counts'
1887 */
1888 quantize_info->number_colors=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00001889 if (quantize_info->number_colors == 0)
1890 break;
anthony31f1bf72012-01-30 12:37:22 +00001891 if ((image->storage_class == DirectClass) ||
1892 image->colors > quantize_info->number_colors)
1893 (void) QuantizeImage(quantize_info,image,exception);
anthony805a2d42011-09-25 08:25:12 +00001894 else
anthony31f1bf72012-01-30 12:37:22 +00001895 (void) CompressImageColormap(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001896 break;
1897 }
anthonydcf510d2011-10-30 13:51:40 +00001898 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001899 {
anthony31f1bf72012-01-30 12:37:22 +00001900 /* WARNING: this is both a image_info setting (already done)
1901 and a operator to change image colorspace.
1902
1903 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00001904 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00001905
anthonyd2cdc862011-10-07 14:07:17 +00001906 Note that +colorspace sets "undefined" or no effect on
1907 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00001908 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00001909 */
anthony31f1bf72012-01-30 12:37:22 +00001910 (void) TransformImageColorspace(image,
1911 plus_alt_op ? RGBColorspace : image_info->colorspace,
anthony6613bf32011-10-15 07:24:44 +00001912 exception);
anthony805a2d42011-09-25 08:25:12 +00001913 break;
1914 }
anthonydcf510d2011-10-30 13:51:40 +00001915 if (LocaleCompare("contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001916 {
anthony31f1bf72012-01-30 12:37:22 +00001917 (void) ContrastImage(image,
anthonyfd706f92012-01-19 04:22:02 +00001918 (MagickBooleanType)(!(int)plus_alt_op),exception);
anthony805a2d42011-09-25 08:25:12 +00001919 break;
1920 }
anthonydcf510d2011-10-30 13:51:40 +00001921 if (LocaleCompare("contrast-stretch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001922 {
1923 double
1924 black_point,
1925 white_point;
1926
1927 MagickStatusType
1928 flags;
1929
anthonyfd706f92012-01-19 04:22:02 +00001930 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001931 black_point=geometry_info.rho;
1932 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
1933 black_point;
1934 if ((flags & PercentValue) != 0)
1935 {
anthony31f1bf72012-01-30 12:37:22 +00001936 black_point*=(double) image->columns*image->rows/100.0;
1937 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00001938 }
anthony31f1bf72012-01-30 12:37:22 +00001939 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00001940 white_point;
anthony31f1bf72012-01-30 12:37:22 +00001941 (void) ContrastStretchImage(image,black_point,white_point,
anthony805a2d42011-09-25 08:25:12 +00001942 exception);
anthony805a2d42011-09-25 08:25:12 +00001943 break;
1944 }
anthonydcf510d2011-10-30 13:51:40 +00001945 if (LocaleCompare("convolve",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001946 {
1947 KernelInfo
1948 *kernel_info;
1949
anthonyfd706f92012-01-19 04:22:02 +00001950 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001951 if (kernel_info == (KernelInfo *) NULL)
1952 break;
anthony31f1bf72012-01-30 12:37:22 +00001953 kernel_info->bias=image->bias;
1954 new_image=ConvolveImage(image,kernel_info,exception);
anthony805a2d42011-09-25 08:25:12 +00001955 kernel_info=DestroyKernelInfo(kernel_info);
1956 break;
1957 }
anthonydcf510d2011-10-30 13:51:40 +00001958 if (LocaleCompare("crop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001959 {
anthony31f1bf72012-01-30 12:37:22 +00001960 /* WARNING: This can generate multiple images! */
1961 new_image=CropImageToTiles(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001962 break;
1963 }
anthonydcf510d2011-10-30 13:51:40 +00001964 if (LocaleCompare("cycle",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001965 {
anthony31f1bf72012-01-30 12:37:22 +00001966 (void) CycleColormapImage(image,(ssize_t) StringToLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00001967 exception);
1968 break;
1969 }
1970 break;
1971 }
1972 case 'd':
1973 {
anthonydcf510d2011-10-30 13:51:40 +00001974 if (LocaleCompare("decipher",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001975 {
1976 StringInfo
1977 *passkey;
1978
anthonyfd706f92012-01-19 04:22:02 +00001979 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00001980 if (passkey != (StringInfo *) NULL)
1981 {
anthony31f1bf72012-01-30 12:37:22 +00001982 (void) PasskeyDecipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00001983 passkey=DestroyStringInfo(passkey);
1984 }
1985 break;
1986 }
anthonydcf510d2011-10-30 13:51:40 +00001987 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001988 {
anthonydcf510d2011-10-30 13:51:40 +00001989 /* The image_info->depth setting has already been set
1990 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00001991
anthonydcf510d2011-10-30 13:51:40 +00001992 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
1993 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00001994
anthonyfd706f92012-01-19 04:22:02 +00001995 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00001996 */
anthony31f1bf72012-01-30 12:37:22 +00001997 (void) SetImageDepth(image,image_info->depth,exception);
anthony805a2d42011-09-25 08:25:12 +00001998 break;
1999 }
anthonydcf510d2011-10-30 13:51:40 +00002000 if (LocaleCompare("deskew",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002001 {
2002 double
2003 threshold;
2004
anthonyfd706f92012-01-19 04:22:02 +00002005 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002006 threshold=40.0*QuantumRange/100.0;
2007 else
anthonyfd706f92012-01-19 04:22:02 +00002008 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002009 new_image=DeskewImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002010 break;
2011 }
anthonydcf510d2011-10-30 13:51:40 +00002012 if (LocaleCompare("despeckle",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002013 {
anthony31f1bf72012-01-30 12:37:22 +00002014 new_image=DespeckleImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002015 break;
2016 }
anthonydcf510d2011-10-30 13:51:40 +00002017 if (LocaleCompare("distort",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002018 {
2019 char
2020 *args,
2021 token[MaxTextExtent];
2022
2023 const char
2024 *p;
2025
2026 DistortImageMethod
2027 method;
2028
2029 double
2030 *arguments;
2031
2032 register ssize_t
2033 x;
2034
2035 size_t
2036 number_arguments;
2037
anthony805a2d42011-09-25 08:25:12 +00002038 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002039 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002040 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002041 {
anthony80c37752012-01-16 01:03:11 +00002042 double
2043 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002044 /* Special Case - Argument is actually a resize geometry!
2045 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002046 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002047 */
anthony31f1bf72012-01-30 12:37:22 +00002048 (void) ParseRegionGeometry(image,arg2,&geometry,
anthony80c37752012-01-16 01:03:11 +00002049 exception);
2050 resize_args[0]=(double) geometry.width;
2051 resize_args[1]=(double) geometry.height;
anthony31f1bf72012-01-30 12:37:22 +00002052 new_image=DistortImage(image,method,(size_t)2,
anthony80c37752012-01-16 01:03:11 +00002053 resize_args,MagickTrue,exception);
anthony805a2d42011-09-25 08:25:12 +00002054 break;
2055 }
anthonyfd706f92012-01-19 04:22:02 +00002056 /* handle percent arguments */
anthony31f1bf72012-01-30 12:37:22 +00002057 args=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002058 exception);
2059 if (args == (char *) NULL)
2060 break;
anthonyfd706f92012-01-19 04:22:02 +00002061 /* convert arguments into an array of doubles
2062 FUTURE: make this a separate function.
2063 Also make use of new 'sentinal' feature to avoid need for
2064 tokenization.
2065 */
anthony805a2d42011-09-25 08:25:12 +00002066 p=(char *) args;
2067 for (x=0; *p != '\0'; x++)
2068 {
2069 GetMagickToken(p,&p,token);
2070 if (*token == ',')
2071 GetMagickToken(p,&p,token);
2072 }
2073 number_arguments=(size_t) x;
2074 arguments=(double *) AcquireQuantumMemory(number_arguments,
2075 sizeof(*arguments));
2076 if (arguments == (double *) NULL)
2077 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002078 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002079 (void) ResetMagickMemory(arguments,0,number_arguments*
2080 sizeof(*arguments));
2081 p=(char *) args;
2082 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2083 {
2084 GetMagickToken(p,&p,token);
2085 if (*token == ',')
2086 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002087 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002088 }
2089 args=DestroyString(args);
anthony31f1bf72012-01-30 12:37:22 +00002090 new_image=DistortImage(image,method,number_arguments,arguments,
anthonyfd706f92012-01-19 04:22:02 +00002091 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002092 arguments=(double *) RelinquishMagickMemory(arguments);
2093 break;
2094 }
anthonydcf510d2011-10-30 13:51:40 +00002095 if (LocaleCompare("draw",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002096 {
anthonyfd706f92012-01-19 04:22:02 +00002097 (void) CloneString(&draw_info->primitive,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002098 (void) DrawImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00002099 (void) CloneString(&draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002100 break;
2101 }
2102 break;
2103 }
2104 case 'e':
2105 {
anthonydcf510d2011-10-30 13:51:40 +00002106 if (LocaleCompare("edge",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002107 {
anthonyfd706f92012-01-19 04:22:02 +00002108 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002109 if ((flags & SigmaValue) == 0)
2110 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002111 new_image=EdgeImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002112 geometry_info.sigma,exception);
2113 break;
2114 }
anthonydcf510d2011-10-30 13:51:40 +00002115 if (LocaleCompare("emboss",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002116 {
anthonyfd706f92012-01-19 04:22:02 +00002117 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002118 if ((flags & SigmaValue) == 0)
2119 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002120 new_image=EmbossImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002121 geometry_info.sigma,exception);
2122 break;
2123 }
anthonydcf510d2011-10-30 13:51:40 +00002124 if (LocaleCompare("encipher",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002125 {
2126 StringInfo
2127 *passkey;
2128
anthonyfd706f92012-01-19 04:22:02 +00002129 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002130 if (passkey != (StringInfo *) NULL)
2131 {
anthony31f1bf72012-01-30 12:37:22 +00002132 (void) PasskeyEncipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002133 passkey=DestroyStringInfo(passkey);
2134 }
2135 break;
2136 }
anthonydcf510d2011-10-30 13:51:40 +00002137 if (LocaleCompare("enhance",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002138 {
anthony31f1bf72012-01-30 12:37:22 +00002139 new_image=EnhanceImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002140 break;
2141 }
anthonydcf510d2011-10-30 13:51:40 +00002142 if (LocaleCompare("equalize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002143 {
anthony31f1bf72012-01-30 12:37:22 +00002144 (void) EqualizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002145 break;
2146 }
anthonydcf510d2011-10-30 13:51:40 +00002147 if (LocaleCompare("evaluate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002148 {
2149 double
2150 constant;
2151
2152 MagickEvaluateOperator
2153 op;
2154
anthony805a2d42011-09-25 08:25:12 +00002155 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002156 MagickEvaluateOptions,MagickFalse,arg1);
2157 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002158 (void) EvaluateImage(image,op,constant,exception);
anthony805a2d42011-09-25 08:25:12 +00002159 break;
2160 }
anthonydcf510d2011-10-30 13:51:40 +00002161 if (LocaleCompare("extent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002162 {
anthony31f1bf72012-01-30 12:37:22 +00002163 flags=ParseGravityGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002164 if (geometry.width == 0)
anthony31f1bf72012-01-30 12:37:22 +00002165 geometry.width=image->columns;
anthony805a2d42011-09-25 08:25:12 +00002166 if (geometry.height == 0)
anthony31f1bf72012-01-30 12:37:22 +00002167 geometry.height=image->rows;
2168 new_image=ExtentImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002169 break;
2170 }
2171 break;
2172 }
2173 case 'f':
2174 {
anthonydcf510d2011-10-30 13:51:40 +00002175 if (LocaleCompare("features",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002176 {
anthony31f1bf72012-01-30 12:37:22 +00002177 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2178 if (plus_alt_op != MagickFalse)
2179 {
2180 (void) DeleteImageArtifact(image,"identify:features");
2181 break;
2182 }
2183 (void) SetImageArtifact(image,"identify:features","true");
2184 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002185 break;
2186 }
anthonydcf510d2011-10-30 13:51:40 +00002187 if (LocaleCompare("flip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002188 {
anthony31f1bf72012-01-30 12:37:22 +00002189 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002190 break;
2191 }
anthonydcf510d2011-10-30 13:51:40 +00002192 if (LocaleCompare("flop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002193 {
anthony31f1bf72012-01-30 12:37:22 +00002194 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002195 break;
2196 }
anthonydcf510d2011-10-30 13:51:40 +00002197 if (LocaleCompare("floodfill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002198 {
2199 PixelInfo
2200 target;
2201
anthony31f1bf72012-01-30 12:37:22 +00002202 (void) ParsePageGeometry(image,arg1,&geometry,exception);
anthonyfd706f92012-01-19 04:22:02 +00002203 (void) QueryColorCompliance(arg2,AllCompliance,&target,exception);
anthony31f1bf72012-01-30 12:37:22 +00002204 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
anthonyfd706f92012-01-19 04:22:02 +00002205 geometry.y,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002206 break;
2207 }
anthonydcf510d2011-10-30 13:51:40 +00002208 if (LocaleCompare("frame",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002209 {
2210 FrameInfo
2211 frame_info;
2212
anthony31f1bf72012-01-30 12:37:22 +00002213 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002214 compose;
2215
2216 const char*
2217 value;
2218
2219 value=GetImageOption(image_info,"compose");
2220 if (value != (const char *) NULL)
2221 compose=(CompositeOperator) ParseCommandOption(
2222 MagickComposeOptions,MagickFalse,value);
2223 else
2224 compose=OverCompositeOp; /* use Over not image->compose */
2225
anthony31f1bf72012-01-30 12:37:22 +00002226 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002227 frame_info.width=geometry.width;
2228 frame_info.height=geometry.height;
2229 if ((flags & HeightValue) == 0)
2230 frame_info.height=geometry.width;
2231 frame_info.outer_bevel=geometry.x;
2232 frame_info.inner_bevel=geometry.y;
2233 frame_info.x=(ssize_t) frame_info.width;
2234 frame_info.y=(ssize_t) frame_info.height;
anthony31f1bf72012-01-30 12:37:22 +00002235 frame_info.width=image->columns+2*frame_info.width;
2236 frame_info.height=image->rows+2*frame_info.height;
2237 new_image=FrameImage(image,&frame_info,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00002238 break;
2239 }
anthonydcf510d2011-10-30 13:51:40 +00002240 if (LocaleCompare("function",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002241 {
2242 char
2243 *arguments,
2244 token[MaxTextExtent];
2245
2246 const char
2247 *p;
2248
2249 double
2250 *parameters;
2251
2252 MagickFunction
2253 function;
2254
2255 register ssize_t
2256 x;
2257
2258 size_t
2259 number_parameters;
2260
cristy947cb4c2011-10-20 18:41:46 +00002261 /*
2262 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002263 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002264 */
anthony805a2d42011-09-25 08:25:12 +00002265 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002266 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002267 arguments=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002268 exception);
2269 if (arguments == (char *) NULL)
2270 break;
2271 p=(char *) arguments;
2272 for (x=0; *p != '\0'; x++)
2273 {
2274 GetMagickToken(p,&p,token);
2275 if (*token == ',')
2276 GetMagickToken(p,&p,token);
2277 }
2278 number_parameters=(size_t) x;
2279 parameters=(double *) AcquireQuantumMemory(number_parameters,
2280 sizeof(*parameters));
2281 if (parameters == (double *) NULL)
2282 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002283 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002284 (void) ResetMagickMemory(parameters,0,number_parameters*
2285 sizeof(*parameters));
2286 p=(char *) arguments;
2287 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2288 {
2289 GetMagickToken(p,&p,token);
2290 if (*token == ',')
2291 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002292 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002293 }
2294 arguments=DestroyString(arguments);
anthony31f1bf72012-01-30 12:37:22 +00002295 (void) FunctionImage(image,function,number_parameters,parameters,
anthony805a2d42011-09-25 08:25:12 +00002296 exception);
2297 parameters=(double *) RelinquishMagickMemory(parameters);
2298 break;
2299 }
2300 break;
2301 }
2302 case 'g':
2303 {
anthonydcf510d2011-10-30 13:51:40 +00002304 if (LocaleCompare("gamma",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002305 {
anthony31f1bf72012-01-30 12:37:22 +00002306 if (plus_alt_op != MagickFalse)
2307 image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002308 else
anthony31f1bf72012-01-30 12:37:22 +00002309 (void) GammaImage(image,StringToDouble(arg1,(char **) NULL),
anthonyfd706f92012-01-19 04:22:02 +00002310 exception);
anthony805a2d42011-09-25 08:25:12 +00002311 break;
2312 }
anthonydcf510d2011-10-30 13:51:40 +00002313 if ((LocaleCompare("gaussian-blur",option) == 0) ||
2314 (LocaleCompare("gaussian",option) == 0))
anthony805a2d42011-09-25 08:25:12 +00002315 {
anthonyfd706f92012-01-19 04:22:02 +00002316 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002317 if ((flags & SigmaValue) == 0)
2318 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002319 new_image=GaussianBlurImage(image,geometry_info.rho,
cristyd89705a2012-01-20 02:52:24 +00002320 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002321 break;
2322 }
anthonydcf510d2011-10-30 13:51:40 +00002323 if (LocaleCompare("geometry",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002324 {
anthonyfd706f92012-01-19 04:22:02 +00002325 /*
anthony31f1bf72012-01-30 12:37:22 +00002326 Record Image offset for composition. (A Setting)
2327 Resize last image. (ListOperator)
2328 FUTURE: Why if no 'offset' does this resize ALL images?
2329 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002330 */
anthony31f1bf72012-01-30 12:37:22 +00002331 if (plus_alt_op != MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00002332 { /* remove the previous composition geometry offset! */
anthony31f1bf72012-01-30 12:37:22 +00002333 if (image->geometry != (char *) NULL)
2334 image->geometry=DestroyString(image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002335 break;
2336 }
anthony31f1bf72012-01-30 12:37:22 +00002337 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002338 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony31f1bf72012-01-30 12:37:22 +00002339 (void) CloneString(&image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002340 else
anthony31f1bf72012-01-30 12:37:22 +00002341 new_image=ResizeImage(image,geometry.width,geometry.height,
2342 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002343 break;
2344 }
anthony805a2d42011-09-25 08:25:12 +00002345 break;
2346 }
2347 case 'h':
2348 {
anthonydcf510d2011-10-30 13:51:40 +00002349 if (LocaleCompare("highlight-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002350 {
anthony31f1bf72012-01-30 12:37:22 +00002351 (void) SetImageArtifact(image,option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002352 break;
2353 }
2354 break;
2355 }
2356 case 'i':
2357 {
anthonydcf510d2011-10-30 13:51:40 +00002358 if (LocaleCompare("identify",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002359 {
anthony31f1bf72012-01-30 12:37:22 +00002360 const char
2361 *format,
anthony805a2d42011-09-25 08:25:12 +00002362 *text;
2363
anthony31f1bf72012-01-30 12:37:22 +00002364 format=GetImageOption(image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002365 if (format == (char *) NULL)
2366 {
anthony31f1bf72012-01-30 12:37:22 +00002367 (void) IdentifyImage(image,stdout,image_info->verbose,
anthony805a2d42011-09-25 08:25:12 +00002368 exception);
2369 break;
2370 }
anthony31f1bf72012-01-30 12:37:22 +00002371 text=InterpretImageProperties(image_info,image,format,exception);
anthony805a2d42011-09-25 08:25:12 +00002372 if (text == (char *) NULL)
2373 break;
2374 (void) fputs(text,stdout);
2375 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002376 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002377 break;
2378 }
anthonydcf510d2011-10-30 13:51:40 +00002379 if (LocaleCompare("implode",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002380 {
anthonyfd706f92012-01-19 04:22:02 +00002381 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002382 new_image=ImplodeImage(image,geometry_info.rho,
2383 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002384 break;
2385 }
anthonyfd706f92012-01-19 04:22:02 +00002386 if (LocaleCompare("interpolative-resize",option) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002387 {
anthony31f1bf72012-01-30 12:37:22 +00002388 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2389 new_image=InterpolativeResizeImage(image,geometry.width,
2390 geometry.height,image->interpolate,exception);
cristy947cb4c2011-10-20 18:41:46 +00002391 break;
2392 }
anthony805a2d42011-09-25 08:25:12 +00002393 break;
2394 }
2395 case 'l':
2396 {
anthonydcf510d2011-10-30 13:51:40 +00002397 if (LocaleCompare("lat",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002398 {
anthonyfd706f92012-01-19 04:22:02 +00002399 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002400 if ((flags & PercentValue) != 0)
2401 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002402 new_image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
2403 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2404 exception);
anthony805a2d42011-09-25 08:25:12 +00002405 break;
2406 }
anthonydcf510d2011-10-30 13:51:40 +00002407 if (LocaleCompare("level",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002408 {
2409 MagickRealType
2410 black_point,
2411 gamma,
2412 white_point;
2413
2414 MagickStatusType
2415 flags;
2416
anthonyfd706f92012-01-19 04:22:02 +00002417 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002418 black_point=geometry_info.rho;
2419 white_point=(MagickRealType) QuantumRange;
2420 if ((flags & SigmaValue) != 0)
2421 white_point=geometry_info.sigma;
2422 gamma=1.0;
2423 if ((flags & XiValue) != 0)
2424 gamma=geometry_info.xi;
2425 if ((flags & PercentValue) != 0)
2426 {
2427 black_point*=(MagickRealType) (QuantumRange/100.0);
2428 white_point*=(MagickRealType) (QuantumRange/100.0);
2429 }
2430 if ((flags & SigmaValue) == 0)
2431 white_point=(MagickRealType) QuantumRange-black_point;
anthony31f1bf72012-01-30 12:37:22 +00002432 if (plus_alt_op || ((flags & AspectValue) != 0))
2433 (void) LevelizeImage(image,black_point,white_point,gamma,
anthony805a2d42011-09-25 08:25:12 +00002434 exception);
2435 else
anthony31f1bf72012-01-30 12:37:22 +00002436 (void) LevelImage(image,black_point,white_point,gamma,
anthony805a2d42011-09-25 08:25:12 +00002437 exception);
anthony805a2d42011-09-25 08:25:12 +00002438 break;
2439 }
anthonydcf510d2011-10-30 13:51:40 +00002440 if (LocaleCompare("level-colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002441 {
2442 char
2443 token[MaxTextExtent];
2444
2445 const char
2446 *p;
2447
2448 PixelInfo
2449 black_point,
2450 white_point;
2451
anthonyfd706f92012-01-19 04:22:02 +00002452 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002453 GetMagickToken(p,&p,token); /* get black point color */
2454 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002455 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002456 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002457 else
cristy269c9412011-10-13 23:41:15 +00002458 (void) QueryColorCompliance("#000000",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002459 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002460 if (isalpha((int) token[0]) || (token[0] == '#'))
2461 GetMagickToken(p,&p,token);
2462 if (*token == '\0')
2463 white_point=black_point; /* set everything to that color */
2464 else
2465 {
2466 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2467 GetMagickToken(p,&p,token); /* Get white point color. */
2468 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002469 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002470 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002471 else
cristy269c9412011-10-13 23:41:15 +00002472 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002473 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002474 }
anthony31f1bf72012-01-30 12:37:22 +00002475 (void) LevelImageColors(image,&black_point,&white_point,
2476 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002477 break;
2478 }
anthonydcf510d2011-10-30 13:51:40 +00002479 if (LocaleCompare("linear-stretch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002480 {
2481 double
2482 black_point,
2483 white_point;
2484
2485 MagickStatusType
2486 flags;
2487
anthonyfd706f92012-01-19 04:22:02 +00002488 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002489 black_point=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002490 white_point=(MagickRealType) image->columns*image->rows;
anthony805a2d42011-09-25 08:25:12 +00002491 if ((flags & SigmaValue) != 0)
2492 white_point=geometry_info.sigma;
2493 if ((flags & PercentValue) != 0)
2494 {
anthony31f1bf72012-01-30 12:37:22 +00002495 black_point*=(double) image->columns*image->rows/100.0;
2496 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002497 }
2498 if ((flags & SigmaValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00002499 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002500 black_point;
anthony31f1bf72012-01-30 12:37:22 +00002501 (void) LinearStretchImage(image,black_point,white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002502 break;
2503 }
anthonydcf510d2011-10-30 13:51:40 +00002504 if (LocaleCompare("liquid-rescale",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002505 {
anthony31f1bf72012-01-30 12:37:22 +00002506 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002507 if ((flags & XValue) == 0)
2508 geometry.x=1;
2509 if ((flags & YValue) == 0)
2510 geometry.y=0;
anthony31f1bf72012-01-30 12:37:22 +00002511 new_image=LiquidRescaleImage(image,geometry.width,
anthony805a2d42011-09-25 08:25:12 +00002512 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2513 break;
2514 }
anthonydcf510d2011-10-30 13:51:40 +00002515 if (LocaleCompare("lowlight-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002516 {
anthony31f1bf72012-01-30 12:37:22 +00002517 (void) SetImageArtifact(image,option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002518 break;
2519 }
2520 break;
2521 }
2522 case 'm':
2523 {
anthonydcf510d2011-10-30 13:51:40 +00002524 if (LocaleCompare("map",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002525 {
2526 Image
2527 *remap_image;
2528
anthony31f1bf72012-01-30 12:37:22 +00002529 /* DEPRECIATED use -remap */
anthonyfd706f92012-01-19 04:22:02 +00002530 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002531 if (remap_image == (Image *) NULL)
2532 break;
anthony31f1bf72012-01-30 12:37:22 +00002533 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002534 remap_image=DestroyImage(remap_image);
2535 break;
2536 }
anthonydcf510d2011-10-30 13:51:40 +00002537 if (LocaleCompare("mask",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002538 {
2539 Image
2540 *mask;
2541
anthony31f1bf72012-01-30 12:37:22 +00002542 if (plus_alt_op != MagickFalse)
2543 { /* Remove a mask. */
2544 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002545 break;
2546 }
anthony31f1bf72012-01-30 12:37:22 +00002547 /* Set the image mask. */
anthonyfd706f92012-01-19 04:22:02 +00002548 mask=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002549 if (mask == (Image *) NULL)
2550 break;
anthony31f1bf72012-01-30 12:37:22 +00002551 (void) SetImageMask(image,mask,exception);
anthony805a2d42011-09-25 08:25:12 +00002552 mask=DestroyImage(mask);
2553 break;
2554 }
anthonydcf510d2011-10-30 13:51:40 +00002555 if (LocaleCompare("matte",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002556 {
anthony31f1bf72012-01-30 12:37:22 +00002557 /* DEPRECIATED */
2558 (void) SetImageAlphaChannel(image,plus_alt_op ?
2559 DeactivateAlphaChannel:SetAlphaChannel ,exception);
anthony805a2d42011-09-25 08:25:12 +00002560 break;
2561 }
anthonydcf510d2011-10-30 13:51:40 +00002562 if (LocaleCompare("mode",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002563 {
anthonyfd706f92012-01-19 04:22:02 +00002564 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002565 if ((flags & SigmaValue) == 0)
2566 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002567 new_image=StatisticImage(image,ModeStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002568 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2569 break;
2570 }
anthonydcf510d2011-10-30 13:51:40 +00002571 if (LocaleCompare("modulate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002572 {
anthony31f1bf72012-01-30 12:37:22 +00002573 (void) ModulateImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002574 break;
2575 }
anthonydcf510d2011-10-30 13:51:40 +00002576 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002577 {
anthony31f1bf72012-01-30 12:37:22 +00002578 (void) SetImageProgressMonitor(image, plus_alt_op?
2579 (MagickProgressMonitor) NULL:MonitorProgress,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002580 break;
2581 }
anthonydcf510d2011-10-30 13:51:40 +00002582 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002583 {
anthony31f1bf72012-01-30 12:37:22 +00002584 (void) SetImageType(image,BilevelType,exception);
anthony805a2d42011-09-25 08:25:12 +00002585 break;
2586 }
anthonydcf510d2011-10-30 13:51:40 +00002587 if (LocaleCompare("morphology",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002588 {
2589 char
2590 token[MaxTextExtent];
2591
2592 const char
2593 *p;
2594
2595 KernelInfo
2596 *kernel;
2597
2598 MorphologyMethod
2599 method;
2600
2601 ssize_t
2602 iterations;
2603
anthonyfd706f92012-01-19 04:22:02 +00002604 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002605 GetMagickToken(p,&p,token);
2606 method=(MorphologyMethod) ParseCommandOption(
2607 MagickMorphologyOptions,MagickFalse,token);
2608 iterations=1L;
2609 GetMagickToken(p,&p,token);
2610 if ((*p == ':') || (*p == ','))
2611 GetMagickToken(p,&p,token);
2612 if ((*p != '\0'))
2613 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002614 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002615 if (kernel == (KernelInfo *) NULL)
2616 {
2617 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002618 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002619 break;
2620 }
anthony31f1bf72012-01-30 12:37:22 +00002621 new_image=MorphologyImage(image,method,iterations,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00002622 kernel=DestroyKernelInfo(kernel);
2623 break;
2624 }
anthonydcf510d2011-10-30 13:51:40 +00002625 if (LocaleCompare("motion-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002626 {
anthonyfd706f92012-01-19 04:22:02 +00002627 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002628 if ((flags & SigmaValue) == 0)
2629 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002630 new_image=MotionBlurImage(image,geometry_info.rho,
2631 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2632 exception);
anthony805a2d42011-09-25 08:25:12 +00002633 break;
2634 }
2635 break;
2636 }
2637 case 'n':
2638 {
anthonydcf510d2011-10-30 13:51:40 +00002639 if (LocaleCompare("negate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002640 {
anthony31f1bf72012-01-30 12:37:22 +00002641 (void) NegateImage(image, plus_alt_op, exception);
anthony805a2d42011-09-25 08:25:12 +00002642 break;
2643 }
anthonydcf510d2011-10-30 13:51:40 +00002644 if (LocaleCompare("noise",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002645 {
anthony31f1bf72012-01-30 12:37:22 +00002646 if (plus_alt_op == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002647 {
anthonyfd706f92012-01-19 04:22:02 +00002648 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002649 if ((flags & SigmaValue) == 0)
2650 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002651 new_image=StatisticImage(image,NonpeakStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002652 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2653 }
2654 else
2655 {
2656 NoiseType
2657 noise;
2658
anthony31f1bf72012-01-30 12:37:22 +00002659 double
2660 attenuate;
2661
2662 const char*
2663 value;
2664
anthony805a2d42011-09-25 08:25:12 +00002665 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002666 MagickFalse,arg1),
2667
2668 value=GetImageOption(image_info,"attenuate");
2669 if (value != (const char *) NULL)
2670 attenuate=StringToDouble(value,(char **) NULL);
2671 else
2672 attenuate=1.0;
2673
2674 new_image=AddNoiseImage(image,noise,attenuate,exception);
anthony805a2d42011-09-25 08:25:12 +00002675 }
2676 break;
2677 }
anthonydcf510d2011-10-30 13:51:40 +00002678 if (LocaleCompare("normalize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002679 {
anthony31f1bf72012-01-30 12:37:22 +00002680 (void) NormalizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002681 break;
2682 }
2683 break;
2684 }
2685 case 'o':
2686 {
anthonydcf510d2011-10-30 13:51:40 +00002687 if (LocaleCompare("opaque",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002688 {
2689 PixelInfo
2690 target;
2691
anthony31f1bf72012-01-30 12:37:22 +00002692 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
2693 (void) OpaquePaintImage(image,&target,&draw_info->fill,plus_alt_op,
2694 exception);
anthony805a2d42011-09-25 08:25:12 +00002695 break;
2696 }
anthonydcf510d2011-10-30 13:51:40 +00002697 if (LocaleCompare("ordered-dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002698 {
anthony31f1bf72012-01-30 12:37:22 +00002699 (void) OrderedPosterizeImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002700 break;
2701 }
2702 break;
2703 }
2704 case 'p':
2705 {
anthonydcf510d2011-10-30 13:51:40 +00002706 if (LocaleCompare("paint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002707 {
anthonyfd706f92012-01-19 04:22:02 +00002708 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002709 new_image=OilPaintImage(image,geometry_info.rho,geometry_info.sigma,
2710 exception);
anthony805a2d42011-09-25 08:25:12 +00002711 break;
2712 }
anthonydcf510d2011-10-30 13:51:40 +00002713 if (LocaleCompare("polaroid",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002714 {
cristye9e3d382011-12-14 01:50:13 +00002715 const char
2716 *caption;
2717
anthony805a2d42011-09-25 08:25:12 +00002718 double
2719 angle;
2720
anthony31f1bf72012-01-30 12:37:22 +00002721 if (plus_alt_op != MagickFalse)
2722 {
2723 RandomInfo
2724 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002725
anthony31f1bf72012-01-30 12:37:22 +00002726 random_info=AcquireRandomInfo();
2727 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2728 random_info=DestroyRandomInfo(random_info);
2729 }
2730 else
anthony805a2d42011-09-25 08:25:12 +00002731 {
2732 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002733 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002734 angle=geometry_info.rho;
2735 }
anthony31f1bf72012-01-30 12:37:22 +00002736 caption=GetImageProperty(image,"caption",exception);
2737 new_image=PolaroidImage(image,draw_info,caption,angle,
2738 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002739 break;
2740 }
anthonydcf510d2011-10-30 13:51:40 +00002741 if (LocaleCompare("posterize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002742 {
anthony31f1bf72012-01-30 12:37:22 +00002743 (void) ParseGeometry(arg1,&geometry_info);
2744 (void) PosterizeImage(image,(size_t) geometry_info.rho,
2745 quantize_info->dither,exception);
anthony805a2d42011-09-25 08:25:12 +00002746 break;
2747 }
anthonydcf510d2011-10-30 13:51:40 +00002748 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002749 {
2750 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002751 preview_type;
anthony170fce92011-10-20 11:50:23 +00002752
anthony31f1bf72012-01-30 12:37:22 +00002753 /* FUTURE: should be a 'Genesis' option?
2754 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002755 */
anthony31f1bf72012-01-30 12:37:22 +00002756 preview_type=UndefinedPreview;
2757 if (plus_alt_op == MagickFalse)
2758 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2759 MagickFalse,arg1);
2760 new_image=PreviewImage(image,preview_type,exception);
anthony805a2d42011-09-25 08:25:12 +00002761 break;
2762 }
anthonydcf510d2011-10-30 13:51:40 +00002763 if (LocaleCompare("profile",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002764 {
2765 const char
2766 *name;
2767
2768 const StringInfo
2769 *profile;
2770
2771 Image
2772 *profile_image;
2773
2774 ImageInfo
2775 *profile_info;
2776
anthony31f1bf72012-01-30 12:37:22 +00002777 if (plus_alt_op != MagickFalse)
2778 { /* Remove a profile from the image. */
2779 (void) ProfileImage(image,arg1,(const unsigned char *)
cristy092d71c2011-10-14 18:01:29 +00002780 NULL,0,exception);
anthony805a2d42011-09-25 08:25:12 +00002781 break;
2782 }
anthony31f1bf72012-01-30 12:37:22 +00002783 /* Associate a profile with the image. */
anthony805a2d42011-09-25 08:25:12 +00002784 profile_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00002785 profile=GetImageProfile(image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002786 if (profile != (StringInfo *) NULL)
2787 profile_info->profile=(void *) CloneStringInfo(profile);
anthonyfd706f92012-01-19 04:22:02 +00002788 profile_image=GetImageCache(profile_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002789 profile_info=DestroyImageInfo(profile_info);
2790 if (profile_image == (Image *) NULL)
2791 {
2792 StringInfo
2793 *profile;
2794
2795 profile_info=CloneImageInfo(image_info);
anthonyfd706f92012-01-19 04:22:02 +00002796 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002797 MaxTextExtent);
2798 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2799 if (profile != (StringInfo *) NULL)
2800 {
anthony31f1bf72012-01-30 12:37:22 +00002801 (void) ProfileImage(image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002802 GetStringInfoDatum(profile),(size_t)
cristy092d71c2011-10-14 18:01:29 +00002803 GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002804 profile=DestroyStringInfo(profile);
2805 }
2806 profile_info=DestroyImageInfo(profile_info);
2807 break;
2808 }
2809 ResetImageProfileIterator(profile_image);
2810 name=GetNextImageProfile(profile_image);
2811 while (name != (const char *) NULL)
2812 {
2813 profile=GetImageProfile(profile_image,name);
2814 if (profile != (StringInfo *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002815 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
cristy092d71c2011-10-14 18:01:29 +00002816 (size_t) GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002817 name=GetNextImageProfile(profile_image);
2818 }
2819 profile_image=DestroyImage(profile_image);
2820 break;
2821 }
2822 break;
2823 }
anthony805a2d42011-09-25 08:25:12 +00002824 case 'r':
2825 {
anthonydcf510d2011-10-30 13:51:40 +00002826 if (LocaleCompare("radial-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002827 {
anthonyfd706f92012-01-19 04:22:02 +00002828 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002829 new_image=RadialBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002830 geometry_info.sigma,exception);
2831 break;
2832 }
anthonydcf510d2011-10-30 13:51:40 +00002833 if (LocaleCompare("raise",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002834 {
anthony31f1bf72012-01-30 12:37:22 +00002835 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002836 if ((flags & SigmaValue) == 0)
2837 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00002838 (void) RaiseImage(image,&geometry,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002839 break;
2840 }
anthonydcf510d2011-10-30 13:51:40 +00002841 if (LocaleCompare("random-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002842 {
anthony31f1bf72012-01-30 12:37:22 +00002843 (void) RandomThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002844 break;
2845 }
anthonydcf510d2011-10-30 13:51:40 +00002846 if (LocaleCompare("remap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002847 {
2848 Image
2849 *remap_image;
2850
anthonyfd706f92012-01-19 04:22:02 +00002851 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002852 if (remap_image == (Image *) NULL)
2853 break;
anthony31f1bf72012-01-30 12:37:22 +00002854 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002855 remap_image=DestroyImage(remap_image);
2856 break;
2857 }
anthonydcf510d2011-10-30 13:51:40 +00002858 if (LocaleCompare("repage",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002859 {
anthony31f1bf72012-01-30 12:37:22 +00002860 if (plus_alt_op == MagickFalse)
2861 (void) ResetImagePage(image,arg1);
2862 else
2863 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
anthony805a2d42011-09-25 08:25:12 +00002864 break;
2865 }
anthonydcf510d2011-10-30 13:51:40 +00002866 if (LocaleCompare("resample",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002867 {
anthony31f1bf72012-01-30 12:37:22 +00002868 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00002869 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002870 if ((flags & SigmaValue) == 0)
2871 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002872 new_image=ResampleImage(image,geometry_info.rho,
2873 geometry_info.sigma,image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002874 break;
2875 }
anthonydcf510d2011-10-30 13:51:40 +00002876 if (LocaleCompare("resize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002877 {
anthonyafbaed72011-10-26 12:05:04 +00002878 /* FUTURE: remove blur argument - no longer used */
anthony31f1bf72012-01-30 12:37:22 +00002879 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2880 new_image=ResizeImage(image,geometry.width,geometry.height,
2881 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002882 break;
2883 }
anthonydcf510d2011-10-30 13:51:40 +00002884 if (LocaleCompare("roll",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002885 {
anthony31f1bf72012-01-30 12:37:22 +00002886 (void) ParsePageGeometry(image,arg1,&geometry,exception);
2887 new_image=RollImage(image,geometry.x,geometry.y,exception);
anthony805a2d42011-09-25 08:25:12 +00002888 break;
2889 }
anthonydcf510d2011-10-30 13:51:40 +00002890 if (LocaleCompare("rotate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002891 {
anthonyfd706f92012-01-19 04:22:02 +00002892 if (strchr(arg1,'>') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002893 if (image->columns <= image->rows)
anthony805a2d42011-09-25 08:25:12 +00002894 break;
anthonyfd706f92012-01-19 04:22:02 +00002895 if (strchr(arg1,'<') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002896 if (image->columns >= image->rows)
anthony805a2d42011-09-25 08:25:12 +00002897 break;
anthonyafbaed72011-10-26 12:05:04 +00002898
anthonyfd706f92012-01-19 04:22:02 +00002899 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002900 new_image=RotateImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00002901 break;
2902 }
2903 break;
2904 }
2905 case 's':
2906 {
anthonydcf510d2011-10-30 13:51:40 +00002907 if (LocaleCompare("sample",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002908 {
anthony31f1bf72012-01-30 12:37:22 +00002909 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2910 new_image=SampleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00002911 exception);
2912 break;
2913 }
anthonydcf510d2011-10-30 13:51:40 +00002914 if (LocaleCompare("scale",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002915 {
anthony31f1bf72012-01-30 12:37:22 +00002916 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2917 new_image=ScaleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00002918 exception);
2919 break;
2920 }
anthonydcf510d2011-10-30 13:51:40 +00002921 if (LocaleCompare("selective-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002922 {
anthonyfd706f92012-01-19 04:22:02 +00002923 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002924 if ((flags & PercentValue) != 0)
2925 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002926 new_image=SelectiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002927 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
2928 break;
2929 }
anthonydcf510d2011-10-30 13:51:40 +00002930 if (LocaleCompare("separate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002931 {
anthony31f1bf72012-01-30 12:37:22 +00002932 /* WARNING: This can generate multiple images! */
2933 new_image=SeparateImages(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002934 break;
2935 }
anthonydcf510d2011-10-30 13:51:40 +00002936 if (LocaleCompare("sepia-tone",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002937 {
2938 double
2939 threshold;
2940
anthonyfd706f92012-01-19 04:22:02 +00002941 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002942 new_image=SepiaToneImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002943 break;
2944 }
anthonydcf510d2011-10-30 13:51:40 +00002945 if (LocaleCompare("segment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002946 {
anthonyfd706f92012-01-19 04:22:02 +00002947 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002948 if ((flags & SigmaValue) == 0)
2949 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002950 (void) SegmentImage(image,image->colorspace,
anthony805a2d42011-09-25 08:25:12 +00002951 image_info->verbose,geometry_info.rho,geometry_info.sigma,
2952 exception);
2953 break;
2954 }
anthonydcf510d2011-10-30 13:51:40 +00002955 if (LocaleCompare("set",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002956 {
2957 char
2958 *value;
2959
anthony31f1bf72012-01-30 12:37:22 +00002960 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002961 {
anthonyfd706f92012-01-19 04:22:02 +00002962 if (LocaleNCompare(arg1,"registry:",9) == 0)
2963 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00002964 else
anthony31f1bf72012-01-30 12:37:22 +00002965 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00002966 {
anthonyfd706f92012-01-19 04:22:02 +00002967 (void) DeleteImageOption(image_info,arg1+7);
anthony31f1bf72012-01-30 12:37:22 +00002968 (void) DeleteImageArtifact(image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00002969 }
2970 else
anthony31f1bf72012-01-30 12:37:22 +00002971 (void) DeleteImageProperty(image,arg1);
anthony805a2d42011-09-25 08:25:12 +00002972 break;
2973 }
anthony31f1bf72012-01-30 12:37:22 +00002974 value=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002975 exception);
2976 if (value == (char *) NULL)
2977 break;
anthonyfd706f92012-01-19 04:22:02 +00002978 if (LocaleNCompare(arg1,"registry:",9) == 0)
2979 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony805a2d42011-09-25 08:25:12 +00002980 exception);
2981 else
anthonyfd706f92012-01-19 04:22:02 +00002982 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00002983 {
anthonyfd706f92012-01-19 04:22:02 +00002984 (void) SetImageOption(image_info,arg1+7,value);
anthony31f1bf72012-01-30 12:37:22 +00002985 (void) SetImageArtifact(image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00002986 }
2987 else
anthony31f1bf72012-01-30 12:37:22 +00002988 (void) SetImageProperty(image,arg1,value,exception);
anthony805a2d42011-09-25 08:25:12 +00002989 value=DestroyString(value);
2990 break;
2991 }
anthonydcf510d2011-10-30 13:51:40 +00002992 if (LocaleCompare("shade",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002993 {
anthonyfd706f92012-01-19 04:22:02 +00002994 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002995 if ((flags & SigmaValue) == 0)
2996 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002997 new_image=ShadeImage(image,normal_op,geometry_info.rho,
2998 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002999 break;
3000 }
anthonydcf510d2011-10-30 13:51:40 +00003001 if (LocaleCompare("shadow",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003002 {
anthonyfd706f92012-01-19 04:22:02 +00003003 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003004 if ((flags & SigmaValue) == 0)
3005 geometry_info.sigma=1.0;
3006 if ((flags & XiValue) == 0)
3007 geometry_info.xi=4.0;
3008 if ((flags & PsiValue) == 0)
3009 geometry_info.psi=4.0;
anthony31f1bf72012-01-30 12:37:22 +00003010 new_image=ShadowImage(image,geometry_info.rho,
3011 geometry_info.sigma,image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003012 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
3013 exception);
anthony805a2d42011-09-25 08:25:12 +00003014 break;
3015 }
anthonydcf510d2011-10-30 13:51:40 +00003016 if (LocaleCompare("sharpen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003017 {
anthonyfd706f92012-01-19 04:22:02 +00003018 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003019 if ((flags & SigmaValue) == 0)
3020 geometry_info.sigma=1.0;
3021 if ((flags & XiValue) == 0)
3022 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00003023 new_image=SharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003024 geometry_info.sigma,geometry_info.xi,exception);
3025 break;
3026 }
anthonydcf510d2011-10-30 13:51:40 +00003027 if (LocaleCompare("shave",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003028 {
anthony31f1bf72012-01-30 12:37:22 +00003029 flags=ParsePageGeometry(image,arg1,&geometry,exception);
3030 new_image=ShaveImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003031 break;
3032 }
anthonydcf510d2011-10-30 13:51:40 +00003033 if (LocaleCompare("shear",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003034 {
anthonyfd706f92012-01-19 04:22:02 +00003035 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003036 if ((flags & SigmaValue) == 0)
3037 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00003038 new_image=ShearImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003039 geometry_info.sigma,exception);
3040 break;
3041 }
anthonydcf510d2011-10-30 13:51:40 +00003042 if (LocaleCompare("sigmoidal-contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003043 {
anthonyfd706f92012-01-19 04:22:02 +00003044 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003045 if ((flags & SigmaValue) == 0)
3046 geometry_info.sigma=(double) QuantumRange/2.0;
3047 if ((flags & PercentValue) != 0)
3048 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3049 100.0;
anthony31f1bf72012-01-30 12:37:22 +00003050 (void) SigmoidalContrastImage(image,normal_op,geometry_info.rho,
3051 geometry_info.sigma,
anthony805a2d42011-09-25 08:25:12 +00003052 exception);
3053 break;
3054 }
anthonydcf510d2011-10-30 13:51:40 +00003055 if (LocaleCompare("sketch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003056 {
anthonyfd706f92012-01-19 04:22:02 +00003057 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003058 if ((flags & SigmaValue) == 0)
3059 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003060 new_image=SketchImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003061 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3062 break;
3063 }
anthonydcf510d2011-10-30 13:51:40 +00003064 if (LocaleCompare("solarize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003065 {
anthony31f1bf72012-01-30 12:37:22 +00003066 (void) SolarizeImage(image,StringToDoubleInterval(arg1,(double)
3067 QuantumRange+1.0),exception);
anthony805a2d42011-09-25 08:25:12 +00003068 break;
3069 }
anthonydcf510d2011-10-30 13:51:40 +00003070 if (LocaleCompare("sparse-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003071 {
3072 SparseColorMethod
3073 method;
3074
3075 char
3076 *arguments;
3077
anthony805a2d42011-09-25 08:25:12 +00003078 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003079 MagickSparseColorOptions,MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003080 arguments=InterpretImageProperties(image_info,image,arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00003081 if (arguments == (char *) NULL)
3082 break;
anthony31f1bf72012-01-30 12:37:22 +00003083 new_image=SparseColorOption(image,method,arguments,exception);
anthony805a2d42011-09-25 08:25:12 +00003084 arguments=DestroyString(arguments);
3085 break;
3086 }
anthonydcf510d2011-10-30 13:51:40 +00003087 if (LocaleCompare("splice",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003088 {
anthony31f1bf72012-01-30 12:37:22 +00003089 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
3090 new_image=SpliceImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003091 break;
3092 }
anthonydcf510d2011-10-30 13:51:40 +00003093 if (LocaleCompare("spread",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003094 {
anthonyfd706f92012-01-19 04:22:02 +00003095 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003096 new_image=SpreadImage(image,geometry_info.rho,image->interpolate,
3097 exception);
anthony805a2d42011-09-25 08:25:12 +00003098 break;
3099 }
anthonydcf510d2011-10-30 13:51:40 +00003100 if (LocaleCompare("statistic",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003101 {
3102 StatisticType
3103 type;
3104
anthony805a2d42011-09-25 08:25:12 +00003105 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003106 MagickFalse,arg1);
3107 (void) ParseGeometry(arg2,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003108 new_image=StatisticImage(image,type,(size_t) geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003109 (size_t) geometry_info.sigma,exception);
3110 break;
3111 }
anthonydcf510d2011-10-30 13:51:40 +00003112 if (LocaleCompare("strip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003113 {
anthony31f1bf72012-01-30 12:37:22 +00003114 (void) StripImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003115 break;
3116 }
anthonydcf510d2011-10-30 13:51:40 +00003117 if (LocaleCompare("swirl",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003118 {
anthonyfd706f92012-01-19 04:22:02 +00003119 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003120 new_image=SwirlImage(image,geometry_info.rho,
3121 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003122 break;
3123 }
3124 break;
3125 }
3126 case 't':
3127 {
anthonydcf510d2011-10-30 13:51:40 +00003128 if (LocaleCompare("threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003129 {
3130 double
3131 threshold;
3132
anthony31f1bf72012-01-30 12:37:22 +00003133 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003134 threshold=(double) QuantumRange/2;
3135 else
anthonyfd706f92012-01-19 04:22:02 +00003136 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003137 (void) BilevelImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003138 break;
3139 }
anthonydcf510d2011-10-30 13:51:40 +00003140 if (LocaleCompare("thumbnail",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003141 {
anthony31f1bf72012-01-30 12:37:22 +00003142 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3143 new_image=ThumbnailImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003144 exception);
3145 break;
3146 }
anthonydcf510d2011-10-30 13:51:40 +00003147 if (LocaleCompare("tint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003148 {
anthony31f1bf72012-01-30 12:37:22 +00003149 new_image=TintImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00003150 break;
3151 }
anthonydcf510d2011-10-30 13:51:40 +00003152 if (LocaleCompare("transform",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003153 {
anthonyfd706f92012-01-19 04:22:02 +00003154 /* DEPRECIATED */
anthony31f1bf72012-01-30 12:37:22 +00003155 new_image=AffineTransformImage(image,&draw_info->affine,
anthony805a2d42011-09-25 08:25:12 +00003156 exception);
3157 break;
3158 }
anthonydcf510d2011-10-30 13:51:40 +00003159 if (LocaleCompare("transparent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003160 {
3161 PixelInfo
3162 target;
3163
anthony31f1bf72012-01-30 12:37:22 +00003164 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
3165 (void) TransparentPaintImage(image,&target,(Quantum)
3166 TransparentAlpha,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003167 break;
3168 }
anthonydcf510d2011-10-30 13:51:40 +00003169 if (LocaleCompare("transpose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003170 {
anthony31f1bf72012-01-30 12:37:22 +00003171 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003172 break;
3173 }
anthonydcf510d2011-10-30 13:51:40 +00003174 if (LocaleCompare("transverse",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003175 {
anthony31f1bf72012-01-30 12:37:22 +00003176 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003177 break;
3178 }
anthonydcf510d2011-10-30 13:51:40 +00003179 if (LocaleCompare("trim",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003180 {
anthony31f1bf72012-01-30 12:37:22 +00003181 new_image=TrimImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003182 break;
3183 }
anthonydcf510d2011-10-30 13:51:40 +00003184 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003185 {
anthonyab3a50c2011-10-27 11:48:57 +00003186 /* Note that "type" setting should have already been defined */
anthony31f1bf72012-01-30 12:37:22 +00003187 (void) SetImageType(image,image_info->type,exception);
anthony805a2d42011-09-25 08:25:12 +00003188 break;
3189 }
3190 break;
3191 }
3192 case 'u':
3193 {
anthonydcf510d2011-10-30 13:51:40 +00003194 if (LocaleCompare("unique",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003195 {
anthony31f1bf72012-01-30 12:37:22 +00003196 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
3197 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003198 {
anthony31f1bf72012-01-30 12:37:22 +00003199 (void) DeleteImageArtifact(image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003200 break;
3201 }
anthony31f1bf72012-01-30 12:37:22 +00003202 (void) SetImageArtifact(image,"identify:unique-colors","true");
3203 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003204 break;
3205 }
anthonydcf510d2011-10-30 13:51:40 +00003206 if (LocaleCompare("unique-colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003207 {
anthony31f1bf72012-01-30 12:37:22 +00003208 new_image=UniqueImageColors(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003209 break;
3210 }
anthonydcf510d2011-10-30 13:51:40 +00003211 if (LocaleCompare("unsharp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003212 {
anthonyfd706f92012-01-19 04:22:02 +00003213 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003214 if ((flags & SigmaValue) == 0)
3215 geometry_info.sigma=1.0;
3216 if ((flags & XiValue) == 0)
3217 geometry_info.xi=1.0;
3218 if ((flags & PsiValue) == 0)
3219 geometry_info.psi=0.05;
anthony31f1bf72012-01-30 12:37:22 +00003220 new_image=UnsharpMaskImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003221 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3222 break;
3223 }
3224 break;
3225 }
3226 case 'v':
3227 {
anthonydcf510d2011-10-30 13:51:40 +00003228 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003229 {
anthony31f1bf72012-01-30 12:37:22 +00003230 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3231 three places! ImageArtifact ImageOption image_info->verbose
3232 Some how new images also get this artifact -- how???
3233 */
3234 (void) SetImageArtifact(image,option,
3235 (plus_alt_op != MagickFalse) ? "false" : "true" );
anthony805a2d42011-09-25 08:25:12 +00003236 break;
3237 }
anthonydcf510d2011-10-30 13:51:40 +00003238 if (LocaleCompare("vignette",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003239 {
anthonyfd706f92012-01-19 04:22:02 +00003240 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003241 if ((flags & SigmaValue) == 0)
3242 geometry_info.sigma=1.0;
3243 if ((flags & XiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003244 geometry_info.xi=0.1*image->columns;
anthony805a2d42011-09-25 08:25:12 +00003245 if ((flags & PsiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003246 geometry_info.psi=0.1*image->rows;
3247 new_image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
3248 image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3249 (ssize_t) ceil(geometry_info.psi-0.5),exception);
anthony805a2d42011-09-25 08:25:12 +00003250 break;
3251 }
anthony805a2d42011-09-25 08:25:12 +00003252 break;
3253 }
3254 case 'w':
3255 {
anthonydcf510d2011-10-30 13:51:40 +00003256 if (LocaleCompare("wave",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003257 {
anthonyfd706f92012-01-19 04:22:02 +00003258 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003259 if ((flags & SigmaValue) == 0)
3260 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003261 new_image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
3262 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003263 break;
3264 }
anthonydcf510d2011-10-30 13:51:40 +00003265 if (LocaleCompare("white-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003266 {
anthony31f1bf72012-01-30 12:37:22 +00003267 (void) WhiteThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003268 break;
3269 }
3270 break;
3271 }
3272 default:
3273 break;
3274 }
3275 /*
3276 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003277 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003278 */
3279 if (new_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003280 ReplaceImageInListReturnLast(&image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003281
anthony31f1bf72012-01-30 12:37:22 +00003282 return;
anthonyfd706f92012-01-19 04:22:02 +00003283#undef image_info
3284#undef draw_info
3285#undef quantize_info
anthony31f1bf72012-01-30 12:37:22 +00003286#undef image
anthonyfd706f92012-01-19 04:22:02 +00003287#undef exception
anthony31f1bf72012-01-30 12:37:22 +00003288#undef normal_op
3289}
anthonyfd706f92012-01-19 04:22:02 +00003290
anthony31f1bf72012-01-30 12:37:22 +00003291WandExport void WandSimpleOperatorImages(MagickWand *wand,
3292 const MagickBooleanType plus_alt_op, const char *option,
3293 const char *arg1, const char *arg2)
3294{
3295 size_t
3296 n;
3297
3298 register ssize_t
3299 i;
3300
3301 assert(wand->image_info != (const ImageInfo *) NULL);
3302 assert(wand->image_info->signature == MagickSignature);
3303 assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
3304 assert(wand->images != (Image *) NULL); /* there is one image */
3305
3306 i=0;
3307 n=GetImageListLength(wand->images);
3308 wand->images=GetFirstImageInList(wand->images);
3309 for ( ; ; )
3310 {
3311 WandSimpleOperatorImage(wand, plus_alt_op, option, arg1, arg2);
3312 if ( wand->images->next == (Image *) NULL )
3313 break;
3314 wand->images=wand->images->next;
3315 i++;
3316 }
3317 wand->images=GetFirstImageInList(wand->images);
3318 return;
anthony805a2d42011-09-25 08:25:12 +00003319}
3320
3321/*
3322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3323% %
3324% %
3325% %
anthony31f1bf72012-01-30 12:37:22 +00003326+ W a n d L i s t O p e r a t o r I m a g e s %
anthony805a2d42011-09-25 08:25:12 +00003327% %
3328% %
3329% %
3330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3331%
anthony31f1bf72012-01-30 12:37:22 +00003332% WandListOperatorImages() applies a single operation that is apply to the
3333% entire image list as a whole. The result is often a complete replacment
3334% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003335%
3336% The format of the MogrifyImage method is:
3337%
anthony36a8c2c2012-02-10 00:08:44 +00003338% void WandListOperatorImages(MagickWand *wand,
3339% const MagickBooleanType plus_alt_op,const char *option,
anthony31f1bf72012-01-30 12:37:22 +00003340% const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003341%
3342% A description of each parameter follows:
3343%
anthony31f1bf72012-01-30 12:37:22 +00003344% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003345%
anthony8b10b462012-02-08 12:32:44 +00003346% o plus_alt_op: request the 'plus' or alturnative form of the operation
3347%
anthony36a8c2c2012-02-10 00:08:44 +00003348% o option: The option string for the operation
3349%
anthony31f1bf72012-01-30 12:37:22 +00003350% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003351%
anthony8b10b462012-02-08 12:32:44 +00003352% NOTE: only "limit" currently uses two arguments.
3353%
3354% Example usage...
3355%
anthonye8f56492012-02-12 12:39:02 +00003356% WandListOperatorImages(wand,MagickFalse,"duplicate", "3", NULL);
3357% WandListOperatorImages(wand,MagickTrue, "append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003358% if ( wand->exception->severity != UndefinedException ) {
3359% CatchException(exception);
3360% exit(1);
3361% }
3362%
3363% Or for handling command line arguments EG: +/-option ["arg"]
3364%
3365% argc,argv
3366% i=index in argv
3367%
3368% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
3369% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthonye8f56492012-02-12 12:39:02 +00003370% if ( (flags & ListOperatorOptionFlag) != 0 )
anthony36a8c2c2012-02-10 00:08:44 +00003371% WandListOperatorImages(wand,
3372% ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
anthony8b10b462012-02-08 12:32:44 +00003373% count>=1 ? argv[i+1] : (char *)NULL,
3374% count>=2 ? argv[i+2] : (char *)NULL );
3375% i += count+1;
3376%
anthony805a2d42011-09-25 08:25:12 +00003377*/
anthony36a8c2c2012-02-10 00:08:44 +00003378WandExport void WandListOperatorImages(MagickWand *wand,
3379 const MagickBooleanType plus_alt_op,const char *option,
3380 const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003381{
anthony31f1bf72012-01-30 12:37:22 +00003382 Image
3383 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003384
anthony31f1bf72012-01-30 12:37:22 +00003385#define image_info (wand->image_info)
3386#define draw_info (wand->draw_info)
3387#define quantize_info (wand->quantize_info)
3388#define images (wand->images)
3389#define exception (wand->exception)
3390#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
anthony805a2d42011-09-25 08:25:12 +00003391
anthony31f1bf72012-01-30 12:37:22 +00003392 assert(image_info != (const ImageInfo *) NULL);
anthony805a2d42011-09-25 08:25:12 +00003393 assert(image_info->signature == MagickSignature);
anthony31f1bf72012-01-30 12:37:22 +00003394 assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
3395 assert(images != (Image *) NULL); /* there is an image */
3396 assert(images->signature == MagickSignature); /* and is a valid image */
anthony805a2d42011-09-25 08:25:12 +00003397
anthony31f1bf72012-01-30 12:37:22 +00003398 if (wand->debug != MagickFalse)
3399 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3400
3401 (void) SyncImagesSettings(image_info,images,exception);
3402
3403 new_images=NewImageList();
3404
3405 switch (*option)
anthony805a2d42011-09-25 08:25:12 +00003406 {
3407 case 'a':
3408 {
anthony31f1bf72012-01-30 12:37:22 +00003409 if (LocaleCompare("append",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003410 {
anthony31f1bf72012-01-30 12:37:22 +00003411 new_images=AppendImages(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003412 break;
3413 }
anthony31f1bf72012-01-30 12:37:22 +00003414 if (LocaleCompare("average",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003415 {
anthony31f1bf72012-01-30 12:37:22 +00003416 /* DEPRECIATED - use -evaluate-sequence Mean */
3417 WandListOperatorImages(wand,plus_alt_op,"evaluate-sequence","Mean",
3418 NULL);
anthony805a2d42011-09-25 08:25:12 +00003419 break;
3420 }
3421 break;
3422 }
3423 case 'c':
3424 {
anthony31f1bf72012-01-30 12:37:22 +00003425 if (LocaleCompare("clut",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003426 {
anthony31f1bf72012-01-30 12:37:22 +00003427 /* FUTURE - make this a compose option (and thus layers compose )
3428 or perhaps compose last image over all other images.
3429 */
anthony805a2d42011-09-25 08:25:12 +00003430 Image
anthony31f1bf72012-01-30 12:37:22 +00003431 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003432
anthony31f1bf72012-01-30 12:37:22 +00003433 new_images=RemoveFirstImageFromList(&images);
3434 clut_image=RemoveLastImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003435 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003436 if (clut_image == (Image *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003437 break;
anthony31f1bf72012-01-30 12:37:22 +00003438 (void) ClutImage(new_images,clut_image,images->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003439 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003440 break;
3441 }
anthony31f1bf72012-01-30 12:37:22 +00003442 if (LocaleCompare("coalesce",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003443 {
anthony31f1bf72012-01-30 12:37:22 +00003444 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003445 break;
3446 }
anthony31f1bf72012-01-30 12:37:22 +00003447 if (LocaleCompare("combine",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003448 {
anthony31f1bf72012-01-30 12:37:22 +00003449 new_images=CombineImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003450 break;
3451 }
anthony31f1bf72012-01-30 12:37:22 +00003452 if (LocaleCompare("composite",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003453 {
3454 Image
3455 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003456 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003457
3458 RectangleInfo
3459 geometry;
3460
anthony31f1bf72012-01-30 12:37:22 +00003461 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003462 compose;
3463
3464 const char*
3465 value;
3466
3467 value=GetImageOption(image_info,"compose");
3468 if (value != (const char *) NULL)
3469 compose=(CompositeOperator) ParseCommandOption(
3470 MagickComposeOptions,MagickFalse,value);
3471 else
anthony31f1bf72012-01-30 12:37:22 +00003472 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003473
anthony31f1bf72012-01-30 12:37:22 +00003474 new_images=RemoveFirstImageFromList(&images);
3475 source_image=RemoveFirstImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003476 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003477 if (source_image == (Image *) NULL)
3478 break;
anthonye8f56492012-02-12 12:39:02 +00003479
anthony31f1bf72012-01-30 12:37:22 +00003480 /* FUTURE - this should not be here! - should be part of -geometry */
3481 (void) TransformImage(&source_image,(char *) NULL,
3482 source_image->geometry,exception);
anthony5f867ae2011-10-09 10:28:34 +00003483
anthony31f1bf72012-01-30 12:37:22 +00003484 SetGeometry(source_image,&geometry);
3485 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3486 GravityAdjustGeometry(new_images->columns,new_images->rows,
3487 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003488
anthony31f1bf72012-01-30 12:37:22 +00003489 mask_image=RemoveFirstImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003490 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003491 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003492 if ((compose == DisplaceCompositeOp) ||
3493 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003494 { /* Merge Y displacement into X displace/distort map. */
3495 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony6613bf32011-10-15 07:24:44 +00003496 mask_image,0,0,exception);
anthony805a2d42011-09-25 08:25:12 +00003497 mask_image=DestroyImage(mask_image);
3498 }
3499 else
3500 {
3501 /*
3502 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003503 */
cristy1539afd2012-01-30 01:32:59 +00003504 (void) NegateImage(mask_image,MagickFalse,exception);
anthony31f1bf72012-01-30 12:37:22 +00003505 (void) SetImageMask(new_images,mask_image,exception);
cristy1539afd2012-01-30 01:32:59 +00003506 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003507 }
3508 }
anthony31f1bf72012-01-30 12:37:22 +00003509 (void) CompositeImage(new_images,compose,source_image,geometry.x,
3510 geometry.y,exception);
3511 (void) SetImageMask(new_images,(Image *) NULL,exception);
3512 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003513 break;
3514 }
3515 break;
3516 }
3517 case 'd':
3518 {
anthony31f1bf72012-01-30 12:37:22 +00003519 if (LocaleCompare("deconstruct",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003520 {
anthony31f1bf72012-01-30 12:37:22 +00003521 /* DEPRECIATED - use -layers CompareAny */
3522 WandListOperatorImages(wand,plus_alt_op,"layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003523 break;
3524 }
anthony31f1bf72012-01-30 12:37:22 +00003525 if (LocaleCompare("delete",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003526 {
anthony31f1bf72012-01-30 12:37:22 +00003527 if (plus_alt_op != MagickFalse)
3528 DeleteImages(&images,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003529 else
anthony31f1bf72012-01-30 12:37:22 +00003530 DeleteImages(&images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003531 break;
3532 }
anthony31f1bf72012-01-30 12:37:22 +00003533 if (LocaleCompare("duplicate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003534 {
anthony31f1bf72012-01-30 12:37:22 +00003535 if (plus_alt_op != MagickFalse)
anthony36a8c2c2012-02-10 00:08:44 +00003536 new_images=DuplicateImages(images,1,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003537 else
3538 {
3539 const char
3540 *p;
3541
3542 size_t
3543 number_duplicates;
3544
anthony31f1bf72012-01-30 12:37:22 +00003545 number_duplicates=(size_t) StringToLong(arg1);
3546 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003547 if (p == (const char *) NULL)
anthony36a8c2c2012-02-10 00:08:44 +00003548 new_images=DuplicateImages(images,number_duplicates,
anthony805a2d42011-09-25 08:25:12 +00003549 "-1",exception);
3550 else
anthony36a8c2c2012-02-10 00:08:44 +00003551 new_images=DuplicateImages(images,number_duplicates,p,
anthony805a2d42011-09-25 08:25:12 +00003552 exception);
3553 }
anthony36a8c2c2012-02-10 00:08:44 +00003554 AppendImageToList(&images, new_images);
3555 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003556 break;
3557 }
3558 break;
3559 }
3560 case 'e':
3561 {
anthony31f1bf72012-01-30 12:37:22 +00003562 if (LocaleCompare("evaluate-sequence",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003563 {
anthony805a2d42011-09-25 08:25:12 +00003564 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003565 method;
anthony805a2d42011-09-25 08:25:12 +00003566
anthony31f1bf72012-01-30 12:37:22 +00003567 method=(MagickEvaluateOperator) ParseCommandOption(
3568 MagickEvaluateOptions,MagickFalse,arg1);
3569 new_images=EvaluateImages(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003570 break;
3571 }
3572 break;
3573 }
3574 case 'f':
3575 {
anthony31f1bf72012-01-30 12:37:22 +00003576 if (LocaleCompare("fft",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003577 {
anthony31f1bf72012-01-30 12:37:22 +00003578 new_images=ForwardFourierTransformImage(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003579 break;
3580 }
anthony31f1bf72012-01-30 12:37:22 +00003581 if (LocaleCompare("flatten",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003582 {
anthony31f1bf72012-01-30 12:37:22 +00003583 /* DEPRECIATED use -layers mosaic instead */
3584 WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
anthony805a2d42011-09-25 08:25:12 +00003585 break;
3586 }
anthony31f1bf72012-01-30 12:37:22 +00003587 if (LocaleCompare("fx",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003588 {
anthony31f1bf72012-01-30 12:37:22 +00003589 new_images=FxImage(images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003590 break;
3591 }
3592 break;
3593 }
3594 case 'h':
3595 {
anthony31f1bf72012-01-30 12:37:22 +00003596 if (LocaleCompare("hald-clut",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003597 {
anthony31f1bf72012-01-30 12:37:22 +00003598 /* FUTURE - make this a compose option (and thus layers compose )
3599 or perhaps compose last image over all other images.
3600 */
anthony805a2d42011-09-25 08:25:12 +00003601 Image
anthony31f1bf72012-01-30 12:37:22 +00003602 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003603
anthony31f1bf72012-01-30 12:37:22 +00003604 new_images=RemoveFirstImageFromList(&images);
3605 hald_image=RemoveLastImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003606 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003607 break;
3608 (void) HaldClutImage(new_images,hald_image,exception);
anthony805a2d42011-09-25 08:25:12 +00003609 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003610 break;
3611 }
3612 break;
3613 }
3614 case 'i':
3615 {
anthony31f1bf72012-01-30 12:37:22 +00003616 if (LocaleCompare("ift",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003617 {
3618 Image
anthony805a2d42011-09-25 08:25:12 +00003619 *magnitude_image,
3620 *phase_image;
3621
anthony31f1bf72012-01-30 12:37:22 +00003622 magnitude_image=RemoveFirstImageFromList(&images);
3623 phase_image=RemoveFirstImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003624 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003625 if (phase_image == (Image *) NULL)
3626 break;
3627 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3628 normal_op,exception);
3629 magnitude_image=DestroyImage(magnitude_image);
3630 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003631 break;
3632 }
anthony31f1bf72012-01-30 12:37:22 +00003633 if (LocaleCompare("insert",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003634 {
3635 Image
anthony31f1bf72012-01-30 12:37:22 +00003636 *insert_image,
3637 *index_image;
3638
3639 ssize_t
3640 index;
anthony805a2d42011-09-25 08:25:12 +00003641
3642 index=0;
anthony31f1bf72012-01-30 12:37:22 +00003643 insert_image=RemoveLastImageFromList(&images);
3644 if (plus_alt_op == MagickFalse)
3645 index=(ssize_t) StringToLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00003646 if (index == 0)
anthony31f1bf72012-01-30 12:37:22 +00003647 PrependImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003648 else
anthony31f1bf72012-01-30 12:37:22 +00003649 if (index == (ssize_t) GetImageListLength(images))
3650 AppendImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003651 else
3652 {
anthony31f1bf72012-01-30 12:37:22 +00003653 index_image=GetImageFromList(images,index-1);
3654 if (index_image == (Image *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003655 {
3656 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00003657 OptionError,"NoSuchImage","`%s'",arg1);
anthony805a2d42011-09-25 08:25:12 +00003658 break;
3659 }
anthony31f1bf72012-01-30 12:37:22 +00003660 InsertImageInList(&index_image,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003661 }
anthony31f1bf72012-01-30 12:37:22 +00003662 images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003663 break;
3664 }
anthony805a2d42011-09-25 08:25:12 +00003665 break;
3666 }
3667 case 'l':
3668 {
anthony31f1bf72012-01-30 12:37:22 +00003669 if (LocaleCompare("layers",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003670 {
anthony805a2d42011-09-25 08:25:12 +00003671 ImageLayerMethod
3672 method;
3673
anthony805a2d42011-09-25 08:25:12 +00003674 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003675 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003676 switch (method)
3677 {
3678 case CoalesceLayer:
3679 {
anthony31f1bf72012-01-30 12:37:22 +00003680 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003681 break;
3682 }
3683 case CompareAnyLayer:
3684 case CompareClearLayer:
3685 case CompareOverlayLayer:
3686 default:
3687 {
anthony31f1bf72012-01-30 12:37:22 +00003688 new_images=CompareImagesLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003689 break;
3690 }
3691 case MergeLayer:
3692 case FlattenLayer:
3693 case MosaicLayer:
3694 case TrimBoundsLayer:
3695 {
anthony31f1bf72012-01-30 12:37:22 +00003696 new_images=MergeImageLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003697 break;
3698 }
3699 case DisposeLayer:
3700 {
anthony31f1bf72012-01-30 12:37:22 +00003701 new_images=DisposeImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003702 break;
3703 }
3704 case OptimizeImageLayer:
3705 {
anthony31f1bf72012-01-30 12:37:22 +00003706 new_images=OptimizeImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003707 break;
3708 }
3709 case OptimizePlusLayer:
3710 {
anthony31f1bf72012-01-30 12:37:22 +00003711 new_images=OptimizePlusImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003712 break;
3713 }
3714 case OptimizeTransLayer:
3715 {
anthony31f1bf72012-01-30 12:37:22 +00003716 OptimizeImageTransparency(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003717 break;
3718 }
3719 case RemoveDupsLayer:
3720 {
anthony31f1bf72012-01-30 12:37:22 +00003721 RemoveDuplicateLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003722 break;
3723 }
3724 case RemoveZeroLayer:
3725 {
anthony31f1bf72012-01-30 12:37:22 +00003726 RemoveZeroDelayLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003727 break;
3728 }
3729 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003730 { /* General Purpose, GIF Animation Optimizer. */
3731 new_images=CoalesceImages(images,exception);
3732 if (new_images == (Image *) NULL)
3733 break;
3734 images=DestroyImageList(images);
3735 images=OptimizeImageLayers(new_images,exception);
3736 if (images == (Image *) NULL)
3737 break;
3738 new_images=DestroyImageList(new_images);
3739 OptimizeImageTransparency(images,exception);
3740 (void) RemapImages(quantize_info,images,(Image *) NULL,
anthony805a2d42011-09-25 08:25:12 +00003741 exception);
3742 break;
3743 }
3744 case CompositeLayer:
3745 {
anthony805a2d42011-09-25 08:25:12 +00003746 Image
3747 *source;
3748
3749 RectangleInfo
3750 geometry;
3751
anthony31f1bf72012-01-30 12:37:22 +00003752 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003753 compose;
3754
3755 const char*
3756 value;
3757
3758 value=GetImageOption(image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003759 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003760 if (value != (const char *) NULL)
3761 compose=(CompositeOperator) ParseCommandOption(
3762 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003763
anthony31f1bf72012-01-30 12:37:22 +00003764 /* Split image sequence at the first 'NULL:' image. */
3765 source=images;
anthony805a2d42011-09-25 08:25:12 +00003766 while (source != (Image *) NULL)
3767 {
3768 source=GetNextImageInList(source);
3769 if ((source != (Image *) NULL) &&
3770 (LocaleCompare(source->magick,"NULL") == 0))
3771 break;
3772 }
3773 if (source != (Image *) NULL)
3774 {
3775 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3776 (GetNextImageInList(source) == (Image *) NULL))
3777 source=(Image *) NULL;
3778 else
anthony31f1bf72012-01-30 12:37:22 +00003779 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003780 source=SplitImageList(source->previous);
3781 DeleteImageFromList(&source);
3782 }
3783 }
3784 if (source == (Image *) NULL)
3785 {
3786 (void) ThrowMagickException(exception,GetMagickModule(),
3787 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003788 break;
3789 }
anthony31f1bf72012-01-30 12:37:22 +00003790 /* Adjust offset with gravity and virtual canvas. */
3791 SetGeometry(images,&geometry);
3792 (void) ParseAbsoluteGeometry(images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003793 geometry.width=source->page.width != 0 ?
3794 source->page.width : source->columns;
3795 geometry.height=source->page.height != 0 ?
3796 source->page.height : source->rows;
anthony31f1bf72012-01-30 12:37:22 +00003797 GravityAdjustGeometry(images->page.width != 0 ?
3798 images->page.width : images->columns,
3799 images->page.height != 0 ? images->page.height :
3800 images->rows,images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003801
anthony31f1bf72012-01-30 12:37:22 +00003802 /* Compose the two image sequences together */
3803 CompositeLayers(images,compose,source,geometry.x,geometry.y,
anthony805a2d42011-09-25 08:25:12 +00003804 exception);
3805 source=DestroyImageList(source);
3806 break;
3807 }
3808 }
anthony805a2d42011-09-25 08:25:12 +00003809 break;
3810 }
anthony72feaa62012-01-17 06:46:23 +00003811 if (LocaleCompare("limit",option) == 0)
3812 {
3813 MagickSizeType
3814 limit;
3815
3816 ResourceType
3817 type;
3818
anthony72feaa62012-01-17 06:46:23 +00003819 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003820 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003821 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003822 if (LocaleCompare("unlimited",arg2) != 0)
3823 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003824 (void) SetMagickResourceLimit(type,limit);
3825 break;
3826 }
anthony805a2d42011-09-25 08:25:12 +00003827 break;
3828 }
3829 case 'm':
3830 {
anthony31f1bf72012-01-30 12:37:22 +00003831 if (LocaleCompare("map",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003832 {
anthony31f1bf72012-01-30 12:37:22 +00003833 /* DEPRECIATED use +remap */
3834 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00003835 break;
3836 }
anthony31f1bf72012-01-30 12:37:22 +00003837 if (LocaleCompare("morph",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003838 {
3839 Image
3840 *morph_image;
3841
anthony31f1bf72012-01-30 12:37:22 +00003842 morph_image=MorphImages(images,StringToUnsignedLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00003843 exception);
3844 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003845 break;
3846 images=DestroyImageList(images);
3847 images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00003848 break;
3849 }
anthony31f1bf72012-01-30 12:37:22 +00003850 if (LocaleCompare("mosaic",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003851 {
anthony31f1bf72012-01-30 12:37:22 +00003852 /* DEPRECIATED use -layers mosaic instead */
3853 WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
anthony805a2d42011-09-25 08:25:12 +00003854 break;
3855 }
3856 break;
3857 }
3858 case 'p':
3859 {
anthony31f1bf72012-01-30 12:37:22 +00003860 if (LocaleCompare("print",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003861 {
3862 char
3863 *string;
3864
anthony31f1bf72012-01-30 12:37:22 +00003865 string=InterpretImageProperties(image_info,images,arg1,
anthony805a2d42011-09-25 08:25:12 +00003866 exception);
3867 if (string == (char *) NULL)
3868 break;
3869 (void) FormatLocaleFile(stdout,"%s",string);
3870 string=DestroyString(string);
3871 }
anthony31f1bf72012-01-30 12:37:22 +00003872 if (LocaleCompare("process",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003873 {
3874 char
3875 **arguments;
3876
3877 int
3878 j,
3879 number_arguments;
3880
anthony31f1bf72012-01-30 12:37:22 +00003881 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00003882 if (arguments == (char **) NULL)
3883 break;
anthony31f1bf72012-01-30 12:37:22 +00003884 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003885 {
3886 char
3887 breaker,
3888 quote,
3889 *token;
3890
3891 const char
3892 *arguments;
3893
3894 int
3895 next,
3896 status;
3897
3898 size_t
3899 length;
3900
3901 TokenInfo
3902 *token_info;
3903
3904 /*
3905 Support old style syntax, filter="-option arg".
3906 */
anthony31f1bf72012-01-30 12:37:22 +00003907 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00003908 token=(char *) NULL;
3909 if (~length >= (MaxTextExtent-1))
3910 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
3911 sizeof(*token));
3912 if (token == (char *) NULL)
3913 break;
3914 next=0;
anthony31f1bf72012-01-30 12:37:22 +00003915 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00003916 token_info=AcquireTokenInfo();
3917 status=Tokenizer(token_info,0,token,length,arguments,"","=",
3918 "\"",'\0',&breaker,&next,&quote);
3919 token_info=DestroyTokenInfo(token_info);
3920 if (status == 0)
3921 {
3922 const char
3923 *argv;
3924
3925 argv=(&(arguments[next]));
anthony31f1bf72012-01-30 12:37:22 +00003926 (void) InvokeDynamicImageFilter(token,&images,1,&argv,
anthony805a2d42011-09-25 08:25:12 +00003927 exception);
3928 }
3929 token=DestroyString(token);
3930 break;
3931 }
3932 (void) SubstituteString(&arguments[1],"-","");
anthony31f1bf72012-01-30 12:37:22 +00003933 (void) InvokeDynamicImageFilter(arguments[1],&images,
anthony805a2d42011-09-25 08:25:12 +00003934 number_arguments-2,(const char **) arguments+2,exception);
3935 for (j=0; j < number_arguments; j++)
3936 arguments[j]=DestroyString(arguments[j]);
3937 arguments=(char **) RelinquishMagickMemory(arguments);
3938 break;
3939 }
3940 break;
3941 }
3942 case 'r':
3943 {
anthony31f1bf72012-01-30 12:37:22 +00003944 if (LocaleCompare("remap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003945 {
anthony31f1bf72012-01-30 12:37:22 +00003946 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3947 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3948 break;
3949 }
3950 if (LocaleCompare("reverse",option) == 0)
3951 {
3952 ReverseImageList(&images);
anthony805a2d42011-09-25 08:25:12 +00003953 break;
3954 }
3955 break;
3956 }
3957 case 's':
3958 {
anthony31f1bf72012-01-30 12:37:22 +00003959 if (LocaleCompare("smush",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003960 {
3961 Image
3962 *smush_image;
3963
3964 ssize_t
3965 offset;
3966
anthony31f1bf72012-01-30 12:37:22 +00003967 offset=(ssize_t) StringToLong(arg1);
3968 smush_image=SmushImages(images,normal_op,offset,exception);
anthony805a2d42011-09-25 08:25:12 +00003969 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003970 break;
3971 images=DestroyImageList(images);
3972 images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00003973 break;
3974 }
anthony31f1bf72012-01-30 12:37:22 +00003975 if (LocaleCompare("swap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003976 {
3977 Image
3978 *p,
3979 *q,
3980 *swap;
3981
3982 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00003983 index,
anthony805a2d42011-09-25 08:25:12 +00003984 swap_index;
3985
anthony31f1bf72012-01-30 12:37:22 +00003986 index=-1;
3987 swap_index=-2;
3988 if (plus_alt_op == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003989 {
3990 GeometryInfo
3991 geometry_info;
3992
3993 MagickStatusType
3994 flags;
3995
3996 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00003997 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003998 index=(ssize_t) geometry_info.rho;
3999 if ((flags & SigmaValue) != 0)
4000 swap_index=(ssize_t) geometry_info.sigma;
4001 }
anthony31f1bf72012-01-30 12:37:22 +00004002 p=GetImageFromList(images,index);
4003 q=GetImageFromList(images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004004 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4005 {
4006 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00004007 OptionError,"NoSuchImage","`%s'",images->filename);
anthony805a2d42011-09-25 08:25:12 +00004008 break;
4009 }
4010 if (p == q)
4011 break;
4012 swap=CloneImage(p,0,0,MagickTrue,exception);
4013 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4014 ReplaceImageInList(&q,swap);
anthony31f1bf72012-01-30 12:37:22 +00004015 images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004016 break;
4017 }
4018 break;
4019 }
4020 case 'w':
4021 {
anthony31f1bf72012-01-30 12:37:22 +00004022 if (LocaleCompare("write",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00004023 {
4024 char
4025 key[MaxTextExtent];
4026
4027 Image
4028 *write_images;
4029
4030 ImageInfo
4031 *write_info;
4032
anthony31f1bf72012-01-30 12:37:22 +00004033 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004034 (void) DeleteImageRegistry(key);
anthony31f1bf72012-01-30 12:37:22 +00004035 write_images=images;
4036 if (plus_alt_op != MagickFalse)
4037 write_images=CloneImageList(images,exception);
anthony805a2d42011-09-25 08:25:12 +00004038 write_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00004039 (void) WriteImages(write_info,write_images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00004040 write_info=DestroyImageInfo(write_info);
anthony31f1bf72012-01-30 12:37:22 +00004041 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00004042 write_images=DestroyImageList(write_images);
4043 break;
4044 }
4045 break;
4046 }
4047 default:
4048 break;
4049 }
anthony31f1bf72012-01-30 12:37:22 +00004050 if (new_images == (Image *) NULL)
4051 return;
anthony805a2d42011-09-25 08:25:12 +00004052
anthony31f1bf72012-01-30 12:37:22 +00004053 if (images != (Image *) NULL)
4054 images=DestroyImageList(images);
4055 images=new_images;
4056 return;
4057
4058#undef image_info
4059#undef draw_info
4060#undef quantize_info
4061#undef images
4062#undef exception
4063#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004064}