blob: ada9bc538a6c42de11cce6587b2e8be75d537bb4 [file] [log] [blame]
anthony805a2d42011-09-25 08:25:12 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% OOO PPPP EEEE RRRR AA TTTTTT III OOO N N %
7% O O P P E R R A A TT I O O NN N %
8% O O PPPP EEE RRRR AAAA TT I O O N N N %
9% O O P E R R A A TT I O O N NN %
10% OOO P EEEE R RR A A TT III OOO N N %
11% %
12% %
13% MagickWand Module Methods %
14% %
15% Software Design %
16% John Cristy %
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
37% the given image(s) according to the current "image_info" and "draw_info"
38% settings.
39%
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%
44% Anthony Thyssen, Sept 2011
45*/
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% %
anthonyd1447672012-01-19 05:33:53 +0000354+ W a n d S e t t i n g O p t i o n I n f 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
anthony72feaa62012-01-17 06:46:23 +0000906 list=ParseCommandOption(MagickListOptions,MagickFalse,
907 ArgOption("list"));
anthony805a2d42011-09-25 08:25:12 +0000908 switch (list)
909 {
910 case MagickCoderOptions:
911 {
912 (void) ListCoderInfo((FILE *) NULL,exception);
913 break;
914 }
915 case MagickColorOptions:
916 {
917 (void) ListColorInfo((FILE *) NULL,exception);
918 break;
919 }
920 case MagickConfigureOptions:
921 {
922 (void) ListConfigureInfo((FILE *) NULL,exception);
923 break;
924 }
925 case MagickDelegateOptions:
926 {
927 (void) ListDelegateInfo((FILE *) NULL,exception);
928 break;
929 }
930 case MagickFontOptions:
931 {
932 (void) ListTypeInfo((FILE *) NULL,exception);
933 break;
934 }
935 case MagickFormatOptions:
936 {
937 (void) ListMagickInfo((FILE *) NULL,exception);
938 break;
939 }
940 case MagickLocaleOptions:
941 {
942 (void) ListLocaleInfo((FILE *) NULL,exception);
943 break;
944 }
945 case MagickLogOptions:
946 {
947 (void) ListLogInfo((FILE *) NULL,exception);
948 break;
949 }
950 case MagickMagicOptions:
951 {
952 (void) ListMagicInfo((FILE *) NULL,exception);
953 break;
954 }
955 case MagickMimeOptions:
956 {
957 (void) ListMimeInfo((FILE *) NULL,exception);
958 break;
959 }
960 case MagickModuleOptions:
961 {
962 (void) ListModuleInfo((FILE *) NULL,exception);
963 break;
964 }
965 case MagickPolicyOptions:
966 {
967 (void) ListPolicyInfo((FILE *) NULL,exception);
968 break;
969 }
970 case MagickResourceOptions:
971 {
972 (void) ListMagickResourceInfo((FILE *) NULL,exception);
973 break;
974 }
975 case MagickThresholdOptions:
976 {
977 (void) ListThresholdMaps((FILE *) NULL,exception);
978 break;
979 }
980 default:
981 {
982 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
983 exception);
984 break;
985 }
986 }
987 break;
988 }
anthony74b1cfc2011-10-06 12:44:16 +0000989 if (LocaleCompare("log",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000990 {
anthonydcf510d2011-10-30 13:51:40 +0000991 if (IfSetOption)
992 (void) SetLogFormat(arg);
anthony805a2d42011-09-25 08:25:12 +0000993 break;
994 }
anthony74b1cfc2011-10-06 12:44:16 +0000995 if (LocaleCompare("loop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000996 {
anthony72feaa62012-01-17 06:46:23 +0000997 /* SyncImageSettings() used to set per-image attribute. */
998 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000999 break;
1000 }
1001 break;
1002 }
1003 case 'm':
1004 {
anthony74b1cfc2011-10-06 12:44:16 +00001005 if (LocaleCompare("mattecolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001006 {
anthony72feaa62012-01-17 06:46:23 +00001007 /* SyncImageSettings() used to set per-image attribute. */
1008 (void) SetImageOption(image_info,option,ArgOption(NULL));
1009 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1010 &image_info->matte_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001011 break;
1012 }
anthony74b1cfc2011-10-06 12:44:16 +00001013 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001014 {
anthony31f1bf72012-01-30 12:37:22 +00001015 (void) SetImageInfoProgressMonitor(image_info, IfSetOption?
1016 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001017 break;
1018 }
anthony74b1cfc2011-10-06 12:44:16 +00001019 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001020 {
anthony72feaa62012-01-17 06:46:23 +00001021 /* Setting (for some input coders)
1022 But also a special 'type' operator
1023 */
1024 image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001025 break;
1026 }
1027 break;
1028 }
1029 case 'o':
1030 {
anthony74b1cfc2011-10-06 12:44:16 +00001031 if (LocaleCompare("orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001032 {
anthony72feaa62012-01-17 06:46:23 +00001033 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001034 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001035 FUTURE: make set meta-data operator instead.
1036 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001037 */
anthony72feaa62012-01-17 06:46:23 +00001038 (void) SetImageOption(image_info,option, ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001039 image_info->orientation=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001040 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001041 break;
1042 }
1043 }
1044 case 'p':
1045 {
anthony74b1cfc2011-10-06 12:44:16 +00001046 if (LocaleCompare("page",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001047 {
anthony72feaa62012-01-17 06:46:23 +00001048 /* Only used for new images and image generators
1049 SyncImageSettings() used to set per-image attribute. ?????
1050 That last is WRONG!!!!
1051 */
anthony805a2d42011-09-25 08:25:12 +00001052 char
1053 *canonical_page,
1054 page[MaxTextExtent];
1055
1056 const char
1057 *image_option;
1058
1059 MagickStatusType
1060 flags;
1061
1062 RectangleInfo
1063 geometry;
1064
anthonydcf510d2011-10-30 13:51:40 +00001065 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001066 {
anthony74b1cfc2011-10-06 12:44:16 +00001067 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +00001068 (void) CloneString(&image_info->page,(char *) NULL);
1069 break;
1070 }
1071 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1072 image_option=GetImageOption(image_info,"page");
1073 if (image_option != (const char *) NULL)
1074 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthonydcf510d2011-10-30 13:51:40 +00001075 canonical_page=GetPageGeometry(arg);
anthony805a2d42011-09-25 08:25:12 +00001076 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1077 canonical_page=DestroyString(canonical_page);
1078 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1079 (unsigned long) geometry.width,(unsigned long) geometry.height);
1080 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1081 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1082 (unsigned long) geometry.width,(unsigned long) geometry.height,
1083 (long) geometry.x,(long) geometry.y);
anthony74b1cfc2011-10-06 12:44:16 +00001084 (void) SetImageOption(image_info,option,page);
anthony805a2d42011-09-25 08:25:12 +00001085 (void) CloneString(&image_info->page,page);
1086 break;
1087 }
anthony74b1cfc2011-10-06 12:44:16 +00001088 if (LocaleCompare("ping",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001089 {
anthony72feaa62012-01-17 06:46:23 +00001090 image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001091 break;
1092 }
anthony74b1cfc2011-10-06 12:44:16 +00001093 if (LocaleCompare("pointsize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001094 {
anthony72feaa62012-01-17 06:46:23 +00001095 image_info->pointsize=draw_info->pointsize=
1096 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001097 break;
1098 }
anthony74b1cfc2011-10-06 12:44:16 +00001099 if (LocaleCompare("precision",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001100 {
anthony72feaa62012-01-17 06:46:23 +00001101 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001102 break;
1103 }
anthonydcf510d2011-10-30 13:51:40 +00001104 /* FUTURE: Only the 'preview' coder appears to use this
1105 * Depreciate the coder? Leaving only the 'preview' operator.
anthony74b1cfc2011-10-06 12:44:16 +00001106 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001107 {
anthonydcf510d2011-10-30 13:51:40 +00001108 image_info->preview_type=UndefinedPreview;
1109 if (IfSetOption)
1110 image_info->preview_type=(PreviewType) ParseCommandOption(
1111 MagickPreviewOptions,MagickFalse,arg);
anthony805a2d42011-09-25 08:25:12 +00001112 break;
1113 }
anthonydcf510d2011-10-30 13:51:40 +00001114 */
anthony805a2d42011-09-25 08:25:12 +00001115 break;
1116 }
1117 case 'q':
1118 {
anthony74b1cfc2011-10-06 12:44:16 +00001119 if (LocaleCompare("quality",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001120 {
anthony72feaa62012-01-17 06:46:23 +00001121 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001122 image_info->quality=UndefinedCompressionQuality;
anthony72feaa62012-01-17 06:46:23 +00001123 if (IfSetOption)
1124 image_info->quality=StringToUnsignedLong(arg);
anthony805a2d42011-09-25 08:25:12 +00001125 break;
1126 }
anthonyafbaed72011-10-26 12:05:04 +00001127 if (LocaleCompare("quantize",option) == 0)
1128 {
anthony72feaa62012-01-17 06:46:23 +00001129 /* Just a set direct in quantize_info */
anthonyafbaed72011-10-26 12:05:04 +00001130 quantize_info->colorspace=UndefinedColorspace;
1131 if (IfSetOption)
1132 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthonydcf510d2011-10-30 13:51:40 +00001133 MagickColorspaceOptions,MagickFalse,arg);
anthonyafbaed72011-10-26 12:05:04 +00001134 break;
1135 }
anthony74b1cfc2011-10-06 12:44:16 +00001136 if (LocaleCompare("quiet",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001137 {
anthonydcf510d2011-10-30 13:51:40 +00001138 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001139 static WarningHandler
1140 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001141
anthonyafbaed72011-10-26 12:05:04 +00001142 WarningHandler
1143 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001144
anthonyafbaed72011-10-26 12:05:04 +00001145 if ( tmp != (WarningHandler) NULL)
1146 warning_handler = tmp; /* remember the old handler */
1147 if (!IfSetOption) /* set the old handler */
1148 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001149 break;
1150 }
1151 break;
1152 }
1153 case 'r':
1154 {
anthony74b1cfc2011-10-06 12:44:16 +00001155 if (LocaleCompare("red-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001156 {
anthonydcf510d2011-10-30 13:51:40 +00001157 /* Image chromaticity X,Y NB: Y=X if Y not defined
1158 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001159 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001160 */
anthony72feaa62012-01-17 06:46:23 +00001161 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001162 break;
1163 }
anthonyafbaed72011-10-26 12:05:04 +00001164 if (LocaleCompare("render",option) == 0)
1165 {
1166 /* draw_info only setting */
1167 draw_info->render= IfSetOption ? MagickFalse : MagickTrue;
1168 break;
1169 }
anthony805a2d42011-09-25 08:25:12 +00001170 break;
1171 }
1172 case 's':
1173 {
anthony74b1cfc2011-10-06 12:44:16 +00001174 if (LocaleCompare("sampling-factor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001175 {
anthonyafbaed72011-10-26 12:05:04 +00001176 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony72feaa62012-01-17 06:46:23 +00001177 (void) CloneString(&image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001178 break;
1179 }
anthony74b1cfc2011-10-06 12:44:16 +00001180 if (LocaleCompare("scene",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001181 {
anthony72feaa62012-01-17 06:46:23 +00001182 /* SyncImageSettings() used to set per-image attribute.
1183 What ??? Why ????
1184 */
1185 (void) SetImageOption(image_info,option,ArgOption(NULL));
1186 image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001187 break;
1188 }
anthony74b1cfc2011-10-06 12:44:16 +00001189 if (LocaleCompare("seed",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001190 {
anthonyafbaed72011-10-26 12:05:04 +00001191 SeedPseudoRandomGenerator(
anthonydcf510d2011-10-30 13:51:40 +00001192 IfSetOption ? (size_t) StringToUnsignedLong(arg)
anthonyafbaed72011-10-26 12:05:04 +00001193 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001194 break;
1195 }
anthony74b1cfc2011-10-06 12:44:16 +00001196 if (LocaleCompare("size",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001197 {
anthonyafbaed72011-10-26 12:05:04 +00001198 /* FUTURE: string in image_info -- convert to Option ???
1199 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001200 */
anthony72feaa62012-01-17 06:46:23 +00001201 (void) CloneString(&image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001202 break;
1203 }
1204 if (LocaleCompare("stretch",option) == 0)
1205 {
anthony72feaa62012-01-17 06:46:23 +00001206 draw_info->stretch=(StretchType) ParseCommandOption(
1207 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001208 break;
1209 }
anthony74b1cfc2011-10-06 12:44:16 +00001210 if (LocaleCompare("stroke",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001211 {
anthonyafbaed72011-10-26 12:05:04 +00001212 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001213 UPDATE: ensure stroke color is not destroyed is a pattern
1214 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001215 */
1216 const char
anthony72feaa62012-01-17 06:46:23 +00001217 *value;
1218
1219 MagickBooleanType
1220 status;
anthonyafbaed72011-10-26 12:05:04 +00001221
1222 ExceptionInfo
1223 *sans;
1224
anthonyfd706f92012-01-19 04:22:02 +00001225 PixelInfo
1226 color;
1227
anthony72feaa62012-01-17 06:46:23 +00001228 value = ArgOption("none");
anthonyafbaed72011-10-26 12:05:04 +00001229 (void) SetImageOption(image_info,option,value);
anthony72feaa62012-01-17 06:46:23 +00001230 if (draw_info->stroke_pattern != (Image *) NULL)
1231 draw_info->stroke_pattern=DestroyImage(draw_info->stroke_pattern);
1232
1233 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001234 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +00001235 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001236 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001237
anthonyafbaed72011-10-26 12:05:04 +00001238 if (status == MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00001239 draw_info->stroke_pattern=GetImageCache(image_info,value,exception);
1240 else
1241 draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001242 break;
1243 }
anthony74b1cfc2011-10-06 12:44:16 +00001244 if (LocaleCompare("strokewidth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001245 {
anthony72feaa62012-01-17 06:46:23 +00001246 (void) SetImageOption(image_info,option,ArgOption(NULL));
1247 draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1248 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001249 break;
1250 }
1251 if (LocaleCompare("style",option) == 0)
1252 {
anthony72feaa62012-01-17 06:46:23 +00001253 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1254 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001255 break;
1256 }
anthony74b1cfc2011-10-06 12:44:16 +00001257 if (LocaleCompare("synchronize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001258 {
anthony72feaa62012-01-17 06:46:23 +00001259 image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001260 break;
1261 }
1262 break;
1263 }
1264 case 't':
1265 {
anthony74b1cfc2011-10-06 12:44:16 +00001266 if (LocaleCompare("taint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001267 {
anthony72feaa62012-01-17 06:46:23 +00001268 /* SyncImageSettings() used to set per-image attribute. */
anthonyafbaed72011-10-26 12:05:04 +00001269 (void) SetImageOption(image_info,option,
1270 IfSetOption ? "true" : "false");
anthony805a2d42011-09-25 08:25:12 +00001271 break;
1272 }
anthony74b1cfc2011-10-06 12:44:16 +00001273 if (LocaleCompare("texture",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001274 {
anthonyafbaed72011-10-26 12:05:04 +00001275 /* FUTURE: move image_info string to option splay-tree */
anthony72feaa62012-01-17 06:46:23 +00001276 (void) CloneString(&image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001277 break;
1278 }
1279 if (LocaleCompare("tile",option) == 0)
1280 {
anthony72feaa62012-01-17 06:46:23 +00001281 draw_info->fill_pattern=IfSetOption
1282 ?GetImageCache(image_info,arg,exception)
1283 :DestroyImage(draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001284 break;
1285 }
anthony74b1cfc2011-10-06 12:44:16 +00001286 if (LocaleCompare("tile-offset",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001287 {
anthony72feaa62012-01-17 06:46:23 +00001288 /* SyncImageSettings() used to set per-image attribute. ??? */
1289 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001290 break;
1291 }
anthony74b1cfc2011-10-06 12:44:16 +00001292 if (LocaleCompare("transparent-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001293 {
anthonyafbaed72011-10-26 12:05:04 +00001294 /* FUTURE: both image_info attribute & ImageOption in use!
1295 image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001296 SyncImageSettings() used to set per-image attribute.
1297
anthonyafbaed72011-10-26 12:05:04 +00001298 Note that +transparent-color, means fall-back to image
1299 attribute so ImageOption is deleted, not set to a default.
1300 */
anthony72feaa62012-01-17 06:46:23 +00001301 (void) SetImageOption(image_info,option,ArgOption(NULL));
1302 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1303 &image_info->transparent_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001304 break;
1305 }
anthony31f1bf72012-01-30 12:37:22 +00001306 if (LocaleCompare("treedepth",option) == 0)
1307 {
1308 (void) SetImageOption(image_info,option,ArgOption(NULL));
1309 quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1310 break;
1311 }
anthony74b1cfc2011-10-06 12:44:16 +00001312 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001313 {
anthony72feaa62012-01-17 06:46:23 +00001314 /* SyncImageSettings() used to set per-image attribute. */
1315 (void) SetImageOption(image_info,option,ArgOption(NULL));
1316 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1317 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001318 break;
1319 }
1320 break;
1321 }
1322 case 'u':
1323 {
anthony74b1cfc2011-10-06 12:44:16 +00001324 if (LocaleCompare("undercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001325 {
anthony72feaa62012-01-17 06:46:23 +00001326 (void) SetImageOption(image_info,option,ArgOption(NULL));
1327 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1328 &draw_info->undercolor,exception);
anthony805a2d42011-09-25 08:25:12 +00001329 break;
1330 }
anthony74b1cfc2011-10-06 12:44:16 +00001331 if (LocaleCompare("units",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001332 {
anthony72feaa62012-01-17 06:46:23 +00001333 /* SyncImageSettings() used to set per-image attribute.
1334 Should this effect draw_info X and Y resolution?
1335 FUTURE: this probably should be part of the density setting
1336 */
1337 (void) SetImageOption(image_info,option,ArgOption(NULL));
1338 image_info->units=(ResolutionType) ParseCommandOption(
1339 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001340 break;
1341 }
1342 break;
1343 }
1344 case 'v':
1345 {
anthony74b1cfc2011-10-06 12:44:16 +00001346 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001347 {
anthonyab3a50c2011-10-27 11:48:57 +00001348 /* FUTURE: Also an image artifact, set in Simple Operators.
1349 But artifact is only used in verbose output.
1350 */
anthony31f1bf72012-01-30 12:37:22 +00001351 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001352 image_info->verbose= ArgBoolean;
anthonyab3a50c2011-10-27 11:48:57 +00001353 image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001354 break;
1355 }
anthony74b1cfc2011-10-06 12:44:16 +00001356 if (LocaleCompare("view",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001357 {
anthony72feaa62012-01-17 06:46:23 +00001358 /* FUTURE: Convert from image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001359 Only used by coder FPX
1360 */
anthony72feaa62012-01-17 06:46:23 +00001361 (void) CloneString(&image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001362 break;
1363 }
anthony74b1cfc2011-10-06 12:44:16 +00001364 if (LocaleCompare("virtual-pixel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001365 {
anthonyfd706f92012-01-19 04:22:02 +00001366 /* SyncImageSettings() used to set per-image attribute.
1367 This is VERY deep in the image caching structure.
1368 */
anthony72feaa62012-01-17 06:46:23 +00001369 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001370 break;
1371 }
1372 break;
1373 }
1374 case 'w':
1375 {
anthonydcf510d2011-10-30 13:51:40 +00001376 if (LocaleCompare("weight",option) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001377 {
anthony72feaa62012-01-17 06:46:23 +00001378 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001379 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001380 */
anthony72feaa62012-01-17 06:46:23 +00001381 if (!IfSetOption)
1382 break;
anthonydcf510d2011-10-30 13:51:40 +00001383 draw_info->weight=StringToUnsignedLong(arg);
1384 if (LocaleCompare(arg,"all") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001385 draw_info->weight=0;
anthonydcf510d2011-10-30 13:51:40 +00001386 if (LocaleCompare(arg,"bold") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001387 draw_info->weight=700;
anthonydcf510d2011-10-30 13:51:40 +00001388 if (LocaleCompare(arg,"bolder") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001389 if (draw_info->weight <= 800)
1390 draw_info->weight+=100;
anthonydcf510d2011-10-30 13:51:40 +00001391 if (LocaleCompare(arg,"lighter") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001392 if (draw_info->weight >= 100)
1393 draw_info->weight-=100;
anthonydcf510d2011-10-30 13:51:40 +00001394 if (LocaleCompare(arg,"normal") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001395 draw_info->weight=400;
1396 break;
1397 }
anthony74b1cfc2011-10-06 12:44:16 +00001398 if (LocaleCompare("white-point",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001399 {
anthony72feaa62012-01-17 06:46:23 +00001400 /* Used as a image chromaticity setting
1401 SyncImageSettings() used to set per-image attribute.
1402 */
1403 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001404 break;
1405 }
1406 break;
1407 }
1408 default:
1409 break;
1410 }
anthonyfd706f92012-01-19 04:22:02 +00001411#undef image_info
1412#undef draw_info
1413#undef quantize_info
1414#undef exception
1415#undef IfSetOption
1416#undef ArgOption
1417#undef ArgBoolean
1418
anthony31f1bf72012-01-30 12:37:22 +00001419 return;
anthony805a2d42011-09-25 08:25:12 +00001420}
1421
1422/*
1423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1424% %
1425% %
1426% %
anthony31f1bf72012-01-30 12:37:22 +00001427+ 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 +00001428% %
1429% %
1430% %
1431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1432%
anthony31f1bf72012-01-30 12:37:22 +00001433% WandSimpleOperatorImages() applys one simple image operation given to all
1434% the images in the current wand, with the settings that are saved in the
1435% CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001436%
1437% It is assumed that any per-image settings are up-to-date with respect to
1438% extra settings that have been saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001439%
anthonyd1447672012-01-19 05:33:53 +00001440% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001441%
anthony31f1bf72012-01-30 12:37:22 +00001442% void WandSimpleOperatorImages(MagickWand *wand,
anthonyfd706f92012-01-19 04:22:02 +00001443% const MagickBooleanType plus_alt_op, const char *option,
1444% const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001445%
1446% A description of each parameter follows:
1447%
anthonydcf510d2011-10-30 13:51:40 +00001448% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00001449%
anthonyfd706f92012-01-19 04:22:02 +00001450% o plus_alt_op: request the 'plus' or alturnative form of the operation
anthony805a2d42011-09-25 08:25:12 +00001451%
anthonyfd706f92012-01-19 04:22:02 +00001452% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001453%
anthonyfd706f92012-01-19 04:22:02 +00001454% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001455%
anthony31f1bf72012-01-30 12:37:22 +00001456% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001457%
anthony31f1bf72012-01-30 12:37:22 +00001458% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001459%
anthony31f1bf72012-01-30 12:37:22 +00001460% WandSimpleOperatorImages(wand,MagickFalse,"crop","100x100+20+30",NULL);
1461% WandSimpleOperatorImages(wand,MagickTrue,"repage",NULL,NULL);
1462% WandSimpleOperatorImages(wand,MagickTrue,"distort","SRT","45");
1463% if ( wand->exception->severity != UndefinedException ) {
1464% CatchException(exception);
1465% exit(1);
1466% }
anthonyfd706f92012-01-19 04:22:02 +00001467%
1468% Or for handling command line arguments EG: +/-option ["arg"]
anthonydcf510d2011-10-30 13:51:40 +00001469%
1470% argc,argv
1471% i=index in argv
1472%
1473% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
1474% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthonyfd706f92012-01-19 04:22:02 +00001475% if ( flags == SimpleOperatorOptionFlag )
anthony31f1bf72012-01-30 12:37:22 +00001476% WandSimpleOperatorImages(wand,
anthonyfd706f92012-01-19 04:22:02 +00001477% (MagickBooleanType)(*argv[i])=='+'), argv[i]+1,
1478% count>=1 ? argv[i+1] : (char *)NULL,
1479% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001480% i += count+1;
1481%
anthony805a2d42011-09-25 08:25:12 +00001482*/
anthony31f1bf72012-01-30 12:37:22 +00001483
1484/*
1485 Internal subrountine to apply one simple image operation to the current
1486 image pointed to by the wand.
1487
1488 The image in the list may be modified in three different ways...
1489 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1490 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1491 * one image replace by a list of images (-separate and -crop only!)
1492
1493 In each case the result replaces the original image in the list, as well as
1494 the pointer to the modified image (last image added if replaced by a list
1495 of images) is returned.
1496
1497 As the image pointed to may be replaced, the first image in the list may
1498 also change. GetFirstImageInList() should be used by caller if they wish
1499 return the Image pointer to the first image in list.
1500*/
1501static void WandSimpleOperatorImage(MagickWand *wand,
anthonyfd706f92012-01-19 04:22:02 +00001502 const MagickBooleanType plus_alt_op, const char *option,
1503 const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001504{
1505 Image *
1506 new_image;
1507
anthony805a2d42011-09-25 08:25:12 +00001508 GeometryInfo
1509 geometry_info;
1510
1511 RectangleInfo
1512 geometry;
1513
1514 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001515 flags;
1516
anthonyfd706f92012-01-19 04:22:02 +00001517#define image_info (wand->image_info)
1518#define draw_info (wand->draw_info)
1519#define quantize_info (wand->quantize_info)
anthony31f1bf72012-01-30 12:37:22 +00001520#define image (wand->images)
1521#define exception (wand->exception)
1522#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001523
anthony805a2d42011-09-25 08:25:12 +00001524 assert(image_info != (const ImageInfo *) NULL);
1525 assert(image_info->signature == MagickSignature);
anthony31f1bf72012-01-30 12:37:22 +00001526 assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
1527 assert(image != (Image *) NULL); /* there is an image */
1528 assert(image->signature == MagickSignature); /* and is a valid image */
anthonydcf510d2011-10-30 13:51:40 +00001529
1530 if (wand->debug != MagickFalse)
1531 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1532
anthony805a2d42011-09-25 08:25:12 +00001533 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001534
anthonydcf510d2011-10-30 13:51:40 +00001535 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001536
anthonyfd706f92012-01-19 04:22:02 +00001537 /* FUTURE: We may need somthing a little more optimized than this!
1538 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1539 */
anthony31f1bf72012-01-30 12:37:22 +00001540 (void) SyncImageSettings(image_info,image,exception);
anthonydcf510d2011-10-30 13:51:40 +00001541
1542 switch (*option)
anthony805a2d42011-09-25 08:25:12 +00001543 {
1544 case 'a':
1545 {
anthonydcf510d2011-10-30 13:51:40 +00001546 if (LocaleCompare("adaptive-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001547 {
anthonyfd706f92012-01-19 04:22:02 +00001548 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001549 if ((flags & SigmaValue) == 0)
1550 geometry_info.sigma=1.0;
1551 if ((flags & XiValue) == 0)
1552 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001553 new_image=AdaptiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001554 geometry_info.sigma,geometry_info.xi,exception);
1555 break;
1556 }
anthonydcf510d2011-10-30 13:51:40 +00001557 if (LocaleCompare("adaptive-resize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001558 {
anthony31f1bf72012-01-30 12:37:22 +00001559 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
1560 new_image=AdaptiveResizeImage(image,geometry.width,geometry.height,
anthonyfd706f92012-01-19 04:22:02 +00001561 exception);
anthony805a2d42011-09-25 08:25:12 +00001562 break;
1563 }
anthonydcf510d2011-10-30 13:51:40 +00001564 if (LocaleCompare("adaptive-sharpen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001565 {
anthonyfd706f92012-01-19 04:22:02 +00001566 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001567 if ((flags & SigmaValue) == 0)
1568 geometry_info.sigma=1.0;
1569 if ((flags & XiValue) == 0)
1570 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001571 new_image=AdaptiveSharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001572 geometry_info.sigma,geometry_info.xi,exception);
1573 break;
1574 }
anthonydcf510d2011-10-30 13:51:40 +00001575 if (LocaleCompare("alpha",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001576 {
1577 AlphaChannelType
1578 alpha_type;
1579
anthony805a2d42011-09-25 08:25:12 +00001580 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
anthonyfd706f92012-01-19 04:22:02 +00001581 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00001582 (void) SetImageAlphaChannel(image,alpha_type,exception);
anthony805a2d42011-09-25 08:25:12 +00001583 break;
1584 }
anthonydcf510d2011-10-30 13:51:40 +00001585 if (LocaleCompare("annotate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001586 {
1587 char
1588 *text,
1589 geometry[MaxTextExtent];
1590
anthony805a2d42011-09-25 08:25:12 +00001591 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001592 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001593 if ((flags & SigmaValue) == 0)
1594 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00001595 text=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00001596 exception);
1597 if (text == (char *) NULL)
1598 break;
1599 (void) CloneString(&draw_info->text,text);
1600 text=DestroyString(text);
1601 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1602 geometry_info.xi,geometry_info.psi);
1603 (void) CloneString(&draw_info->geometry,geometry);
1604 draw_info->affine.sx=cos(DegreesToRadians(
1605 fmod(geometry_info.rho,360.0)));
1606 draw_info->affine.rx=sin(DegreesToRadians(
1607 fmod(geometry_info.rho,360.0)));
1608 draw_info->affine.ry=(-sin(DegreesToRadians(
1609 fmod(geometry_info.sigma,360.0))));
1610 draw_info->affine.sy=cos(DegreesToRadians(
1611 fmod(geometry_info.sigma,360.0)));
anthony31f1bf72012-01-30 12:37:22 +00001612 (void) AnnotateImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00001613 GetAffineMatrix(&draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001614 break;
1615 }
anthonydcf510d2011-10-30 13:51:40 +00001616 if (LocaleCompare("auto-gamma",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001617 {
anthony31f1bf72012-01-30 12:37:22 +00001618 (void) AutoGammaImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001619 break;
1620 }
anthonydcf510d2011-10-30 13:51:40 +00001621 if (LocaleCompare("auto-level",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001622 {
anthony31f1bf72012-01-30 12:37:22 +00001623 (void) AutoLevelImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001624 break;
1625 }
anthonydcf510d2011-10-30 13:51:40 +00001626 if (LocaleCompare("auto-orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001627 {
anthony31f1bf72012-01-30 12:37:22 +00001628 switch (image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001629 {
1630 case TopRightOrientation:
1631 {
anthony31f1bf72012-01-30 12:37:22 +00001632 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001633 break;
1634 }
1635 case BottomRightOrientation:
1636 {
anthony31f1bf72012-01-30 12:37:22 +00001637 new_image=RotateImage(image,180.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001638 break;
1639 }
1640 case BottomLeftOrientation:
1641 {
anthony31f1bf72012-01-30 12:37:22 +00001642 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001643 break;
1644 }
1645 case LeftTopOrientation:
1646 {
anthony31f1bf72012-01-30 12:37:22 +00001647 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001648 break;
1649 }
1650 case RightTopOrientation:
1651 {
anthony31f1bf72012-01-30 12:37:22 +00001652 new_image=RotateImage(image,90.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001653 break;
1654 }
1655 case RightBottomOrientation:
1656 {
anthony31f1bf72012-01-30 12:37:22 +00001657 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001658 break;
1659 }
1660 case LeftBottomOrientation:
1661 {
anthony31f1bf72012-01-30 12:37:22 +00001662 new_image=RotateImage(image,270.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001663 break;
1664 }
1665 default:
1666 break;
1667 }
1668 if (new_image != (Image *) NULL)
1669 new_image->orientation=TopLeftOrientation;
1670 break;
1671 }
1672 break;
1673 }
1674 case 'b':
1675 {
anthonydcf510d2011-10-30 13:51:40 +00001676 if (LocaleCompare("black-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001677 {
anthony31f1bf72012-01-30 12:37:22 +00001678 (void) BlackThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001679 break;
1680 }
anthonydcf510d2011-10-30 13:51:40 +00001681 if (LocaleCompare("blue-shift",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001682 {
anthony805a2d42011-09-25 08:25:12 +00001683 geometry_info.rho=1.5;
anthonyfd706f92012-01-19 04:22:02 +00001684 if (plus_alt_op == MagickFalse)
1685 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00001686 new_image=BlueShiftImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00001687 break;
1688 }
anthonydcf510d2011-10-30 13:51:40 +00001689 if (LocaleCompare("blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001690 {
anthony74b1cfc2011-10-06 12:44:16 +00001691 /* FUTURE: use of "bias" in a blur is non-sensible */
anthonyfd706f92012-01-19 04:22:02 +00001692 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001693 if ((flags & SigmaValue) == 0)
1694 geometry_info.sigma=1.0;
1695 if ((flags & XiValue) == 0)
1696 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001697 new_image=BlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001698 geometry_info.sigma,geometry_info.xi,exception);
1699 break;
1700 }
anthonydcf510d2011-10-30 13:51:40 +00001701 if (LocaleCompare("border",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001702 {
anthony31f1bf72012-01-30 12:37:22 +00001703 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001704 compose;
1705
1706 const char*
anthony5f867ae2011-10-09 10:28:34 +00001707 value;
1708
1709 value=GetImageOption(image_info,"compose");
1710 if (value != (const char *) NULL)
1711 compose=(CompositeOperator) ParseCommandOption(
1712 MagickComposeOptions,MagickFalse,value);
1713 else
1714 compose=OverCompositeOp; /* use Over not image->compose */
1715
anthony31f1bf72012-01-30 12:37:22 +00001716 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001717 if ((flags & SigmaValue) == 0)
1718 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00001719 new_image=BorderImage(image,&geometry,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00001720 break;
1721 }
anthonydcf510d2011-10-30 13:51:40 +00001722 if (LocaleCompare("brightness-contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001723 {
1724 double
1725 brightness,
1726 contrast;
1727
1728 GeometryInfo
1729 geometry_info;
1730
1731 MagickStatusType
1732 flags;
1733
anthonyfd706f92012-01-19 04:22:02 +00001734 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001735 brightness=geometry_info.rho;
1736 contrast=0.0;
1737 if ((flags & SigmaValue) != 0)
1738 contrast=geometry_info.sigma;
anthony31f1bf72012-01-30 12:37:22 +00001739 (void) BrightnessContrastImage(image,brightness,contrast,
anthony805a2d42011-09-25 08:25:12 +00001740 exception);
anthony805a2d42011-09-25 08:25:12 +00001741 break;
1742 }
1743 break;
1744 }
1745 case 'c':
1746 {
anthonydcf510d2011-10-30 13:51:40 +00001747 if (LocaleCompare("cdl",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001748 {
1749 char
1750 *color_correction_collection;
1751
1752 /*
1753 Color correct with a color decision list.
1754 */
anthonyfd706f92012-01-19 04:22:02 +00001755 color_correction_collection=FileToString(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00001756 if (color_correction_collection == (char *) NULL)
1757 break;
anthony31f1bf72012-01-30 12:37:22 +00001758 (void) ColorDecisionListImage(image,color_correction_collection,
anthony805a2d42011-09-25 08:25:12 +00001759 exception);
anthony805a2d42011-09-25 08:25:12 +00001760 break;
1761 }
anthonydcf510d2011-10-30 13:51:40 +00001762 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001763 {
anthonyfd706f92012-01-19 04:22:02 +00001764 /* The "channel" setting has already been set
anthonyd1447672012-01-19 05:33:53 +00001765 FUTURE: This probably should be part of WandSettingOptionInfo()
anthonyfd706f92012-01-19 04:22:02 +00001766 or SyncImageSettings().
1767 */
anthony31f1bf72012-01-30 12:37:22 +00001768 SetPixelChannelMapMask(image,image_info->channel);
anthony805a2d42011-09-25 08:25:12 +00001769 break;
1770 }
anthonydcf510d2011-10-30 13:51:40 +00001771 if (LocaleCompare("charcoal",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001772 {
anthonyfd706f92012-01-19 04:22:02 +00001773 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001774 if ((flags & SigmaValue) == 0)
1775 geometry_info.sigma=1.0;
1776 if ((flags & XiValue) == 0)
1777 geometry_info.xi=1.0;
anthony31f1bf72012-01-30 12:37:22 +00001778 new_image=CharcoalImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001779 geometry_info.sigma,geometry_info.xi,exception);
1780 break;
1781 }
anthonydcf510d2011-10-30 13:51:40 +00001782 if (LocaleCompare("chop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001783 {
anthony31f1bf72012-01-30 12:37:22 +00001784 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
1785 new_image=ChopImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001786 break;
1787 }
anthonydcf510d2011-10-30 13:51:40 +00001788 if (LocaleCompare("clamp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001789 {
anthony31f1bf72012-01-30 12:37:22 +00001790 (void) ClampImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001791 break;
1792 }
anthonydcf510d2011-10-30 13:51:40 +00001793 if (LocaleCompare("clip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001794 {
anthonyfd706f92012-01-19 04:22:02 +00001795 if (plus_alt_op == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001796 (void) ClipImage(image,exception);
anthonyfd706f92012-01-19 04:22:02 +00001797 else /* "+clip" remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001798 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001799 break;
1800 }
anthonydcf510d2011-10-30 13:51:40 +00001801 if (LocaleCompare("clip-mask",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001802 {
1803 CacheView
1804 *mask_view;
1805
1806 Image
1807 *mask_image;
1808
1809 register Quantum
1810 *restrict q;
1811
1812 register ssize_t
1813 x;
1814
1815 ssize_t
1816 y;
1817
anthonyfd706f92012-01-19 04:22:02 +00001818 if (plus_alt_op != MagickFalse)
1819 { /* "+clip-mask" Remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001820 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001821 break;
1822 }
anthonyfd706f92012-01-19 04:22:02 +00001823 mask_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001824 if (mask_image == (Image *) NULL)
1825 break;
anthonyfd706f92012-01-19 04:22:02 +00001826 if (SetImageStorageClass(mask_image,DirectClass,exception)
1827 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001828 break;
1829 /* Create a write mask from clip-mask image */
anthonyfd706f92012-01-19 04:22:02 +00001830 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001831 mask_view=AcquireCacheView(mask_image);
1832 for (y=0; y < (ssize_t) mask_image->rows; y++)
1833 {
1834 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1835 exception);
1836 if (q == (Quantum *) NULL)
1837 break;
1838 for (x=0; x < (ssize_t) mask_image->columns; x++)
1839 {
1840 if (mask_image->matte == MagickFalse)
1841 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1842 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1843 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1844 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1845 q+=GetPixelChannels(mask_image);
1846 }
1847 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1848 break;
1849 }
anthonyfd706f92012-01-19 04:22:02 +00001850 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001851 mask_view=DestroyCacheView(mask_view);
1852 mask_image->matte=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00001853 (void) SetImageMask(image,mask_image,exception);
anthony805a2d42011-09-25 08:25:12 +00001854 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001855 break;
1856 }
anthonydcf510d2011-10-30 13:51:40 +00001857 if (LocaleCompare("clip-path",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001858 {
anthony31f1bf72012-01-30 12:37:22 +00001859 (void) ClipImagePath(image,arg1,
anthonyfd706f92012-01-19 04:22:02 +00001860 (MagickBooleanType)(!(int)plus_alt_op),exception);
anthony805a2d42011-09-25 08:25:12 +00001861 break;
1862 }
anthonydcf510d2011-10-30 13:51:40 +00001863 if (LocaleCompare("colorize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001864 {
anthony31f1bf72012-01-30 12:37:22 +00001865 new_image=ColorizeImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00001866 break;
1867 }
anthonydcf510d2011-10-30 13:51:40 +00001868 if (LocaleCompare("color-matrix",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001869 {
1870 KernelInfo
1871 *kernel;
1872
anthonyfd706f92012-01-19 04:22:02 +00001873 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001874 if (kernel == (KernelInfo *) NULL)
1875 break;
anthony31f1bf72012-01-30 12:37:22 +00001876 new_image=ColorMatrixImage(image,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00001877 kernel=DestroyKernelInfo(kernel);
1878 break;
1879 }
anthonydcf510d2011-10-30 13:51:40 +00001880 if (LocaleCompare("colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001881 {
anthonyfd706f92012-01-19 04:22:02 +00001882 /* Reduce the number of colors in the image.
1883 FUTURE: also provide 'plus version with image 'color counts'
1884 */
1885 quantize_info->number_colors=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00001886 if (quantize_info->number_colors == 0)
1887 break;
anthony31f1bf72012-01-30 12:37:22 +00001888 if ((image->storage_class == DirectClass) ||
1889 image->colors > quantize_info->number_colors)
1890 (void) QuantizeImage(quantize_info,image,exception);
anthony805a2d42011-09-25 08:25:12 +00001891 else
anthony31f1bf72012-01-30 12:37:22 +00001892 (void) CompressImageColormap(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001893 break;
1894 }
anthonydcf510d2011-10-30 13:51:40 +00001895 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001896 {
anthony31f1bf72012-01-30 12:37:22 +00001897 /* WARNING: this is both a image_info setting (already done)
1898 and a operator to change image colorspace.
1899
1900 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00001901 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00001902
anthonyd2cdc862011-10-07 14:07:17 +00001903 Note that +colorspace sets "undefined" or no effect on
1904 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00001905 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00001906 */
anthony31f1bf72012-01-30 12:37:22 +00001907 (void) TransformImageColorspace(image,
1908 plus_alt_op ? RGBColorspace : image_info->colorspace,
anthony6613bf32011-10-15 07:24:44 +00001909 exception);
anthony805a2d42011-09-25 08:25:12 +00001910 break;
1911 }
anthonydcf510d2011-10-30 13:51:40 +00001912 if (LocaleCompare("contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001913 {
anthony31f1bf72012-01-30 12:37:22 +00001914 (void) ContrastImage(image,
anthonyfd706f92012-01-19 04:22:02 +00001915 (MagickBooleanType)(!(int)plus_alt_op),exception);
anthony805a2d42011-09-25 08:25:12 +00001916 break;
1917 }
anthonydcf510d2011-10-30 13:51:40 +00001918 if (LocaleCompare("contrast-stretch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001919 {
1920 double
1921 black_point,
1922 white_point;
1923
1924 MagickStatusType
1925 flags;
1926
anthonyfd706f92012-01-19 04:22:02 +00001927 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001928 black_point=geometry_info.rho;
1929 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
1930 black_point;
1931 if ((flags & PercentValue) != 0)
1932 {
anthony31f1bf72012-01-30 12:37:22 +00001933 black_point*=(double) image->columns*image->rows/100.0;
1934 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00001935 }
anthony31f1bf72012-01-30 12:37:22 +00001936 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00001937 white_point;
anthony31f1bf72012-01-30 12:37:22 +00001938 (void) ContrastStretchImage(image,black_point,white_point,
anthony805a2d42011-09-25 08:25:12 +00001939 exception);
anthony805a2d42011-09-25 08:25:12 +00001940 break;
1941 }
anthonydcf510d2011-10-30 13:51:40 +00001942 if (LocaleCompare("convolve",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001943 {
1944 KernelInfo
1945 *kernel_info;
1946
anthonyfd706f92012-01-19 04:22:02 +00001947 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001948 if (kernel_info == (KernelInfo *) NULL)
1949 break;
anthony31f1bf72012-01-30 12:37:22 +00001950 kernel_info->bias=image->bias;
1951 new_image=ConvolveImage(image,kernel_info,exception);
anthony805a2d42011-09-25 08:25:12 +00001952 kernel_info=DestroyKernelInfo(kernel_info);
1953 break;
1954 }
anthonydcf510d2011-10-30 13:51:40 +00001955 if (LocaleCompare("crop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001956 {
anthony31f1bf72012-01-30 12:37:22 +00001957 /* WARNING: This can generate multiple images! */
1958 new_image=CropImageToTiles(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001959 break;
1960 }
anthonydcf510d2011-10-30 13:51:40 +00001961 if (LocaleCompare("cycle",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001962 {
anthony31f1bf72012-01-30 12:37:22 +00001963 (void) CycleColormapImage(image,(ssize_t) StringToLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00001964 exception);
1965 break;
1966 }
1967 break;
1968 }
1969 case 'd':
1970 {
anthonydcf510d2011-10-30 13:51:40 +00001971 if (LocaleCompare("decipher",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001972 {
1973 StringInfo
1974 *passkey;
1975
anthonyfd706f92012-01-19 04:22:02 +00001976 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00001977 if (passkey != (StringInfo *) NULL)
1978 {
anthony31f1bf72012-01-30 12:37:22 +00001979 (void) PasskeyDecipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00001980 passkey=DestroyStringInfo(passkey);
1981 }
1982 break;
1983 }
anthonydcf510d2011-10-30 13:51:40 +00001984 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001985 {
anthonydcf510d2011-10-30 13:51:40 +00001986 /* The image_info->depth setting has already been set
1987 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00001988
anthonydcf510d2011-10-30 13:51:40 +00001989 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
1990 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00001991
anthonyfd706f92012-01-19 04:22:02 +00001992 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00001993 */
anthony31f1bf72012-01-30 12:37:22 +00001994 (void) SetImageDepth(image,image_info->depth,exception);
anthony805a2d42011-09-25 08:25:12 +00001995 break;
1996 }
anthonydcf510d2011-10-30 13:51:40 +00001997 if (LocaleCompare("deskew",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001998 {
1999 double
2000 threshold;
2001
anthonyfd706f92012-01-19 04:22:02 +00002002 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002003 threshold=40.0*QuantumRange/100.0;
2004 else
anthonyfd706f92012-01-19 04:22:02 +00002005 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002006 new_image=DeskewImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002007 break;
2008 }
anthonydcf510d2011-10-30 13:51:40 +00002009 if (LocaleCompare("despeckle",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002010 {
anthony31f1bf72012-01-30 12:37:22 +00002011 new_image=DespeckleImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002012 break;
2013 }
anthonydcf510d2011-10-30 13:51:40 +00002014 if (LocaleCompare("distort",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002015 {
2016 char
2017 *args,
2018 token[MaxTextExtent];
2019
2020 const char
2021 *p;
2022
2023 DistortImageMethod
2024 method;
2025
2026 double
2027 *arguments;
2028
2029 register ssize_t
2030 x;
2031
2032 size_t
2033 number_arguments;
2034
anthony805a2d42011-09-25 08:25:12 +00002035 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002036 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002037 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002038 {
anthony80c37752012-01-16 01:03:11 +00002039 double
2040 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002041 /* Special Case - Argument is actually a resize geometry!
2042 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002043 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002044 */
anthony31f1bf72012-01-30 12:37:22 +00002045 (void) ParseRegionGeometry(image,arg2,&geometry,
anthony80c37752012-01-16 01:03:11 +00002046 exception);
2047 resize_args[0]=(double) geometry.width;
2048 resize_args[1]=(double) geometry.height;
anthony31f1bf72012-01-30 12:37:22 +00002049 new_image=DistortImage(image,method,(size_t)2,
anthony80c37752012-01-16 01:03:11 +00002050 resize_args,MagickTrue,exception);
anthony805a2d42011-09-25 08:25:12 +00002051 break;
2052 }
anthonyfd706f92012-01-19 04:22:02 +00002053 /* handle percent arguments */
anthony31f1bf72012-01-30 12:37:22 +00002054 args=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002055 exception);
2056 if (args == (char *) NULL)
2057 break;
anthonyfd706f92012-01-19 04:22:02 +00002058 /* convert arguments into an array of doubles
2059 FUTURE: make this a separate function.
2060 Also make use of new 'sentinal' feature to avoid need for
2061 tokenization.
2062 */
anthony805a2d42011-09-25 08:25:12 +00002063 p=(char *) args;
2064 for (x=0; *p != '\0'; x++)
2065 {
2066 GetMagickToken(p,&p,token);
2067 if (*token == ',')
2068 GetMagickToken(p,&p,token);
2069 }
2070 number_arguments=(size_t) x;
2071 arguments=(double *) AcquireQuantumMemory(number_arguments,
2072 sizeof(*arguments));
2073 if (arguments == (double *) NULL)
2074 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002075 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002076 (void) ResetMagickMemory(arguments,0,number_arguments*
2077 sizeof(*arguments));
2078 p=(char *) args;
2079 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2080 {
2081 GetMagickToken(p,&p,token);
2082 if (*token == ',')
2083 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002084 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002085 }
2086 args=DestroyString(args);
anthony31f1bf72012-01-30 12:37:22 +00002087 new_image=DistortImage(image,method,number_arguments,arguments,
anthonyfd706f92012-01-19 04:22:02 +00002088 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002089 arguments=(double *) RelinquishMagickMemory(arguments);
2090 break;
2091 }
anthonydcf510d2011-10-30 13:51:40 +00002092 if (LocaleCompare("draw",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002093 {
anthonyfd706f92012-01-19 04:22:02 +00002094 (void) CloneString(&draw_info->primitive,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002095 (void) DrawImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00002096 (void) CloneString(&draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002097 break;
2098 }
2099 break;
2100 }
2101 case 'e':
2102 {
anthonydcf510d2011-10-30 13:51:40 +00002103 if (LocaleCompare("edge",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002104 {
anthonyfd706f92012-01-19 04:22:02 +00002105 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002106 if ((flags & SigmaValue) == 0)
2107 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002108 new_image=EdgeImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002109 geometry_info.sigma,exception);
2110 break;
2111 }
anthonydcf510d2011-10-30 13:51:40 +00002112 if (LocaleCompare("emboss",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002113 {
anthonyfd706f92012-01-19 04:22:02 +00002114 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002115 if ((flags & SigmaValue) == 0)
2116 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002117 new_image=EmbossImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002118 geometry_info.sigma,exception);
2119 break;
2120 }
anthonydcf510d2011-10-30 13:51:40 +00002121 if (LocaleCompare("encipher",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002122 {
2123 StringInfo
2124 *passkey;
2125
anthonyfd706f92012-01-19 04:22:02 +00002126 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002127 if (passkey != (StringInfo *) NULL)
2128 {
anthony31f1bf72012-01-30 12:37:22 +00002129 (void) PasskeyEncipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002130 passkey=DestroyStringInfo(passkey);
2131 }
2132 break;
2133 }
anthonydcf510d2011-10-30 13:51:40 +00002134 if (LocaleCompare("enhance",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002135 {
anthony31f1bf72012-01-30 12:37:22 +00002136 new_image=EnhanceImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002137 break;
2138 }
anthonydcf510d2011-10-30 13:51:40 +00002139 if (LocaleCompare("equalize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002140 {
anthony31f1bf72012-01-30 12:37:22 +00002141 (void) EqualizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002142 break;
2143 }
anthonydcf510d2011-10-30 13:51:40 +00002144 if (LocaleCompare("evaluate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002145 {
2146 double
2147 constant;
2148
2149 MagickEvaluateOperator
2150 op;
2151
anthony805a2d42011-09-25 08:25:12 +00002152 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002153 MagickEvaluateOptions,MagickFalse,arg1);
2154 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002155 (void) EvaluateImage(image,op,constant,exception);
anthony805a2d42011-09-25 08:25:12 +00002156 break;
2157 }
anthonydcf510d2011-10-30 13:51:40 +00002158 if (LocaleCompare("extent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002159 {
anthony31f1bf72012-01-30 12:37:22 +00002160 flags=ParseGravityGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002161 if (geometry.width == 0)
anthony31f1bf72012-01-30 12:37:22 +00002162 geometry.width=image->columns;
anthony805a2d42011-09-25 08:25:12 +00002163 if (geometry.height == 0)
anthony31f1bf72012-01-30 12:37:22 +00002164 geometry.height=image->rows;
2165 new_image=ExtentImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002166 break;
2167 }
2168 break;
2169 }
2170 case 'f':
2171 {
anthonydcf510d2011-10-30 13:51:40 +00002172 if (LocaleCompare("features",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002173 {
anthony31f1bf72012-01-30 12:37:22 +00002174 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2175 if (plus_alt_op != MagickFalse)
2176 {
2177 (void) DeleteImageArtifact(image,"identify:features");
2178 break;
2179 }
2180 (void) SetImageArtifact(image,"identify:features","true");
2181 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002182 break;
2183 }
anthonydcf510d2011-10-30 13:51:40 +00002184 if (LocaleCompare("flip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002185 {
anthony31f1bf72012-01-30 12:37:22 +00002186 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002187 break;
2188 }
anthonydcf510d2011-10-30 13:51:40 +00002189 if (LocaleCompare("flop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002190 {
anthony31f1bf72012-01-30 12:37:22 +00002191 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002192 break;
2193 }
anthonydcf510d2011-10-30 13:51:40 +00002194 if (LocaleCompare("floodfill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002195 {
2196 PixelInfo
2197 target;
2198
anthony31f1bf72012-01-30 12:37:22 +00002199 (void) ParsePageGeometry(image,arg1,&geometry,exception);
anthonyfd706f92012-01-19 04:22:02 +00002200 (void) QueryColorCompliance(arg2,AllCompliance,&target,exception);
anthony31f1bf72012-01-30 12:37:22 +00002201 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
anthonyfd706f92012-01-19 04:22:02 +00002202 geometry.y,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002203 break;
2204 }
anthonydcf510d2011-10-30 13:51:40 +00002205 if (LocaleCompare("frame",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002206 {
2207 FrameInfo
2208 frame_info;
2209
anthony31f1bf72012-01-30 12:37:22 +00002210 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002211 compose;
2212
2213 const char*
2214 value;
2215
2216 value=GetImageOption(image_info,"compose");
2217 if (value != (const char *) NULL)
2218 compose=(CompositeOperator) ParseCommandOption(
2219 MagickComposeOptions,MagickFalse,value);
2220 else
2221 compose=OverCompositeOp; /* use Over not image->compose */
2222
anthony31f1bf72012-01-30 12:37:22 +00002223 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002224 frame_info.width=geometry.width;
2225 frame_info.height=geometry.height;
2226 if ((flags & HeightValue) == 0)
2227 frame_info.height=geometry.width;
2228 frame_info.outer_bevel=geometry.x;
2229 frame_info.inner_bevel=geometry.y;
2230 frame_info.x=(ssize_t) frame_info.width;
2231 frame_info.y=(ssize_t) frame_info.height;
anthony31f1bf72012-01-30 12:37:22 +00002232 frame_info.width=image->columns+2*frame_info.width;
2233 frame_info.height=image->rows+2*frame_info.height;
2234 new_image=FrameImage(image,&frame_info,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00002235 break;
2236 }
anthonydcf510d2011-10-30 13:51:40 +00002237 if (LocaleCompare("function",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002238 {
2239 char
2240 *arguments,
2241 token[MaxTextExtent];
2242
2243 const char
2244 *p;
2245
2246 double
2247 *parameters;
2248
2249 MagickFunction
2250 function;
2251
2252 register ssize_t
2253 x;
2254
2255 size_t
2256 number_parameters;
2257
cristy947cb4c2011-10-20 18:41:46 +00002258 /*
2259 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002260 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002261 */
anthony805a2d42011-09-25 08:25:12 +00002262 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002263 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002264 arguments=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002265 exception);
2266 if (arguments == (char *) NULL)
2267 break;
2268 p=(char *) arguments;
2269 for (x=0; *p != '\0'; x++)
2270 {
2271 GetMagickToken(p,&p,token);
2272 if (*token == ',')
2273 GetMagickToken(p,&p,token);
2274 }
2275 number_parameters=(size_t) x;
2276 parameters=(double *) AcquireQuantumMemory(number_parameters,
2277 sizeof(*parameters));
2278 if (parameters == (double *) NULL)
2279 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002280 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002281 (void) ResetMagickMemory(parameters,0,number_parameters*
2282 sizeof(*parameters));
2283 p=(char *) arguments;
2284 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2285 {
2286 GetMagickToken(p,&p,token);
2287 if (*token == ',')
2288 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002289 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002290 }
2291 arguments=DestroyString(arguments);
anthony31f1bf72012-01-30 12:37:22 +00002292 (void) FunctionImage(image,function,number_parameters,parameters,
anthony805a2d42011-09-25 08:25:12 +00002293 exception);
2294 parameters=(double *) RelinquishMagickMemory(parameters);
2295 break;
2296 }
2297 break;
2298 }
2299 case 'g':
2300 {
anthonydcf510d2011-10-30 13:51:40 +00002301 if (LocaleCompare("gamma",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002302 {
anthony31f1bf72012-01-30 12:37:22 +00002303 if (plus_alt_op != MagickFalse)
2304 image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002305 else
anthony31f1bf72012-01-30 12:37:22 +00002306 (void) GammaImage(image,StringToDouble(arg1,(char **) NULL),
anthonyfd706f92012-01-19 04:22:02 +00002307 exception);
anthony805a2d42011-09-25 08:25:12 +00002308 break;
2309 }
anthonydcf510d2011-10-30 13:51:40 +00002310 if ((LocaleCompare("gaussian-blur",option) == 0) ||
2311 (LocaleCompare("gaussian",option) == 0))
anthony805a2d42011-09-25 08:25:12 +00002312 {
anthonyfd706f92012-01-19 04:22:02 +00002313 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002314 if ((flags & SigmaValue) == 0)
2315 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002316 new_image=GaussianBlurImage(image,geometry_info.rho,
cristyd89705a2012-01-20 02:52:24 +00002317 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002318 break;
2319 }
anthonydcf510d2011-10-30 13:51:40 +00002320 if (LocaleCompare("geometry",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002321 {
anthonyfd706f92012-01-19 04:22:02 +00002322 /*
anthony31f1bf72012-01-30 12:37:22 +00002323 Record Image offset for composition. (A Setting)
2324 Resize last image. (ListOperator)
2325 FUTURE: Why if no 'offset' does this resize ALL images?
2326 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002327 */
anthony31f1bf72012-01-30 12:37:22 +00002328 if (plus_alt_op != MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00002329 { /* remove the previous composition geometry offset! */
anthony31f1bf72012-01-30 12:37:22 +00002330 if (image->geometry != (char *) NULL)
2331 image->geometry=DestroyString(image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002332 break;
2333 }
anthony31f1bf72012-01-30 12:37:22 +00002334 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002335 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony31f1bf72012-01-30 12:37:22 +00002336 (void) CloneString(&image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002337 else
anthony31f1bf72012-01-30 12:37:22 +00002338 new_image=ResizeImage(image,geometry.width,geometry.height,
2339 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002340 break;
2341 }
anthony805a2d42011-09-25 08:25:12 +00002342 break;
2343 }
2344 case 'h':
2345 {
anthonydcf510d2011-10-30 13:51:40 +00002346 if (LocaleCompare("highlight-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002347 {
anthony31f1bf72012-01-30 12:37:22 +00002348 (void) SetImageArtifact(image,option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002349 break;
2350 }
2351 break;
2352 }
2353 case 'i':
2354 {
anthonydcf510d2011-10-30 13:51:40 +00002355 if (LocaleCompare("identify",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002356 {
anthony31f1bf72012-01-30 12:37:22 +00002357 const char
2358 *format,
anthony805a2d42011-09-25 08:25:12 +00002359 *text;
2360
anthony31f1bf72012-01-30 12:37:22 +00002361 format=GetImageOption(image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002362 if (format == (char *) NULL)
2363 {
anthony31f1bf72012-01-30 12:37:22 +00002364 (void) IdentifyImage(image,stdout,image_info->verbose,
anthony805a2d42011-09-25 08:25:12 +00002365 exception);
2366 break;
2367 }
anthony31f1bf72012-01-30 12:37:22 +00002368 text=InterpretImageProperties(image_info,image,format,exception);
anthony805a2d42011-09-25 08:25:12 +00002369 if (text == (char *) NULL)
2370 break;
2371 (void) fputs(text,stdout);
2372 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002373 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002374 break;
2375 }
anthonydcf510d2011-10-30 13:51:40 +00002376 if (LocaleCompare("implode",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002377 {
anthonyfd706f92012-01-19 04:22:02 +00002378 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002379 new_image=ImplodeImage(image,geometry_info.rho,
2380 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002381 break;
2382 }
anthonyfd706f92012-01-19 04:22:02 +00002383 if (LocaleCompare("interpolative-resize",option) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002384 {
anthony31f1bf72012-01-30 12:37:22 +00002385 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2386 new_image=InterpolativeResizeImage(image,geometry.width,
2387 geometry.height,image->interpolate,exception);
cristy947cb4c2011-10-20 18:41:46 +00002388 break;
2389 }
anthony805a2d42011-09-25 08:25:12 +00002390 break;
2391 }
2392 case 'l':
2393 {
anthonydcf510d2011-10-30 13:51:40 +00002394 if (LocaleCompare("lat",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002395 {
anthonyfd706f92012-01-19 04:22:02 +00002396 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002397 if ((flags & PercentValue) != 0)
2398 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002399 new_image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
2400 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2401 exception);
anthony805a2d42011-09-25 08:25:12 +00002402 break;
2403 }
anthonydcf510d2011-10-30 13:51:40 +00002404 if (LocaleCompare("level",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002405 {
2406 MagickRealType
2407 black_point,
2408 gamma,
2409 white_point;
2410
2411 MagickStatusType
2412 flags;
2413
anthonyfd706f92012-01-19 04:22:02 +00002414 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002415 black_point=geometry_info.rho;
2416 white_point=(MagickRealType) QuantumRange;
2417 if ((flags & SigmaValue) != 0)
2418 white_point=geometry_info.sigma;
2419 gamma=1.0;
2420 if ((flags & XiValue) != 0)
2421 gamma=geometry_info.xi;
2422 if ((flags & PercentValue) != 0)
2423 {
2424 black_point*=(MagickRealType) (QuantumRange/100.0);
2425 white_point*=(MagickRealType) (QuantumRange/100.0);
2426 }
2427 if ((flags & SigmaValue) == 0)
2428 white_point=(MagickRealType) QuantumRange-black_point;
anthony31f1bf72012-01-30 12:37:22 +00002429 if (plus_alt_op || ((flags & AspectValue) != 0))
2430 (void) LevelizeImage(image,black_point,white_point,gamma,
anthony805a2d42011-09-25 08:25:12 +00002431 exception);
2432 else
anthony31f1bf72012-01-30 12:37:22 +00002433 (void) LevelImage(image,black_point,white_point,gamma,
anthony805a2d42011-09-25 08:25:12 +00002434 exception);
anthony805a2d42011-09-25 08:25:12 +00002435 break;
2436 }
anthonydcf510d2011-10-30 13:51:40 +00002437 if (LocaleCompare("level-colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002438 {
2439 char
2440 token[MaxTextExtent];
2441
2442 const char
2443 *p;
2444
2445 PixelInfo
2446 black_point,
2447 white_point;
2448
anthonyfd706f92012-01-19 04:22:02 +00002449 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002450 GetMagickToken(p,&p,token); /* get black point color */
2451 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002452 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002453 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002454 else
cristy269c9412011-10-13 23:41:15 +00002455 (void) QueryColorCompliance("#000000",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002456 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002457 if (isalpha((int) token[0]) || (token[0] == '#'))
2458 GetMagickToken(p,&p,token);
2459 if (*token == '\0')
2460 white_point=black_point; /* set everything to that color */
2461 else
2462 {
2463 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2464 GetMagickToken(p,&p,token); /* Get white point color. */
2465 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002466 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002467 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002468 else
cristy269c9412011-10-13 23:41:15 +00002469 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002470 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002471 }
anthony31f1bf72012-01-30 12:37:22 +00002472 (void) LevelImageColors(image,&black_point,&white_point,
2473 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002474 break;
2475 }
anthonydcf510d2011-10-30 13:51:40 +00002476 if (LocaleCompare("linear-stretch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002477 {
2478 double
2479 black_point,
2480 white_point;
2481
2482 MagickStatusType
2483 flags;
2484
anthonyfd706f92012-01-19 04:22:02 +00002485 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002486 black_point=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002487 white_point=(MagickRealType) image->columns*image->rows;
anthony805a2d42011-09-25 08:25:12 +00002488 if ((flags & SigmaValue) != 0)
2489 white_point=geometry_info.sigma;
2490 if ((flags & PercentValue) != 0)
2491 {
anthony31f1bf72012-01-30 12:37:22 +00002492 black_point*=(double) image->columns*image->rows/100.0;
2493 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002494 }
2495 if ((flags & SigmaValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00002496 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002497 black_point;
anthony31f1bf72012-01-30 12:37:22 +00002498 (void) LinearStretchImage(image,black_point,white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002499 break;
2500 }
anthonydcf510d2011-10-30 13:51:40 +00002501 if (LocaleCompare("liquid-rescale",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002502 {
anthony31f1bf72012-01-30 12:37:22 +00002503 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002504 if ((flags & XValue) == 0)
2505 geometry.x=1;
2506 if ((flags & YValue) == 0)
2507 geometry.y=0;
anthony31f1bf72012-01-30 12:37:22 +00002508 new_image=LiquidRescaleImage(image,geometry.width,
anthony805a2d42011-09-25 08:25:12 +00002509 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2510 break;
2511 }
anthonydcf510d2011-10-30 13:51:40 +00002512 if (LocaleCompare("lowlight-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002513 {
anthony31f1bf72012-01-30 12:37:22 +00002514 (void) SetImageArtifact(image,option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002515 break;
2516 }
2517 break;
2518 }
2519 case 'm':
2520 {
anthonydcf510d2011-10-30 13:51:40 +00002521 if (LocaleCompare("map",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002522 {
2523 Image
2524 *remap_image;
2525
anthony31f1bf72012-01-30 12:37:22 +00002526 /* DEPRECIATED use -remap */
anthonyfd706f92012-01-19 04:22:02 +00002527 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002528 if (remap_image == (Image *) NULL)
2529 break;
anthony31f1bf72012-01-30 12:37:22 +00002530 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002531 remap_image=DestroyImage(remap_image);
2532 break;
2533 }
anthonydcf510d2011-10-30 13:51:40 +00002534 if (LocaleCompare("mask",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002535 {
2536 Image
2537 *mask;
2538
anthony31f1bf72012-01-30 12:37:22 +00002539 if (plus_alt_op != MagickFalse)
2540 { /* Remove a mask. */
2541 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002542 break;
2543 }
anthony31f1bf72012-01-30 12:37:22 +00002544 /* Set the image mask. */
anthonyfd706f92012-01-19 04:22:02 +00002545 mask=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002546 if (mask == (Image *) NULL)
2547 break;
anthony31f1bf72012-01-30 12:37:22 +00002548 (void) SetImageMask(image,mask,exception);
anthony805a2d42011-09-25 08:25:12 +00002549 mask=DestroyImage(mask);
2550 break;
2551 }
anthonydcf510d2011-10-30 13:51:40 +00002552 if (LocaleCompare("matte",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002553 {
anthony31f1bf72012-01-30 12:37:22 +00002554 /* DEPRECIATED */
2555 (void) SetImageAlphaChannel(image,plus_alt_op ?
2556 DeactivateAlphaChannel:SetAlphaChannel ,exception);
anthony805a2d42011-09-25 08:25:12 +00002557 break;
2558 }
anthonydcf510d2011-10-30 13:51:40 +00002559 if (LocaleCompare("mode",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002560 {
anthonyfd706f92012-01-19 04:22:02 +00002561 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002562 if ((flags & SigmaValue) == 0)
2563 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002564 new_image=StatisticImage(image,ModeStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002565 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2566 break;
2567 }
anthonydcf510d2011-10-30 13:51:40 +00002568 if (LocaleCompare("modulate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002569 {
anthony31f1bf72012-01-30 12:37:22 +00002570 (void) ModulateImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002571 break;
2572 }
anthonydcf510d2011-10-30 13:51:40 +00002573 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002574 {
anthony31f1bf72012-01-30 12:37:22 +00002575 (void) SetImageProgressMonitor(image, plus_alt_op?
2576 (MagickProgressMonitor) NULL:MonitorProgress,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002577 break;
2578 }
anthonydcf510d2011-10-30 13:51:40 +00002579 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002580 {
anthony31f1bf72012-01-30 12:37:22 +00002581 (void) SetImageType(image,BilevelType,exception);
anthony805a2d42011-09-25 08:25:12 +00002582 break;
2583 }
anthonydcf510d2011-10-30 13:51:40 +00002584 if (LocaleCompare("morphology",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002585 {
2586 char
2587 token[MaxTextExtent];
2588
2589 const char
2590 *p;
2591
2592 KernelInfo
2593 *kernel;
2594
2595 MorphologyMethod
2596 method;
2597
2598 ssize_t
2599 iterations;
2600
anthonyfd706f92012-01-19 04:22:02 +00002601 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002602 GetMagickToken(p,&p,token);
2603 method=(MorphologyMethod) ParseCommandOption(
2604 MagickMorphologyOptions,MagickFalse,token);
2605 iterations=1L;
2606 GetMagickToken(p,&p,token);
2607 if ((*p == ':') || (*p == ','))
2608 GetMagickToken(p,&p,token);
2609 if ((*p != '\0'))
2610 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002611 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002612 if (kernel == (KernelInfo *) NULL)
2613 {
2614 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002615 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002616 break;
2617 }
anthony31f1bf72012-01-30 12:37:22 +00002618 new_image=MorphologyImage(image,method,iterations,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00002619 kernel=DestroyKernelInfo(kernel);
2620 break;
2621 }
anthonydcf510d2011-10-30 13:51:40 +00002622 if (LocaleCompare("motion-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002623 {
anthonyfd706f92012-01-19 04:22:02 +00002624 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002625 if ((flags & SigmaValue) == 0)
2626 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002627 new_image=MotionBlurImage(image,geometry_info.rho,
2628 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2629 exception);
anthony805a2d42011-09-25 08:25:12 +00002630 break;
2631 }
2632 break;
2633 }
2634 case 'n':
2635 {
anthonydcf510d2011-10-30 13:51:40 +00002636 if (LocaleCompare("negate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002637 {
anthony31f1bf72012-01-30 12:37:22 +00002638 (void) NegateImage(image, plus_alt_op, exception);
anthony805a2d42011-09-25 08:25:12 +00002639 break;
2640 }
anthonydcf510d2011-10-30 13:51:40 +00002641 if (LocaleCompare("noise",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002642 {
anthony31f1bf72012-01-30 12:37:22 +00002643 if (plus_alt_op == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002644 {
anthonyfd706f92012-01-19 04:22:02 +00002645 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002646 if ((flags & SigmaValue) == 0)
2647 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002648 new_image=StatisticImage(image,NonpeakStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002649 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2650 }
2651 else
2652 {
2653 NoiseType
2654 noise;
2655
anthony31f1bf72012-01-30 12:37:22 +00002656 double
2657 attenuate;
2658
2659 const char*
2660 value;
2661
anthony805a2d42011-09-25 08:25:12 +00002662 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002663 MagickFalse,arg1),
2664
2665 value=GetImageOption(image_info,"attenuate");
2666 if (value != (const char *) NULL)
2667 attenuate=StringToDouble(value,(char **) NULL);
2668 else
2669 attenuate=1.0;
2670
2671 new_image=AddNoiseImage(image,noise,attenuate,exception);
anthony805a2d42011-09-25 08:25:12 +00002672 }
2673 break;
2674 }
anthonydcf510d2011-10-30 13:51:40 +00002675 if (LocaleCompare("normalize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002676 {
anthony31f1bf72012-01-30 12:37:22 +00002677 (void) NormalizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002678 break;
2679 }
2680 break;
2681 }
2682 case 'o':
2683 {
anthonydcf510d2011-10-30 13:51:40 +00002684 if (LocaleCompare("opaque",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002685 {
2686 PixelInfo
2687 target;
2688
anthony31f1bf72012-01-30 12:37:22 +00002689 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
2690 (void) OpaquePaintImage(image,&target,&draw_info->fill,plus_alt_op,
2691 exception);
anthony805a2d42011-09-25 08:25:12 +00002692 break;
2693 }
anthonydcf510d2011-10-30 13:51:40 +00002694 if (LocaleCompare("ordered-dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002695 {
anthony31f1bf72012-01-30 12:37:22 +00002696 (void) OrderedPosterizeImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002697 break;
2698 }
2699 break;
2700 }
2701 case 'p':
2702 {
anthonydcf510d2011-10-30 13:51:40 +00002703 if (LocaleCompare("paint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002704 {
anthonyfd706f92012-01-19 04:22:02 +00002705 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002706 new_image=OilPaintImage(image,geometry_info.rho,geometry_info.sigma,
2707 exception);
anthony805a2d42011-09-25 08:25:12 +00002708 break;
2709 }
anthonydcf510d2011-10-30 13:51:40 +00002710 if (LocaleCompare("polaroid",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002711 {
cristye9e3d382011-12-14 01:50:13 +00002712 const char
2713 *caption;
2714
anthony805a2d42011-09-25 08:25:12 +00002715 double
2716 angle;
2717
anthony31f1bf72012-01-30 12:37:22 +00002718 if (plus_alt_op != MagickFalse)
2719 {
2720 RandomInfo
2721 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002722
anthony31f1bf72012-01-30 12:37:22 +00002723 random_info=AcquireRandomInfo();
2724 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2725 random_info=DestroyRandomInfo(random_info);
2726 }
2727 else
anthony805a2d42011-09-25 08:25:12 +00002728 {
2729 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002730 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002731 angle=geometry_info.rho;
2732 }
anthony31f1bf72012-01-30 12:37:22 +00002733 caption=GetImageProperty(image,"caption",exception);
2734 new_image=PolaroidImage(image,draw_info,caption,angle,
2735 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002736 break;
2737 }
anthonydcf510d2011-10-30 13:51:40 +00002738 if (LocaleCompare("posterize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002739 {
anthony31f1bf72012-01-30 12:37:22 +00002740 (void) ParseGeometry(arg1,&geometry_info);
2741 (void) PosterizeImage(image,(size_t) geometry_info.rho,
2742 quantize_info->dither,exception);
anthony805a2d42011-09-25 08:25:12 +00002743 break;
2744 }
anthonydcf510d2011-10-30 13:51:40 +00002745 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002746 {
2747 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002748 preview_type;
anthony170fce92011-10-20 11:50:23 +00002749
anthony31f1bf72012-01-30 12:37:22 +00002750 /* FUTURE: should be a 'Genesis' option?
2751 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002752 */
anthony31f1bf72012-01-30 12:37:22 +00002753 preview_type=UndefinedPreview;
2754 if (plus_alt_op == MagickFalse)
2755 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2756 MagickFalse,arg1);
2757 new_image=PreviewImage(image,preview_type,exception);
anthony805a2d42011-09-25 08:25:12 +00002758 break;
2759 }
anthonydcf510d2011-10-30 13:51:40 +00002760 if (LocaleCompare("profile",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002761 {
2762 const char
2763 *name;
2764
2765 const StringInfo
2766 *profile;
2767
2768 Image
2769 *profile_image;
2770
2771 ImageInfo
2772 *profile_info;
2773
anthony31f1bf72012-01-30 12:37:22 +00002774 if (plus_alt_op != MagickFalse)
2775 { /* Remove a profile from the image. */
2776 (void) ProfileImage(image,arg1,(const unsigned char *)
cristy092d71c2011-10-14 18:01:29 +00002777 NULL,0,exception);
anthony805a2d42011-09-25 08:25:12 +00002778 break;
2779 }
anthony31f1bf72012-01-30 12:37:22 +00002780 /* Associate a profile with the image. */
anthony805a2d42011-09-25 08:25:12 +00002781 profile_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00002782 profile=GetImageProfile(image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002783 if (profile != (StringInfo *) NULL)
2784 profile_info->profile=(void *) CloneStringInfo(profile);
anthonyfd706f92012-01-19 04:22:02 +00002785 profile_image=GetImageCache(profile_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002786 profile_info=DestroyImageInfo(profile_info);
2787 if (profile_image == (Image *) NULL)
2788 {
2789 StringInfo
2790 *profile;
2791
2792 profile_info=CloneImageInfo(image_info);
anthonyfd706f92012-01-19 04:22:02 +00002793 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002794 MaxTextExtent);
2795 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2796 if (profile != (StringInfo *) NULL)
2797 {
anthony31f1bf72012-01-30 12:37:22 +00002798 (void) ProfileImage(image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002799 GetStringInfoDatum(profile),(size_t)
cristy092d71c2011-10-14 18:01:29 +00002800 GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002801 profile=DestroyStringInfo(profile);
2802 }
2803 profile_info=DestroyImageInfo(profile_info);
2804 break;
2805 }
2806 ResetImageProfileIterator(profile_image);
2807 name=GetNextImageProfile(profile_image);
2808 while (name != (const char *) NULL)
2809 {
2810 profile=GetImageProfile(profile_image,name);
2811 if (profile != (StringInfo *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002812 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
cristy092d71c2011-10-14 18:01:29 +00002813 (size_t) GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002814 name=GetNextImageProfile(profile_image);
2815 }
2816 profile_image=DestroyImage(profile_image);
2817 break;
2818 }
2819 break;
2820 }
anthony805a2d42011-09-25 08:25:12 +00002821 case 'r':
2822 {
anthonydcf510d2011-10-30 13:51:40 +00002823 if (LocaleCompare("radial-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002824 {
anthonyfd706f92012-01-19 04:22:02 +00002825 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002826 new_image=RadialBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002827 geometry_info.sigma,exception);
2828 break;
2829 }
anthonydcf510d2011-10-30 13:51:40 +00002830 if (LocaleCompare("raise",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002831 {
anthony31f1bf72012-01-30 12:37:22 +00002832 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002833 if ((flags & SigmaValue) == 0)
2834 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00002835 (void) RaiseImage(image,&geometry,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002836 break;
2837 }
anthonydcf510d2011-10-30 13:51:40 +00002838 if (LocaleCompare("random-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002839 {
anthony31f1bf72012-01-30 12:37:22 +00002840 (void) RandomThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002841 break;
2842 }
anthonydcf510d2011-10-30 13:51:40 +00002843 if (LocaleCompare("remap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002844 {
2845 Image
2846 *remap_image;
2847
anthonyfd706f92012-01-19 04:22:02 +00002848 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002849 if (remap_image == (Image *) NULL)
2850 break;
anthony31f1bf72012-01-30 12:37:22 +00002851 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002852 remap_image=DestroyImage(remap_image);
2853 break;
2854 }
anthonydcf510d2011-10-30 13:51:40 +00002855 if (LocaleCompare("repage",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002856 {
anthony31f1bf72012-01-30 12:37:22 +00002857 if (plus_alt_op == MagickFalse)
2858 (void) ResetImagePage(image,arg1);
2859 else
2860 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
anthony805a2d42011-09-25 08:25:12 +00002861 break;
2862 }
anthonydcf510d2011-10-30 13:51:40 +00002863 if (LocaleCompare("resample",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002864 {
anthony31f1bf72012-01-30 12:37:22 +00002865 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00002866 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002867 if ((flags & SigmaValue) == 0)
2868 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002869 new_image=ResampleImage(image,geometry_info.rho,
2870 geometry_info.sigma,image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002871 break;
2872 }
anthonydcf510d2011-10-30 13:51:40 +00002873 if (LocaleCompare("resize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002874 {
anthonyafbaed72011-10-26 12:05:04 +00002875 /* FUTURE: remove blur argument - no longer used */
anthony31f1bf72012-01-30 12:37:22 +00002876 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2877 new_image=ResizeImage(image,geometry.width,geometry.height,
2878 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002879 break;
2880 }
anthonydcf510d2011-10-30 13:51:40 +00002881 if (LocaleCompare("roll",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002882 {
anthony31f1bf72012-01-30 12:37:22 +00002883 (void) ParsePageGeometry(image,arg1,&geometry,exception);
2884 new_image=RollImage(image,geometry.x,geometry.y,exception);
anthony805a2d42011-09-25 08:25:12 +00002885 break;
2886 }
anthonydcf510d2011-10-30 13:51:40 +00002887 if (LocaleCompare("rotate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002888 {
anthonyfd706f92012-01-19 04:22:02 +00002889 if (strchr(arg1,'>') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002890 if (image->columns <= image->rows)
anthony805a2d42011-09-25 08:25:12 +00002891 break;
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;
anthonyafbaed72011-10-26 12:05:04 +00002895
anthonyfd706f92012-01-19 04:22:02 +00002896 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002897 new_image=RotateImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00002898 break;
2899 }
2900 break;
2901 }
2902 case 's':
2903 {
anthonydcf510d2011-10-30 13:51:40 +00002904 if (LocaleCompare("sample",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002905 {
anthony31f1bf72012-01-30 12:37:22 +00002906 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2907 new_image=SampleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00002908 exception);
2909 break;
2910 }
anthonydcf510d2011-10-30 13:51:40 +00002911 if (LocaleCompare("scale",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002912 {
anthony31f1bf72012-01-30 12:37:22 +00002913 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2914 new_image=ScaleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00002915 exception);
2916 break;
2917 }
anthonydcf510d2011-10-30 13:51:40 +00002918 if (LocaleCompare("selective-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002919 {
anthonyfd706f92012-01-19 04:22:02 +00002920 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002921 if ((flags & PercentValue) != 0)
2922 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002923 new_image=SelectiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002924 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
2925 break;
2926 }
anthonydcf510d2011-10-30 13:51:40 +00002927 if (LocaleCompare("separate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002928 {
anthony31f1bf72012-01-30 12:37:22 +00002929 /* WARNING: This can generate multiple images! */
2930 new_image=SeparateImages(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002931 break;
2932 }
anthonydcf510d2011-10-30 13:51:40 +00002933 if (LocaleCompare("sepia-tone",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002934 {
2935 double
2936 threshold;
2937
anthonyfd706f92012-01-19 04:22:02 +00002938 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002939 new_image=SepiaToneImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002940 break;
2941 }
anthonydcf510d2011-10-30 13:51:40 +00002942 if (LocaleCompare("segment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002943 {
anthonyfd706f92012-01-19 04:22:02 +00002944 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002945 if ((flags & SigmaValue) == 0)
2946 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002947 (void) SegmentImage(image,image->colorspace,
anthony805a2d42011-09-25 08:25:12 +00002948 image_info->verbose,geometry_info.rho,geometry_info.sigma,
2949 exception);
2950 break;
2951 }
anthonydcf510d2011-10-30 13:51:40 +00002952 if (LocaleCompare("set",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002953 {
2954 char
2955 *value;
2956
anthony31f1bf72012-01-30 12:37:22 +00002957 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002958 {
anthonyfd706f92012-01-19 04:22:02 +00002959 if (LocaleNCompare(arg1,"registry:",9) == 0)
2960 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00002961 else
anthony31f1bf72012-01-30 12:37:22 +00002962 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00002963 {
anthonyfd706f92012-01-19 04:22:02 +00002964 (void) DeleteImageOption(image_info,arg1+7);
anthony31f1bf72012-01-30 12:37:22 +00002965 (void) DeleteImageArtifact(image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00002966 }
2967 else
anthony31f1bf72012-01-30 12:37:22 +00002968 (void) DeleteImageProperty(image,arg1);
anthony805a2d42011-09-25 08:25:12 +00002969 break;
2970 }
anthony31f1bf72012-01-30 12:37:22 +00002971 value=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002972 exception);
2973 if (value == (char *) NULL)
2974 break;
anthonyfd706f92012-01-19 04:22:02 +00002975 if (LocaleNCompare(arg1,"registry:",9) == 0)
2976 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony805a2d42011-09-25 08:25:12 +00002977 exception);
2978 else
anthonyfd706f92012-01-19 04:22:02 +00002979 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00002980 {
anthonyfd706f92012-01-19 04:22:02 +00002981 (void) SetImageOption(image_info,arg1+7,value);
anthony31f1bf72012-01-30 12:37:22 +00002982 (void) SetImageArtifact(image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00002983 }
2984 else
anthony31f1bf72012-01-30 12:37:22 +00002985 (void) SetImageProperty(image,arg1,value,exception);
anthony805a2d42011-09-25 08:25:12 +00002986 value=DestroyString(value);
2987 break;
2988 }
anthonydcf510d2011-10-30 13:51:40 +00002989 if (LocaleCompare("shade",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002990 {
anthonyfd706f92012-01-19 04:22:02 +00002991 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002992 if ((flags & SigmaValue) == 0)
2993 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002994 new_image=ShadeImage(image,normal_op,geometry_info.rho,
2995 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002996 break;
2997 }
anthonydcf510d2011-10-30 13:51:40 +00002998 if (LocaleCompare("shadow",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002999 {
anthonyfd706f92012-01-19 04:22:02 +00003000 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003001 if ((flags & SigmaValue) == 0)
3002 geometry_info.sigma=1.0;
3003 if ((flags & XiValue) == 0)
3004 geometry_info.xi=4.0;
3005 if ((flags & PsiValue) == 0)
3006 geometry_info.psi=4.0;
anthony31f1bf72012-01-30 12:37:22 +00003007 new_image=ShadowImage(image,geometry_info.rho,
3008 geometry_info.sigma,image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003009 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
3010 exception);
anthony805a2d42011-09-25 08:25:12 +00003011 break;
3012 }
anthonydcf510d2011-10-30 13:51:40 +00003013 if (LocaleCompare("sharpen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003014 {
anthonyfd706f92012-01-19 04:22:02 +00003015 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003016 if ((flags & SigmaValue) == 0)
3017 geometry_info.sigma=1.0;
3018 if ((flags & XiValue) == 0)
3019 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00003020 new_image=SharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003021 geometry_info.sigma,geometry_info.xi,exception);
3022 break;
3023 }
anthonydcf510d2011-10-30 13:51:40 +00003024 if (LocaleCompare("shave",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003025 {
anthony31f1bf72012-01-30 12:37:22 +00003026 flags=ParsePageGeometry(image,arg1,&geometry,exception);
3027 new_image=ShaveImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003028 break;
3029 }
anthonydcf510d2011-10-30 13:51:40 +00003030 if (LocaleCompare("shear",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003031 {
anthonyfd706f92012-01-19 04:22:02 +00003032 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003033 if ((flags & SigmaValue) == 0)
3034 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00003035 new_image=ShearImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003036 geometry_info.sigma,exception);
3037 break;
3038 }
anthonydcf510d2011-10-30 13:51:40 +00003039 if (LocaleCompare("sigmoidal-contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003040 {
anthonyfd706f92012-01-19 04:22:02 +00003041 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003042 if ((flags & SigmaValue) == 0)
3043 geometry_info.sigma=(double) QuantumRange/2.0;
3044 if ((flags & PercentValue) != 0)
3045 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3046 100.0;
anthony31f1bf72012-01-30 12:37:22 +00003047 (void) SigmoidalContrastImage(image,normal_op,geometry_info.rho,
3048 geometry_info.sigma,
anthony805a2d42011-09-25 08:25:12 +00003049 exception);
3050 break;
3051 }
anthonydcf510d2011-10-30 13:51:40 +00003052 if (LocaleCompare("sketch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003053 {
anthonyfd706f92012-01-19 04:22:02 +00003054 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003055 if ((flags & SigmaValue) == 0)
3056 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003057 new_image=SketchImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003058 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3059 break;
3060 }
anthonydcf510d2011-10-30 13:51:40 +00003061 if (LocaleCompare("solarize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003062 {
anthony31f1bf72012-01-30 12:37:22 +00003063 (void) SolarizeImage(image,StringToDoubleInterval(arg1,(double)
3064 QuantumRange+1.0),exception);
anthony805a2d42011-09-25 08:25:12 +00003065 break;
3066 }
anthonydcf510d2011-10-30 13:51:40 +00003067 if (LocaleCompare("sparse-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003068 {
3069 SparseColorMethod
3070 method;
3071
3072 char
3073 *arguments;
3074
anthony805a2d42011-09-25 08:25:12 +00003075 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003076 MagickSparseColorOptions,MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003077 arguments=InterpretImageProperties(image_info,image,arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00003078 if (arguments == (char *) NULL)
3079 break;
anthony31f1bf72012-01-30 12:37:22 +00003080 new_image=SparseColorOption(image,method,arguments,exception);
anthony805a2d42011-09-25 08:25:12 +00003081 arguments=DestroyString(arguments);
3082 break;
3083 }
anthonydcf510d2011-10-30 13:51:40 +00003084 if (LocaleCompare("splice",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003085 {
anthony31f1bf72012-01-30 12:37:22 +00003086 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
3087 new_image=SpliceImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003088 break;
3089 }
anthonydcf510d2011-10-30 13:51:40 +00003090 if (LocaleCompare("spread",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003091 {
anthonyfd706f92012-01-19 04:22:02 +00003092 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003093 new_image=SpreadImage(image,geometry_info.rho,image->interpolate,
3094 exception);
anthony805a2d42011-09-25 08:25:12 +00003095 break;
3096 }
anthonydcf510d2011-10-30 13:51:40 +00003097 if (LocaleCompare("statistic",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003098 {
3099 StatisticType
3100 type;
3101
anthony805a2d42011-09-25 08:25:12 +00003102 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003103 MagickFalse,arg1);
3104 (void) ParseGeometry(arg2,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003105 new_image=StatisticImage(image,type,(size_t) geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003106 (size_t) geometry_info.sigma,exception);
3107 break;
3108 }
anthonydcf510d2011-10-30 13:51:40 +00003109 if (LocaleCompare("strip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003110 {
anthony31f1bf72012-01-30 12:37:22 +00003111 (void) StripImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003112 break;
3113 }
anthonydcf510d2011-10-30 13:51:40 +00003114 if (LocaleCompare("swirl",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003115 {
anthonyfd706f92012-01-19 04:22:02 +00003116 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003117 new_image=SwirlImage(image,geometry_info.rho,
3118 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003119 break;
3120 }
3121 break;
3122 }
3123 case 't':
3124 {
anthonydcf510d2011-10-30 13:51:40 +00003125 if (LocaleCompare("threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003126 {
3127 double
3128 threshold;
3129
anthony31f1bf72012-01-30 12:37:22 +00003130 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003131 threshold=(double) QuantumRange/2;
3132 else
anthonyfd706f92012-01-19 04:22:02 +00003133 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003134 (void) BilevelImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003135 break;
3136 }
anthonydcf510d2011-10-30 13:51:40 +00003137 if (LocaleCompare("thumbnail",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003138 {
anthony31f1bf72012-01-30 12:37:22 +00003139 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3140 new_image=ThumbnailImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003141 exception);
3142 break;
3143 }
anthonydcf510d2011-10-30 13:51:40 +00003144 if (LocaleCompare("tint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003145 {
anthony31f1bf72012-01-30 12:37:22 +00003146 new_image=TintImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00003147 break;
3148 }
anthonydcf510d2011-10-30 13:51:40 +00003149 if (LocaleCompare("transform",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003150 {
anthonyfd706f92012-01-19 04:22:02 +00003151 /* DEPRECIATED */
anthony31f1bf72012-01-30 12:37:22 +00003152 new_image=AffineTransformImage(image,&draw_info->affine,
anthony805a2d42011-09-25 08:25:12 +00003153 exception);
3154 break;
3155 }
anthonydcf510d2011-10-30 13:51:40 +00003156 if (LocaleCompare("transparent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003157 {
3158 PixelInfo
3159 target;
3160
anthony31f1bf72012-01-30 12:37:22 +00003161 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
3162 (void) TransparentPaintImage(image,&target,(Quantum)
3163 TransparentAlpha,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003164 break;
3165 }
anthonydcf510d2011-10-30 13:51:40 +00003166 if (LocaleCompare("transpose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003167 {
anthony31f1bf72012-01-30 12:37:22 +00003168 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003169 break;
3170 }
anthonydcf510d2011-10-30 13:51:40 +00003171 if (LocaleCompare("transverse",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003172 {
anthony31f1bf72012-01-30 12:37:22 +00003173 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003174 break;
3175 }
anthonydcf510d2011-10-30 13:51:40 +00003176 if (LocaleCompare("trim",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003177 {
anthony31f1bf72012-01-30 12:37:22 +00003178 new_image=TrimImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003179 break;
3180 }
anthonydcf510d2011-10-30 13:51:40 +00003181 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003182 {
anthonyab3a50c2011-10-27 11:48:57 +00003183 /* Note that "type" setting should have already been defined */
anthony31f1bf72012-01-30 12:37:22 +00003184 (void) SetImageType(image,image_info->type,exception);
anthony805a2d42011-09-25 08:25:12 +00003185 break;
3186 }
3187 break;
3188 }
3189 case 'u':
3190 {
anthonydcf510d2011-10-30 13:51:40 +00003191 if (LocaleCompare("unique",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003192 {
anthony31f1bf72012-01-30 12:37:22 +00003193 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
3194 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003195 {
anthony31f1bf72012-01-30 12:37:22 +00003196 (void) DeleteImageArtifact(image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003197 break;
3198 }
anthony31f1bf72012-01-30 12:37:22 +00003199 (void) SetImageArtifact(image,"identify:unique-colors","true");
3200 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003201 break;
3202 }
anthonydcf510d2011-10-30 13:51:40 +00003203 if (LocaleCompare("unique-colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003204 {
anthony31f1bf72012-01-30 12:37:22 +00003205 new_image=UniqueImageColors(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003206 break;
3207 }
anthonydcf510d2011-10-30 13:51:40 +00003208 if (LocaleCompare("unsharp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003209 {
anthonyfd706f92012-01-19 04:22:02 +00003210 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003211 if ((flags & SigmaValue) == 0)
3212 geometry_info.sigma=1.0;
3213 if ((flags & XiValue) == 0)
3214 geometry_info.xi=1.0;
3215 if ((flags & PsiValue) == 0)
3216 geometry_info.psi=0.05;
anthony31f1bf72012-01-30 12:37:22 +00003217 new_image=UnsharpMaskImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003218 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3219 break;
3220 }
3221 break;
3222 }
3223 case 'v':
3224 {
anthonydcf510d2011-10-30 13:51:40 +00003225 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003226 {
anthony31f1bf72012-01-30 12:37:22 +00003227 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3228 three places! ImageArtifact ImageOption image_info->verbose
3229 Some how new images also get this artifact -- how???
3230 */
3231 (void) SetImageArtifact(image,option,
3232 (plus_alt_op != MagickFalse) ? "false" : "true" );
anthony805a2d42011-09-25 08:25:12 +00003233 break;
3234 }
anthonydcf510d2011-10-30 13:51:40 +00003235 if (LocaleCompare("vignette",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003236 {
anthonyfd706f92012-01-19 04:22:02 +00003237 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003238 if ((flags & SigmaValue) == 0)
3239 geometry_info.sigma=1.0;
3240 if ((flags & XiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003241 geometry_info.xi=0.1*image->columns;
anthony805a2d42011-09-25 08:25:12 +00003242 if ((flags & PsiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003243 geometry_info.psi=0.1*image->rows;
3244 new_image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
3245 image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3246 (ssize_t) ceil(geometry_info.psi-0.5),exception);
anthony805a2d42011-09-25 08:25:12 +00003247 break;
3248 }
anthony805a2d42011-09-25 08:25:12 +00003249 break;
3250 }
3251 case 'w':
3252 {
anthonydcf510d2011-10-30 13:51:40 +00003253 if (LocaleCompare("wave",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003254 {
anthonyfd706f92012-01-19 04:22:02 +00003255 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003256 if ((flags & SigmaValue) == 0)
3257 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003258 new_image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
3259 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003260 break;
3261 }
anthonydcf510d2011-10-30 13:51:40 +00003262 if (LocaleCompare("white-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003263 {
anthony31f1bf72012-01-30 12:37:22 +00003264 (void) WhiteThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003265 break;
3266 }
3267 break;
3268 }
3269 default:
3270 break;
3271 }
3272 /*
3273 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003274 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003275 */
3276 if (new_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003277 ReplaceImageInListReturnLast(&image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003278
anthony31f1bf72012-01-30 12:37:22 +00003279 return;
anthonyfd706f92012-01-19 04:22:02 +00003280#undef image_info
3281#undef draw_info
3282#undef quantize_info
anthony31f1bf72012-01-30 12:37:22 +00003283#undef image
anthonyfd706f92012-01-19 04:22:02 +00003284#undef exception
anthony31f1bf72012-01-30 12:37:22 +00003285#undef normal_op
3286}
anthonyfd706f92012-01-19 04:22:02 +00003287
anthony31f1bf72012-01-30 12:37:22 +00003288WandExport void WandSimpleOperatorImages(MagickWand *wand,
3289 const MagickBooleanType plus_alt_op, const char *option,
3290 const char *arg1, const char *arg2)
3291{
3292 size_t
3293 n;
3294
3295 register ssize_t
3296 i;
3297
3298 assert(wand->image_info != (const ImageInfo *) NULL);
3299 assert(wand->image_info->signature == MagickSignature);
3300 assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
3301 assert(wand->images != (Image *) NULL); /* there is one image */
3302
3303 i=0;
3304 n=GetImageListLength(wand->images);
3305 wand->images=GetFirstImageInList(wand->images);
3306 for ( ; ; )
3307 {
3308 WandSimpleOperatorImage(wand, plus_alt_op, option, arg1, arg2);
3309 if ( wand->images->next == (Image *) NULL )
3310 break;
3311 wand->images=wand->images->next;
3312 i++;
3313 }
3314 wand->images=GetFirstImageInList(wand->images);
3315 return;
anthony805a2d42011-09-25 08:25:12 +00003316}
3317
3318/*
3319%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3320% %
3321% %
3322% %
anthony31f1bf72012-01-30 12:37:22 +00003323+ 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 +00003324% %
3325% %
3326% %
3327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3328%
anthony31f1bf72012-01-30 12:37:22 +00003329% WandListOperatorImages() applies a single operation that is apply to the
3330% entire image list as a whole. The result is often a complete replacment
3331% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003332%
3333% The format of the MogrifyImage method is:
3334%
anthony31f1bf72012-01-30 12:37:22 +00003335% void WandListOperatorImages(MagickWand *wand,
3336% const MagickBooleanType plus_alt_op, const char *option,
3337% const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003338%
3339% A description of each parameter follows:
3340%
anthony31f1bf72012-01-30 12:37:22 +00003341% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003342%
anthony31f1bf72012-01-30 12:37:22 +00003343% o plus_alt_op: request the 'plus' or alturnative form of the operation
anthony805a2d42011-09-25 08:25:12 +00003344%
anthony31f1bf72012-01-30 12:37:22 +00003345% o option: The option string for the operation
anthony805a2d42011-09-25 08:25:12 +00003346%
anthony31f1bf72012-01-30 12:37:22 +00003347% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003348%
3349*/
anthony31f1bf72012-01-30 12:37:22 +00003350WandExport void WandListOperatorImages(MagickWand *wand,
3351 const MagickBooleanType plus_alt_op, const char *option,
3352 const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003353{
anthony31f1bf72012-01-30 12:37:22 +00003354 Image
3355 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003356
anthony31f1bf72012-01-30 12:37:22 +00003357#define image_info (wand->image_info)
3358#define draw_info (wand->draw_info)
3359#define quantize_info (wand->quantize_info)
3360#define images (wand->images)
3361#define exception (wand->exception)
3362#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
anthony805a2d42011-09-25 08:25:12 +00003363
anthony31f1bf72012-01-30 12:37:22 +00003364 assert(image_info != (const ImageInfo *) NULL);
anthony805a2d42011-09-25 08:25:12 +00003365 assert(image_info->signature == MagickSignature);
anthony31f1bf72012-01-30 12:37:22 +00003366 assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
3367 assert(images != (Image *) NULL); /* there is an image */
3368 assert(images->signature == MagickSignature); /* and is a valid image */
anthony805a2d42011-09-25 08:25:12 +00003369
anthony31f1bf72012-01-30 12:37:22 +00003370 if (wand->debug != MagickFalse)
3371 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3372
3373 (void) SyncImagesSettings(image_info,images,exception);
3374
3375 new_images=NewImageList();
3376
3377 switch (*option)
anthony805a2d42011-09-25 08:25:12 +00003378 {
3379 case 'a':
3380 {
anthony31f1bf72012-01-30 12:37:22 +00003381 if (LocaleCompare("append",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003382 {
anthony31f1bf72012-01-30 12:37:22 +00003383 new_images=AppendImages(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003384 break;
3385 }
anthony31f1bf72012-01-30 12:37:22 +00003386 if (LocaleCompare("average",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003387 {
anthony31f1bf72012-01-30 12:37:22 +00003388 /* DEPRECIATED - use -evaluate-sequence Mean */
3389 WandListOperatorImages(wand,plus_alt_op,"evaluate-sequence","Mean",
3390 NULL);
anthony805a2d42011-09-25 08:25:12 +00003391 break;
3392 }
3393 break;
3394 }
3395 case 'c':
3396 {
anthony31f1bf72012-01-30 12:37:22 +00003397 if (LocaleCompare("clut",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003398 {
anthony31f1bf72012-01-30 12:37:22 +00003399 /* FUTURE - make this a compose option (and thus layers compose )
3400 or perhaps compose last image over all other images.
3401 */
anthony805a2d42011-09-25 08:25:12 +00003402 Image
anthony31f1bf72012-01-30 12:37:22 +00003403 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003404
anthony31f1bf72012-01-30 12:37:22 +00003405 new_images=RemoveFirstImageFromList(&images);
3406 clut_image=RemoveLastImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003407 if (clut_image == (Image *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003408 break;
anthony31f1bf72012-01-30 12:37:22 +00003409 (void) ClutImage(new_images,clut_image,images->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003410 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003411 break;
3412 }
anthony31f1bf72012-01-30 12:37:22 +00003413 if (LocaleCompare("coalesce",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003414 {
anthony31f1bf72012-01-30 12:37:22 +00003415 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003416 break;
3417 }
anthony31f1bf72012-01-30 12:37:22 +00003418 if (LocaleCompare("combine",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003419 {
anthony31f1bf72012-01-30 12:37:22 +00003420 new_images=CombineImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003421 break;
3422 }
anthony31f1bf72012-01-30 12:37:22 +00003423 if (LocaleCompare("composite",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003424 {
3425 Image
3426 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003427 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003428
3429 RectangleInfo
3430 geometry;
3431
anthony31f1bf72012-01-30 12:37:22 +00003432 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003433 compose;
3434
3435 const char*
3436 value;
3437
3438 value=GetImageOption(image_info,"compose");
3439 if (value != (const char *) NULL)
3440 compose=(CompositeOperator) ParseCommandOption(
3441 MagickComposeOptions,MagickFalse,value);
3442 else
anthony31f1bf72012-01-30 12:37:22 +00003443 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003444
anthony31f1bf72012-01-30 12:37:22 +00003445 new_images=RemoveFirstImageFromList(&images);
3446 source_image=RemoveFirstImageFromList(&images);
3447 if (source_image == (Image *) NULL)
3448 break;
3449 /* FUTURE - this should not be here! - should be part of -geometry */
3450 (void) TransformImage(&source_image,(char *) NULL,
3451 source_image->geometry,exception);
anthony5f867ae2011-10-09 10:28:34 +00003452
anthony31f1bf72012-01-30 12:37:22 +00003453 SetGeometry(source_image,&geometry);
3454 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3455 GravityAdjustGeometry(new_images->columns,new_images->rows,
3456 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003457
anthony31f1bf72012-01-30 12:37:22 +00003458 mask_image=RemoveFirstImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003459 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003460 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003461 if ((compose == DisplaceCompositeOp) ||
3462 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003463 { /* Merge Y displacement into X displace/distort map. */
3464 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony6613bf32011-10-15 07:24:44 +00003465 mask_image,0,0,exception);
anthony805a2d42011-09-25 08:25:12 +00003466 mask_image=DestroyImage(mask_image);
3467 }
3468 else
3469 {
3470 /*
3471 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003472 */
cristy1539afd2012-01-30 01:32:59 +00003473 (void) NegateImage(mask_image,MagickFalse,exception);
anthony31f1bf72012-01-30 12:37:22 +00003474 (void) SetImageMask(new_images,mask_image,exception);
cristy1539afd2012-01-30 01:32:59 +00003475 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003476 }
3477 }
anthony31f1bf72012-01-30 12:37:22 +00003478 (void) CompositeImage(new_images,compose,source_image,geometry.x,
3479 geometry.y,exception);
3480 (void) SetImageMask(new_images,(Image *) NULL,exception);
3481 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003482 break;
3483 }
3484 break;
3485 }
3486 case 'd':
3487 {
anthony31f1bf72012-01-30 12:37:22 +00003488 if (LocaleCompare("deconstruct",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003489 {
anthony31f1bf72012-01-30 12:37:22 +00003490 /* DEPRECIATED - use -layers CompareAny */
3491 WandListOperatorImages(wand,plus_alt_op,"layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003492 break;
3493 }
anthony31f1bf72012-01-30 12:37:22 +00003494 if (LocaleCompare("delete",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003495 {
anthony31f1bf72012-01-30 12:37:22 +00003496 if (plus_alt_op != MagickFalse)
3497 DeleteImages(&images,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003498 else
anthony31f1bf72012-01-30 12:37:22 +00003499 DeleteImages(&images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003500 break;
3501 }
anthony31f1bf72012-01-30 12:37:22 +00003502 if (LocaleCompare("duplicate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003503 {
3504 Image
3505 *duplicate_images;
3506
anthony31f1bf72012-01-30 12:37:22 +00003507 if (plus_alt_op != MagickFalse)
3508 duplicate_images=DuplicateImages(images,1,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003509 else
3510 {
3511 const char
3512 *p;
3513
3514 size_t
3515 number_duplicates;
3516
anthony31f1bf72012-01-30 12:37:22 +00003517 number_duplicates=(size_t) StringToLong(arg1);
3518 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003519 if (p == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003520 duplicate_images=DuplicateImages(images,number_duplicates,
anthony805a2d42011-09-25 08:25:12 +00003521 "-1",exception);
3522 else
anthony31f1bf72012-01-30 12:37:22 +00003523 duplicate_images=DuplicateImages(images,number_duplicates,p,
anthony805a2d42011-09-25 08:25:12 +00003524 exception);
3525 }
anthony31f1bf72012-01-30 12:37:22 +00003526 AppendImageToList(&images, duplicate_images);
anthony805a2d42011-09-25 08:25:12 +00003527 break;
3528 }
3529 break;
3530 }
3531 case 'e':
3532 {
anthony31f1bf72012-01-30 12:37:22 +00003533 if (LocaleCompare("evaluate-sequence",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003534 {
anthony805a2d42011-09-25 08:25:12 +00003535 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003536 method;
anthony805a2d42011-09-25 08:25:12 +00003537
anthony31f1bf72012-01-30 12:37:22 +00003538 method=(MagickEvaluateOperator) ParseCommandOption(
3539 MagickEvaluateOptions,MagickFalse,arg1);
3540 new_images=EvaluateImages(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003541 break;
3542 }
3543 break;
3544 }
3545 case 'f':
3546 {
anthony31f1bf72012-01-30 12:37:22 +00003547 if (LocaleCompare("fft",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003548 {
anthony31f1bf72012-01-30 12:37:22 +00003549 new_images=ForwardFourierTransformImage(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003550 break;
3551 }
anthony31f1bf72012-01-30 12:37:22 +00003552 if (LocaleCompare("flatten",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003553 {
anthony31f1bf72012-01-30 12:37:22 +00003554 /* DEPRECIATED use -layers mosaic instead */
3555 WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
anthony805a2d42011-09-25 08:25:12 +00003556 break;
3557 }
anthony31f1bf72012-01-30 12:37:22 +00003558 if (LocaleCompare("fx",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003559 {
anthony31f1bf72012-01-30 12:37:22 +00003560 new_images=FxImage(images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003561 break;
3562 }
3563 break;
3564 }
3565 case 'h':
3566 {
anthony31f1bf72012-01-30 12:37:22 +00003567 if (LocaleCompare("hald-clut",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003568 {
anthony31f1bf72012-01-30 12:37:22 +00003569 /* FUTURE - make this a compose option (and thus layers compose )
3570 or perhaps compose last image over all other images.
3571 */
anthony805a2d42011-09-25 08:25:12 +00003572 Image
anthony31f1bf72012-01-30 12:37:22 +00003573 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003574
anthony31f1bf72012-01-30 12:37:22 +00003575 new_images=RemoveFirstImageFromList(&images);
3576 hald_image=RemoveLastImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003577 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003578 break;
3579 (void) HaldClutImage(new_images,hald_image,exception);
anthony805a2d42011-09-25 08:25:12 +00003580 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003581 break;
3582 }
3583 break;
3584 }
3585 case 'i':
3586 {
anthony31f1bf72012-01-30 12:37:22 +00003587 if (LocaleCompare("ift",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003588 {
3589 Image
anthony805a2d42011-09-25 08:25:12 +00003590 *magnitude_image,
3591 *phase_image;
3592
anthony31f1bf72012-01-30 12:37:22 +00003593 magnitude_image=RemoveFirstImageFromList(&images);
3594 phase_image=RemoveFirstImageFromList(&images);
3595 if (phase_image == (Image *) NULL)
3596 break;
3597 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3598 normal_op,exception);
3599 magnitude_image=DestroyImage(magnitude_image);
3600 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003601 break;
3602 }
anthony31f1bf72012-01-30 12:37:22 +00003603 if (LocaleCompare("insert",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003604 {
3605 Image
anthony31f1bf72012-01-30 12:37:22 +00003606 *insert_image,
3607 *index_image;
3608
3609 ssize_t
3610 index;
anthony805a2d42011-09-25 08:25:12 +00003611
3612 index=0;
anthony31f1bf72012-01-30 12:37:22 +00003613 insert_image=RemoveLastImageFromList(&images);
3614 if (plus_alt_op == MagickFalse)
3615 index=(ssize_t) StringToLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00003616 if (index == 0)
anthony31f1bf72012-01-30 12:37:22 +00003617 PrependImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003618 else
anthony31f1bf72012-01-30 12:37:22 +00003619 if (index == (ssize_t) GetImageListLength(images))
3620 AppendImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003621 else
3622 {
anthony31f1bf72012-01-30 12:37:22 +00003623 index_image=GetImageFromList(images,index-1);
3624 if (index_image == (Image *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003625 {
3626 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00003627 OptionError,"NoSuchImage","`%s'",arg1);
anthony805a2d42011-09-25 08:25:12 +00003628 break;
3629 }
anthony31f1bf72012-01-30 12:37:22 +00003630 InsertImageInList(&index_image,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003631 }
anthony31f1bf72012-01-30 12:37:22 +00003632 images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003633 break;
3634 }
anthony805a2d42011-09-25 08:25:12 +00003635 break;
3636 }
3637 case 'l':
3638 {
anthony31f1bf72012-01-30 12:37:22 +00003639 if (LocaleCompare("layers",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003640 {
anthony805a2d42011-09-25 08:25:12 +00003641 ImageLayerMethod
3642 method;
3643
anthony805a2d42011-09-25 08:25:12 +00003644 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003645 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003646 switch (method)
3647 {
3648 case CoalesceLayer:
3649 {
anthony31f1bf72012-01-30 12:37:22 +00003650 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003651 break;
3652 }
3653 case CompareAnyLayer:
3654 case CompareClearLayer:
3655 case CompareOverlayLayer:
3656 default:
3657 {
anthony31f1bf72012-01-30 12:37:22 +00003658 new_images=CompareImagesLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003659 break;
3660 }
3661 case MergeLayer:
3662 case FlattenLayer:
3663 case MosaicLayer:
3664 case TrimBoundsLayer:
3665 {
anthony31f1bf72012-01-30 12:37:22 +00003666 new_images=MergeImageLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003667 break;
3668 }
3669 case DisposeLayer:
3670 {
anthony31f1bf72012-01-30 12:37:22 +00003671 new_images=DisposeImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003672 break;
3673 }
3674 case OptimizeImageLayer:
3675 {
anthony31f1bf72012-01-30 12:37:22 +00003676 new_images=OptimizeImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003677 break;
3678 }
3679 case OptimizePlusLayer:
3680 {
anthony31f1bf72012-01-30 12:37:22 +00003681 new_images=OptimizePlusImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003682 break;
3683 }
3684 case OptimizeTransLayer:
3685 {
anthony31f1bf72012-01-30 12:37:22 +00003686 OptimizeImageTransparency(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003687 break;
3688 }
3689 case RemoveDupsLayer:
3690 {
anthony31f1bf72012-01-30 12:37:22 +00003691 RemoveDuplicateLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003692 break;
3693 }
3694 case RemoveZeroLayer:
3695 {
anthony31f1bf72012-01-30 12:37:22 +00003696 RemoveZeroDelayLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003697 break;
3698 }
3699 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003700 { /* General Purpose, GIF Animation Optimizer. */
3701 new_images=CoalesceImages(images,exception);
3702 if (new_images == (Image *) NULL)
3703 break;
3704 images=DestroyImageList(images);
3705 images=OptimizeImageLayers(new_images,exception);
3706 if (images == (Image *) NULL)
3707 break;
3708 new_images=DestroyImageList(new_images);
3709 OptimizeImageTransparency(images,exception);
3710 (void) RemapImages(quantize_info,images,(Image *) NULL,
anthony805a2d42011-09-25 08:25:12 +00003711 exception);
3712 break;
3713 }
3714 case CompositeLayer:
3715 {
anthony805a2d42011-09-25 08:25:12 +00003716 Image
3717 *source;
3718
3719 RectangleInfo
3720 geometry;
3721
anthony31f1bf72012-01-30 12:37:22 +00003722 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003723 compose;
3724
3725 const char*
3726 value;
3727
3728 value=GetImageOption(image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003729 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003730 if (value != (const char *) NULL)
3731 compose=(CompositeOperator) ParseCommandOption(
3732 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003733
anthony31f1bf72012-01-30 12:37:22 +00003734 /* Split image sequence at the first 'NULL:' image. */
3735 source=images;
anthony805a2d42011-09-25 08:25:12 +00003736 while (source != (Image *) NULL)
3737 {
3738 source=GetNextImageInList(source);
3739 if ((source != (Image *) NULL) &&
3740 (LocaleCompare(source->magick,"NULL") == 0))
3741 break;
3742 }
3743 if (source != (Image *) NULL)
3744 {
3745 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3746 (GetNextImageInList(source) == (Image *) NULL))
3747 source=(Image *) NULL;
3748 else
anthony31f1bf72012-01-30 12:37:22 +00003749 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003750 source=SplitImageList(source->previous);
3751 DeleteImageFromList(&source);
3752 }
3753 }
3754 if (source == (Image *) NULL)
3755 {
3756 (void) ThrowMagickException(exception,GetMagickModule(),
3757 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003758 break;
3759 }
anthony31f1bf72012-01-30 12:37:22 +00003760 /* Adjust offset with gravity and virtual canvas. */
3761 SetGeometry(images,&geometry);
3762 (void) ParseAbsoluteGeometry(images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003763 geometry.width=source->page.width != 0 ?
3764 source->page.width : source->columns;
3765 geometry.height=source->page.height != 0 ?
3766 source->page.height : source->rows;
anthony31f1bf72012-01-30 12:37:22 +00003767 GravityAdjustGeometry(images->page.width != 0 ?
3768 images->page.width : images->columns,
3769 images->page.height != 0 ? images->page.height :
3770 images->rows,images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003771
anthony31f1bf72012-01-30 12:37:22 +00003772 /* Compose the two image sequences together */
3773 CompositeLayers(images,compose,source,geometry.x,geometry.y,
anthony805a2d42011-09-25 08:25:12 +00003774 exception);
3775 source=DestroyImageList(source);
3776 break;
3777 }
3778 }
anthony805a2d42011-09-25 08:25:12 +00003779 break;
3780 }
anthony72feaa62012-01-17 06:46:23 +00003781 if (LocaleCompare("limit",option) == 0)
3782 {
3783 MagickSizeType
3784 limit;
3785
3786 ResourceType
3787 type;
3788
anthony72feaa62012-01-17 06:46:23 +00003789 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003790 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003791 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003792 if (LocaleCompare("unlimited",arg2) != 0)
3793 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003794 (void) SetMagickResourceLimit(type,limit);
3795 break;
3796 }
anthony805a2d42011-09-25 08:25:12 +00003797 break;
3798 }
3799 case 'm':
3800 {
anthony31f1bf72012-01-30 12:37:22 +00003801 if (LocaleCompare("map",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003802 {
anthony31f1bf72012-01-30 12:37:22 +00003803 /* DEPRECIATED use +remap */
3804 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00003805 break;
3806 }
anthony31f1bf72012-01-30 12:37:22 +00003807 if (LocaleCompare("morph",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003808 {
3809 Image
3810 *morph_image;
3811
anthony31f1bf72012-01-30 12:37:22 +00003812 morph_image=MorphImages(images,StringToUnsignedLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00003813 exception);
3814 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003815 break;
3816 images=DestroyImageList(images);
3817 images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00003818 break;
3819 }
anthony31f1bf72012-01-30 12:37:22 +00003820 if (LocaleCompare("mosaic",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003821 {
anthony31f1bf72012-01-30 12:37:22 +00003822 /* DEPRECIATED use -layers mosaic instead */
3823 WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
anthony805a2d42011-09-25 08:25:12 +00003824 break;
3825 }
3826 break;
3827 }
3828 case 'p':
3829 {
anthony31f1bf72012-01-30 12:37:22 +00003830 if (LocaleCompare("print",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003831 {
3832 char
3833 *string;
3834
anthony31f1bf72012-01-30 12:37:22 +00003835 string=InterpretImageProperties(image_info,images,arg1,
anthony805a2d42011-09-25 08:25:12 +00003836 exception);
3837 if (string == (char *) NULL)
3838 break;
3839 (void) FormatLocaleFile(stdout,"%s",string);
3840 string=DestroyString(string);
3841 }
anthony31f1bf72012-01-30 12:37:22 +00003842 if (LocaleCompare("process",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003843 {
3844 char
3845 **arguments;
3846
3847 int
3848 j,
3849 number_arguments;
3850
anthony31f1bf72012-01-30 12:37:22 +00003851 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00003852 if (arguments == (char **) NULL)
3853 break;
anthony31f1bf72012-01-30 12:37:22 +00003854 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003855 {
3856 char
3857 breaker,
3858 quote,
3859 *token;
3860
3861 const char
3862 *arguments;
3863
3864 int
3865 next,
3866 status;
3867
3868 size_t
3869 length;
3870
3871 TokenInfo
3872 *token_info;
3873
3874 /*
3875 Support old style syntax, filter="-option arg".
3876 */
anthony31f1bf72012-01-30 12:37:22 +00003877 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00003878 token=(char *) NULL;
3879 if (~length >= (MaxTextExtent-1))
3880 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
3881 sizeof(*token));
3882 if (token == (char *) NULL)
3883 break;
3884 next=0;
anthony31f1bf72012-01-30 12:37:22 +00003885 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00003886 token_info=AcquireTokenInfo();
3887 status=Tokenizer(token_info,0,token,length,arguments,"","=",
3888 "\"",'\0',&breaker,&next,&quote);
3889 token_info=DestroyTokenInfo(token_info);
3890 if (status == 0)
3891 {
3892 const char
3893 *argv;
3894
3895 argv=(&(arguments[next]));
anthony31f1bf72012-01-30 12:37:22 +00003896 (void) InvokeDynamicImageFilter(token,&images,1,&argv,
anthony805a2d42011-09-25 08:25:12 +00003897 exception);
3898 }
3899 token=DestroyString(token);
3900 break;
3901 }
3902 (void) SubstituteString(&arguments[1],"-","");
anthony31f1bf72012-01-30 12:37:22 +00003903 (void) InvokeDynamicImageFilter(arguments[1],&images,
anthony805a2d42011-09-25 08:25:12 +00003904 number_arguments-2,(const char **) arguments+2,exception);
3905 for (j=0; j < number_arguments; j++)
3906 arguments[j]=DestroyString(arguments[j]);
3907 arguments=(char **) RelinquishMagickMemory(arguments);
3908 break;
3909 }
3910 break;
3911 }
3912 case 'r':
3913 {
anthony31f1bf72012-01-30 12:37:22 +00003914 if (LocaleCompare("remap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003915 {
anthony31f1bf72012-01-30 12:37:22 +00003916 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3917 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3918 break;
3919 }
3920 if (LocaleCompare("reverse",option) == 0)
3921 {
3922 ReverseImageList(&images);
anthony805a2d42011-09-25 08:25:12 +00003923 break;
3924 }
3925 break;
3926 }
3927 case 's':
3928 {
anthony31f1bf72012-01-30 12:37:22 +00003929 if (LocaleCompare("smush",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003930 {
3931 Image
3932 *smush_image;
3933
3934 ssize_t
3935 offset;
3936
anthony31f1bf72012-01-30 12:37:22 +00003937 offset=(ssize_t) StringToLong(arg1);
3938 smush_image=SmushImages(images,normal_op,offset,exception);
anthony805a2d42011-09-25 08:25:12 +00003939 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003940 break;
3941 images=DestroyImageList(images);
3942 images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00003943 break;
3944 }
anthony31f1bf72012-01-30 12:37:22 +00003945 if (LocaleCompare("swap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003946 {
3947 Image
3948 *p,
3949 *q,
3950 *swap;
3951
3952 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00003953 index,
anthony805a2d42011-09-25 08:25:12 +00003954 swap_index;
3955
anthony31f1bf72012-01-30 12:37:22 +00003956 index=-1;
3957 swap_index=-2;
3958 if (plus_alt_op == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003959 {
3960 GeometryInfo
3961 geometry_info;
3962
3963 MagickStatusType
3964 flags;
3965
3966 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00003967 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003968 index=(ssize_t) geometry_info.rho;
3969 if ((flags & SigmaValue) != 0)
3970 swap_index=(ssize_t) geometry_info.sigma;
3971 }
anthony31f1bf72012-01-30 12:37:22 +00003972 p=GetImageFromList(images,index);
3973 q=GetImageFromList(images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00003974 if ((p == (Image *) NULL) || (q == (Image *) NULL))
3975 {
3976 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00003977 OptionError,"NoSuchImage","`%s'",images->filename);
anthony805a2d42011-09-25 08:25:12 +00003978 break;
3979 }
3980 if (p == q)
3981 break;
3982 swap=CloneImage(p,0,0,MagickTrue,exception);
3983 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
3984 ReplaceImageInList(&q,swap);
anthony31f1bf72012-01-30 12:37:22 +00003985 images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00003986 break;
3987 }
3988 break;
3989 }
3990 case 'w':
3991 {
anthony31f1bf72012-01-30 12:37:22 +00003992 if (LocaleCompare("write",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003993 {
3994 char
3995 key[MaxTextExtent];
3996
3997 Image
3998 *write_images;
3999
4000 ImageInfo
4001 *write_info;
4002
anthony31f1bf72012-01-30 12:37:22 +00004003 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004004 (void) DeleteImageRegistry(key);
anthony31f1bf72012-01-30 12:37:22 +00004005 write_images=images;
4006 if (plus_alt_op != MagickFalse)
4007 write_images=CloneImageList(images,exception);
anthony805a2d42011-09-25 08:25:12 +00004008 write_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00004009 (void) WriteImages(write_info,write_images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00004010 write_info=DestroyImageInfo(write_info);
anthony31f1bf72012-01-30 12:37:22 +00004011 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00004012 write_images=DestroyImageList(write_images);
4013 break;
4014 }
4015 break;
4016 }
4017 default:
4018 break;
4019 }
anthony31f1bf72012-01-30 12:37:22 +00004020 if (new_images == (Image *) NULL)
4021 return;
anthony805a2d42011-09-25 08:25:12 +00004022
anthony31f1bf72012-01-30 12:37:22 +00004023 if (images != (Image *) NULL)
4024 images=DestroyImageList(images);
4025 images=new_images;
4026 return;
4027
4028#undef image_info
4029#undef draw_info
4030#undef quantize_info
4031#undef images
4032#undef exception
4033#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004034}