blob: 0b6a106bcbd5f08f0c1e385f7e11a1208be2d184 [file] [log] [blame]
anthony805a2d42011-09-25 08:25:12 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
anthony8b10b462012-02-08 12:32:44 +00006% OOO PPPP EEEE RRRR AA TTTTT III OOO N N %
7% O O P P E R R A A T I O O NN N %
8% O O PPPP EEE RRRR AAAA T I O O N N N %
9% O O P E R R A A T I O O N NN %
10% OOO P EEEE R RR A A T III OOO N N %
anthony805a2d42011-09-25 08:25:12 +000011% %
12% %
anthony8b10b462012-02-08 12:32:44 +000013% CLI Magick Option Methods %
anthony805a2d42011-09-25 08:25:12 +000014% %
anthony8b10b462012-02-08 12:32:44 +000015% Dragon Computing %
cristy9e58efd2012-01-30 14:27:34 +000016% Anthony Thyssen %
cristy0a0ca4f2011-09-28 01:15:28 +000017% September 2011 %
anthony805a2d42011-09-25 08:25:12 +000018% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
anthony805a2d42011-09-25 08:25:12 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% Apply the given options (settings, and simple, or sequence operations) to
anthony8b10b462012-02-08 12:32:44 +000037% the given image(s) according to the current "image_info", "draw_info", and
38% "quantize_info" settings, stored in a special CLI Image Wand.
anthony805a2d42011-09-25 08:25:12 +000039%
40% The final goal is to allow the execution in a strict one option at a time
41% manner that is needed for 'pipelining and file scripting' of options in
42% IMv7.
43%
anthony8b10b462012-02-08 12:32:44 +000044% Anthony Thyssen, September 2011
anthony805a2d42011-09-25 08:25:12 +000045*/
46
47/*
48 Include declarations.
49*/
50#include "MagickWand/studio.h"
51#include "MagickWand/MagickWand.h"
anthony72feaa62012-01-17 06:46:23 +000052#include "MagickWand/magick-wand-private.h"
anthonyfd706f92012-01-19 04:22:02 +000053#include "MagickWand/operation.h"
anthony805a2d42011-09-25 08:25:12 +000054#include "MagickCore/monitor-private.h"
55#include "MagickCore/thread-private.h"
56#include "MagickCore/string-private.h"
cristy8d951092012-02-08 18:54:56 +000057#if 0
anthony805a2d42011-09-25 08:25:12 +000058
59/*
60 Define declarations.
61*/
62#define UndefinedCompressionQuality 0UL
63/*
64 Constant declaration. (temporary exports)
65*/
66static const char
67 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000068 BorderColor[] = "#dfdfdf", /* sRGB gray */
69 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony805a2d42011-09-25 08:25:12 +000070
71/*
72** Function to report on the progress of image operations
73*/
74static MagickBooleanType MonitorProgress(const char *text,
75 const MagickOffsetType offset,const MagickSizeType extent,
76 void *wand_unused(client_data))
77{
78 char
79 message[MaxTextExtent],
80 tag[MaxTextExtent];
81
82 const char
83 *locale_message;
84
85 register char
86 *p;
87
88 if (extent < 2)
89 return(MagickTrue);
90 (void) CopyMagickMemory(tag,text,MaxTextExtent);
91 p=strrchr(tag,'/');
92 if (p != (char *) NULL)
93 *p='\0';
94 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
95 locale_message=GetLocaleMessage(message);
96 if (locale_message == message)
97 locale_message=tag;
98 if (p == (char *) NULL)
99 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
100 locale_message,(long) offset,(unsigned long) extent,(long)
101 (100L*offset/(extent-1)));
102 else
103 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
104 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
105 (100L*offset/(extent-1)));
106 if (offset == (MagickOffsetType) (extent-1))
107 (void) FormatLocaleFile(stderr,"\n");
108 (void) fflush(stderr);
109 return(MagickTrue);
110}
111
112/*
113** GetImageCache() will read an image into a image cache if not already
114** present then return the image that is in the cache under that filename.
115*/
116static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
117 ExceptionInfo *exception)
118{
119 char
120 key[MaxTextExtent];
121
122 ExceptionInfo
123 *sans_exception;
124
125 Image
126 *image;
127
128 ImageInfo
129 *read_info;
130
131 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
132 sans_exception=AcquireExceptionInfo();
133 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
134 sans_exception=DestroyExceptionInfo(sans_exception);
135 if (image != (Image *) NULL)
136 return(image);
137 read_info=CloneImageInfo(image_info);
138 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
139 image=ReadImage(read_info,exception);
140 read_info=DestroyImageInfo(read_info);
141 if (image != (Image *) NULL)
142 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
143 return(image);
144}
145
146/*
anthonya89dd172011-10-04 13:29:35 +0000147 SparseColorOption() parse the complex -sparse-color argument into an
148 an array of floating point values than call SparseColorImage().
149 Argument is a complex mix of floating-point pixel coodinates, and color
150 specifications (or direct floating point numbers). The number of floats
151 needed to represent a color varies depending on teh current channel
152 setting.
anthony805a2d42011-09-25 08:25:12 +0000153*/
154static Image *SparseColorOption(const Image *image,
155 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000156 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000157{
158 char
159 token[MaxTextExtent];
160
161 const char
162 *p;
163
164 double
165 *sparse_arguments;
166
167 Image
168 *sparse_image;
169
170 PixelInfo
171 color;
172
173 MagickBooleanType
174 error;
175
176 register size_t
177 x;
178
179 size_t
180 number_arguments,
181 number_colors;
182
183 assert(image != (Image *) NULL);
184 assert(image->signature == MagickSignature);
185 if (image->debug != MagickFalse)
186 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
187 assert(exception != (ExceptionInfo *) NULL);
188 assert(exception->signature == MagickSignature);
189 /*
190 Limit channels according to image - and add up number of color channel.
191 */
192 number_colors=0;
193 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
194 number_colors++;
195 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
196 number_colors++;
197 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
198 number_colors++;
199 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
200 (image->colorspace == CMYKColorspace))
201 number_colors++;
202 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
203 (image->matte != MagickFalse))
204 number_colors++;
205
206 /*
207 Read string, to determine number of arguments needed,
208 */
209 p=arguments;
210 x=0;
211 while( *p != '\0' )
212 {
213 GetMagickToken(p,&p,token);
214 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000215 if ( isalpha((int) token[0]) || token[0] == '#' )
216 x += number_colors; /* color argument found */
anthony805a2d42011-09-25 08:25:12 +0000217 else {
218 x++; /* floating point argument */
219 }
220 }
221 error=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +0000222 /* control points and color values */
223 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
224 number_arguments=x;
anthony805a2d42011-09-25 08:25:12 +0000225 if ( error ) {
226 (void) ThrowMagickException(exception,GetMagickModule(),
227 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
228 "Invalid number of Arguments");
229 return( (Image *)NULL);
230 }
231
232 /* Allocate and fill in the floating point arguments */
233 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
234 sizeof(*sparse_arguments));
235 if (sparse_arguments == (double *) NULL) {
236 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
237 "MemoryAllocationFailed","%s","SparseColorOption");
238 return( (Image *)NULL);
239 }
240 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
241 sizeof(*sparse_arguments));
242 p=arguments;
243 x=0;
244 while( *p != '\0' && x < number_arguments ) {
245 /* X coordinate */
246 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
247 if ( token[0] == '\0' ) break;
248 if ( isalpha((int) token[0]) || token[0] == '#' ) {
249 (void) ThrowMagickException(exception,GetMagickModule(),
250 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
251 "Color found, instead of X-coord");
252 error = MagickTrue;
253 break;
254 }
cristydbdd0e32011-11-04 23:29:40 +0000255 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000256 /* Y coordinate */
257 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
258 if ( token[0] == '\0' ) break;
259 if ( isalpha((int) token[0]) || token[0] == '#' ) {
260 (void) ThrowMagickException(exception,GetMagickModule(),
261 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
262 "Color found, instead of Y-coord");
263 error = MagickTrue;
264 break;
265 }
cristydbdd0e32011-11-04 23:29:40 +0000266 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000267 /* color name or function given in string argument */
268 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
269 if ( token[0] == '\0' ) break;
270 if ( isalpha((int) token[0]) || token[0] == '#' ) {
271 /* Color string given */
272 (void) QueryColorCompliance(token,AllCompliance,&color,
273 exception);
274 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
275 sparse_arguments[x++] = QuantumScale*color.red;
276 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
277 sparse_arguments[x++] = QuantumScale*color.green;
278 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
279 sparse_arguments[x++] = QuantumScale*color.blue;
280 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
281 (image->colorspace == CMYKColorspace))
282 sparse_arguments[x++] = QuantumScale*color.black;
283 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
284 (image->matte != MagickFalse))
285 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000286 }
anthony31f1bf72012-01-30 12:37:22 +0000287 else {
288 /* Colors given as a set of floating point values - experimental */
289 /* NB: token contains the first floating point value to use! */
290 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
291 {
292 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
293 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
294 break;
295 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
296 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000297 }
anthony31f1bf72012-01-30 12:37:22 +0000298 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
299 {
300 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
301 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
302 break;
303 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
304 token[0] = ','; /* used this token - get another */
305 }
306 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
307 {
308 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
309 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
310 break;
311 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
312 token[0] = ','; /* used this token - get another */
313 }
314 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
315 (image->colorspace == CMYKColorspace))
316 {
317 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
318 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
319 break;
320 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
321 token[0] = ','; /* used this token - get another */
322 }
323 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
324 (image->matte != MagickFalse))
325 {
326 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
327 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
328 break;
329 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
330 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000331 }
332 }
333 }
334 if ( number_arguments != x && !error ) {
335 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
336 "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
337 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
338 return( (Image *)NULL);
339 }
340 if ( error )
341 return( (Image *)NULL);
342
anthony31f1bf72012-01-30 12:37:22 +0000343 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000344 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
345 exception);
346 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
347 return( sparse_image );
348}
349
350/*
351%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
352% %
353% %
354% %
anthony8b10b462012-02-08 12:32:44 +0000355+ W a n d S e t t i n g O p t i o n I n f o %
anthony805a2d42011-09-25 08:25:12 +0000356% %
357% %
358% %
359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360%
anthonyd1447672012-01-19 05:33:53 +0000361% WandSettingOptionInfo() applies a single settings option into a CLI wand
anthonydcf510d2011-10-30 13:51:40 +0000362% holding the image_info, draw_info, quantize_info structures that will be
anthonyfd706f92012-01-19 04:22:02 +0000363% used when processing the images also found within the wand.
anthony805a2d42011-09-25 08:25:12 +0000364%
anthony80c37752012-01-16 01:03:11 +0000365% These options do no require images to be present in the wand for them to be
anthony31f1bf72012-01-30 12:37:22 +0000366% able to be set, in which case they will be applied to
anthony80c37752012-01-16 01:03:11 +0000367%
368% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000369% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000370%
anthonyd1447672012-01-19 05:33:53 +0000371% The format of the WandSettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000372%
anthony31f1bf72012-01-30 12:37:22 +0000373% void WandSettingOptionInfo(MagickWand *wand,const char *option,
374% const char *arg)
anthony805a2d42011-09-25 08:25:12 +0000375%
376% A description of each parameter follows:
377%
anthony1afdc7a2011-10-05 11:54:28 +0000378% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000379%
anthonydcf510d2011-10-30 13:51:40 +0000380% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000381%
anthony72feaa62012-01-17 06:46:23 +0000382% o arg: The single argument used to set this option.
383% If NULL the setting is reset to its default value.
anthony31f1bf72012-01-30 12:37:22 +0000384% For boolean (no argument) settings false=NULL, true=any_string
anthonydcf510d2011-10-30 13:51:40 +0000385%
anthony72feaa62012-01-17 06:46:23 +0000386% Example usage...
387%
anthonyd1447672012-01-19 05:33:53 +0000388% WandSettingOptionInfo(wand, "background", MagickTrue, "Red");
389% WandSettingOptionInfo(wand, "adjoin", "true");
390% WandSettingOptionInfo(wand, "adjoin", NULL);
anthony72feaa62012-01-17 06:46:23 +0000391%
392% Or for handling command line arguments EG: +/-option ["arg"]
anthonydcf510d2011-10-30 13:51:40 +0000393%
394% argc,argv
395% i=index in argv
396%
397% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
398% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthonyfd706f92012-01-19 04:22:02 +0000399% if ( (flags & SettingOptionFlags) != 0 )
anthonyd1447672012-01-19 05:33:53 +0000400% WandSettingOptionInfo(wand, argv[i]+1,
anthonyfd706f92012-01-19 04:22:02 +0000401% (((*argv[i])!='-') ? (char *)NULL
402% : (count>0) ? argv[i+1] : "true") );
anthonydcf510d2011-10-30 13:51:40 +0000403% i += count+1;
404%
anthony805a2d42011-09-25 08:25:12 +0000405*/
anthony31f1bf72012-01-30 12:37:22 +0000406WandExport void WandSettingOptionInfo(MagickWand *wand,const char *option,
407 const char *arg)
anthony805a2d42011-09-25 08:25:12 +0000408{
anthony1afdc7a2011-10-05 11:54:28 +0000409 assert(wand != (MagickWand *) NULL);
410 assert(wand->signature == WandSignature);
411 assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
anthony1afdc7a2011-10-05 11:54:28 +0000412 if (wand->debug != MagickFalse)
413 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
anthony1afdc7a2011-10-05 11:54:28 +0000414
anthony72feaa62012-01-17 06:46:23 +0000415#define image_info (wand->image_info)
416#define draw_info (wand->draw_info)
417#define quantize_info (wand->quantize_info)
anthonyfd706f92012-01-19 04:22:02 +0000418#define exception (wand->exception)
anthony72feaa62012-01-17 06:46:23 +0000419#define IfSetOption (arg!=(char *)NULL)
420#define ArgOption(def) (IfSetOption?arg:(const char *)(def))
421#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
anthony74b1cfc2011-10-06 12:44:16 +0000422
423 switch (*option)
anthony805a2d42011-09-25 08:25:12 +0000424 {
425 case 'a':
426 {
anthony74b1cfc2011-10-06 12:44:16 +0000427 if (LocaleCompare("adjoin",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000428 {
anthony72feaa62012-01-17 06:46:23 +0000429 image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000430 break;
431 }
anthony74b1cfc2011-10-06 12:44:16 +0000432 if (LocaleCompare("affine",option) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000433 {
anthony31f1bf72012-01-30 12:37:22 +0000434 /* DEPRECIATED: draw_info setting only: for -draw and -transform */
anthony74b1cfc2011-10-06 12:44:16 +0000435 if (IfSetOption)
anthony72feaa62012-01-17 06:46:23 +0000436 (void) ParseAffineGeometry(arg,&draw_info->affine,exception);
anthony74b1cfc2011-10-06 12:44:16 +0000437 else
anthony72feaa62012-01-17 06:46:23 +0000438 GetAffineMatrix(&draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000439 break;
440 }
anthony74b1cfc2011-10-06 12:44:16 +0000441 if (LocaleCompare("antialias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000442 {
anthony1afdc7a2011-10-05 11:54:28 +0000443 image_info->antialias =
anthony72feaa62012-01-17 06:46:23 +0000444 draw_info->stroke_antialias =
445 draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000446 break;
447 }
anthony31f1bf72012-01-30 12:37:22 +0000448 if (LocaleCompare("attenuate",option+1) == 0)
449 {
450 (void) SetImageOption(image_info,option,ArgOption(NULL));
451 break;
452 }
anthony74b1cfc2011-10-06 12:44:16 +0000453 if (LocaleCompare("authenticate",option) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000454 {
anthony72feaa62012-01-17 06:46:23 +0000455 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000456 break;
457 }
458 break;
459 }
460 case 'b':
461 {
anthony74b1cfc2011-10-06 12:44:16 +0000462 if (LocaleCompare("background",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000463 {
anthony74b1cfc2011-10-06 12:44:16 +0000464 /* FUTURE: both image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000465 image_info only used directly for generating new images.
466 SyncImageSettings() used to set per-image attribute.
467
468 FUTURE: if image_info->background_color is not set then
469 we should fall back to image
470 Note that +background, means fall-back to image background
471 and only if not set fall back to BackgroundColor const.
anthony74b1cfc2011-10-06 12:44:16 +0000472 */
anthony72feaa62012-01-17 06:46:23 +0000473 (void) SetImageOption(image_info,option,ArgOption(NULL));
474 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
475 &image_info->background_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000476 break;
477 }
anthony74b1cfc2011-10-06 12:44:16 +0000478 if (LocaleCompare("bias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000479 {
anthony74b1cfc2011-10-06 12:44:16 +0000480 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000481 as it is actually rarely used except in direct convolve operations
482 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000483
484 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000485 */
anthony72feaa62012-01-17 06:46:23 +0000486 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000487 break;
488 }
anthony74b1cfc2011-10-06 12:44:16 +0000489 if (LocaleCompare("black-point-compensation",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000490 {
anthony72feaa62012-01-17 06:46:23 +0000491 /* Used as a image chromaticity setting
492 SyncImageSettings() used to set per-image attribute.
493 */
anthony74b1cfc2011-10-06 12:44:16 +0000494 (void) SetImageOption(image_info,option,
495 IfSetOption ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +0000496 break;
497 }
anthony74b1cfc2011-10-06 12:44:16 +0000498 if (LocaleCompare("blue-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000499 {
anthonyafbaed72011-10-26 12:05:04 +0000500 /* Image chromaticity X,Y NB: Y=X if Y not defined
501 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000502 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000503 */
anthony72feaa62012-01-17 06:46:23 +0000504 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000505 break;
506 }
anthony74b1cfc2011-10-06 12:44:16 +0000507 if (LocaleCompare("bordercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000508 {
anthony72feaa62012-01-17 06:46:23 +0000509 /* FUTURE: both image_info attribute & ImageOption in use!
510 SyncImageSettings() used to set per-image attribute.
511 */
anthony74b1cfc2011-10-06 12:44:16 +0000512 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000513 {
anthonydcf510d2011-10-30 13:51:40 +0000514 (void) SetImageOption(image_info,option,arg);
anthony72feaa62012-01-17 06:46:23 +0000515 (void) QueryColorCompliance(arg,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000516 &image_info->border_color,exception);
anthonydcf510d2011-10-30 13:51:40 +0000517 (void) QueryColorCompliance(arg,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000518 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000519 break;
520 }
anthony74b1cfc2011-10-06 12:44:16 +0000521 (void) DeleteImageOption(image_info,option);
522 (void) QueryColorCompliance(BorderColor,AllCompliance,
523 &image_info->border_color,exception);
524 (void) QueryColorCompliance(BorderColor,AllCompliance,
525 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000526 break;
527 }
anthony74b1cfc2011-10-06 12:44:16 +0000528 if (LocaleCompare("box",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000529 {
anthonyfd706f92012-01-19 04:22:02 +0000530 /* DEPRECIATED - now "undercolor" */
anthonyd1447672012-01-19 05:33:53 +0000531 WandSettingOptionInfo(wand,"undercolor",arg);
anthonyfd706f92012-01-19 04:22:02 +0000532 break;
anthony805a2d42011-09-25 08:25:12 +0000533 }
534 break;
535 }
536 case 'c':
537 {
anthony74b1cfc2011-10-06 12:44:16 +0000538 if (LocaleCompare("cache",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000539 {
540 MagickSizeType
541 limit;
542
543 limit=MagickResourceInfinity;
anthonydcf510d2011-10-30 13:51:40 +0000544 if (LocaleCompare("unlimited",arg) != 0)
cristy9b34e302011-11-05 02:15:45 +0000545 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg,100.0);
anthony805a2d42011-09-25 08:25:12 +0000546 (void) SetMagickResourceLimit(MemoryResource,limit);
547 (void) SetMagickResourceLimit(MapResource,2*limit);
548 break;
549 }
anthony74b1cfc2011-10-06 12:44:16 +0000550 if (LocaleCompare("caption",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000551 {
anthony72feaa62012-01-17 06:46:23 +0000552 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000553 break;
554 }
anthony74b1cfc2011-10-06 12:44:16 +0000555 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000556 {
anthony31f1bf72012-01-30 12:37:22 +0000557 /* This is applied to images in SimpleImageOperator!!!
558 FUTURE: move it to SyncImageSettings() - or alternative
559 */
anthony74b1cfc2011-10-06 12:44:16 +0000560 image_info->channel=(ChannelType) (
anthonydcf510d2011-10-30 13:51:40 +0000561 IfSetOption ? ParseChannelOption(arg) : DefaultChannels );
anthony805a2d42011-09-25 08:25:12 +0000562 break;
563 }
anthony74b1cfc2011-10-06 12:44:16 +0000564 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000565 {
anthonyafbaed72011-10-26 12:05:04 +0000566 /* Setting used for new images via AquireImage()
567 But also used as a SimpleImageOperator
568 Undefined colorspace means don't modify images on
569 read or as a operation */
anthony72feaa62012-01-17 06:46:23 +0000570 image_info->colorspace=(ColorspaceType) ParseCommandOption(
571 MagickColorspaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000572 break;
573 }
anthony74b1cfc2011-10-06 12:44:16 +0000574 if (LocaleCompare("comment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000575 {
anthony72feaa62012-01-17 06:46:23 +0000576 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000577 break;
578 }
anthony74b1cfc2011-10-06 12:44:16 +0000579 if (LocaleCompare("compose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000580 {
anthony72feaa62012-01-17 06:46:23 +0000581 /* FUTURE: image_info should be used,
582 SyncImageSettings() used to set per-image attribute. - REMOVE
583
anthonyafbaed72011-10-26 12:05:04 +0000584 This setting should NOT be used to set image 'compose'
anthony72feaa62012-01-17 06:46:23 +0000585 "-layer" operators shoud use image_info if defined otherwise
586 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000587 */
anthony72feaa62012-01-17 06:46:23 +0000588 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony965524b2011-10-07 12:34:14 +0000589 image_info->compose=(CompositeOperator) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000590 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000591 break;
592 }
anthony74b1cfc2011-10-06 12:44:16 +0000593 if (LocaleCompare("compress",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000594 {
anthony5f867ae2011-10-09 10:28:34 +0000595 /* FUTURE: What should be used? image_info or ImageOption ???
596 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000597 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000598
599 The coders appears to use image_info, not Image_Option
600 however the image attribute (for save) is set from the
601 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000602
603 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000604 */
anthony72feaa62012-01-17 06:46:23 +0000605 (void) SetImageOption(image_info,option,ArgOption(NULL));
606 image_info->compression=(CompressionType) ParseCommandOption(
607 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000608 break;
609 }
610 break;
611 }
612 case 'd':
613 {
anthony74b1cfc2011-10-06 12:44:16 +0000614 if (LocaleCompare("debug",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000615 {
anthony72feaa62012-01-17 06:46:23 +0000616 /* SyncImageSettings() used to set per-image attribute. */
617 (void) SetLogEventMask(ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000618 image_info->debug=IsEventLogging(); /* extract logging*/
619 wand->debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000620 break;
621 }
anthony74b1cfc2011-10-06 12:44:16 +0000622 if (LocaleCompare("define",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000623 {
anthony72feaa62012-01-17 06:46:23 +0000624 /* DefineImageOption() equals SetImageOption() but with '='
625 It does not however set individual image options.
626 -set will set individual image options as well!
anthony5f867ae2011-10-09 10:28:34 +0000627 */
anthonydcf510d2011-10-30 13:51:40 +0000628 if (LocaleNCompare(arg,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000629 {
anthony5f867ae2011-10-09 10:28:34 +0000630 if (IfSetOption)
anthonydcf510d2011-10-30 13:51:40 +0000631 (void) DefineImageRegistry(StringRegistryType,arg+9,
anthony5f867ae2011-10-09 10:28:34 +0000632 exception);
633 else
anthony72feaa62012-01-17 06:46:23 +0000634 (void) DeleteImageRegistry(arg+9);
anthony805a2d42011-09-25 08:25:12 +0000635 break;
636 }
anthony5f867ae2011-10-09 10:28:34 +0000637 if (IfSetOption)
anthony72feaa62012-01-17 06:46:23 +0000638 (void) DefineImageOption(image_info,arg);
anthony5f867ae2011-10-09 10:28:34 +0000639 else
anthony72feaa62012-01-17 06:46:23 +0000640 (void) DeleteImageOption(image_info,arg);
anthony805a2d42011-09-25 08:25:12 +0000641 break;
642 }
anthony74b1cfc2011-10-06 12:44:16 +0000643 if (LocaleCompare("delay",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000644 {
anthonyafbaed72011-10-26 12:05:04 +0000645 /* Only used for new images via AcquireImage()
646 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000647 */
anthony72feaa62012-01-17 06:46:23 +0000648 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000649 break;
650 }
anthony74b1cfc2011-10-06 12:44:16 +0000651 if (LocaleCompare("density",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000652 {
anthony72feaa62012-01-17 06:46:23 +0000653 /* FUTURE: strings used in image_info attr and draw_info!
654 Basically as density can be in a XxY form!
655
656 SyncImageSettings() used to set per-image attribute.
657 */
658 (void) SetImageOption(image_info,option,ArgOption(NULL));
659 (void) CloneString(&image_info->density,ArgOption(NULL));
660 (void) CloneString(&draw_info->density,image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000661 break;
662 }
anthony74b1cfc2011-10-06 12:44:16 +0000663 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000664 {
anthony72feaa62012-01-17 06:46:23 +0000665 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
666 SyncImageSettings() used to set per-image attribute.
667 */
anthonydcf510d2011-10-30 13:51:40 +0000668 image_info->depth=IfSetOption?StringToUnsignedLong(arg)
anthony5f867ae2011-10-09 10:28:34 +0000669 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000670 break;
671 }
anthony74b1cfc2011-10-06 12:44:16 +0000672 if (LocaleCompare("direction",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000673 {
anthony6dc09cd2011-10-12 08:56:49 +0000674 /* Image Option is only used to set draw_info */
anthony72feaa62012-01-17 06:46:23 +0000675 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony5f867ae2011-10-09 10:28:34 +0000676 draw_info->direction=(DirectionType) ParseCommandOption(
677 MagickDirectionOptions,MagickFalse,
anthony72feaa62012-01-17 06:46:23 +0000678 ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000679 break;
680 }
anthony74b1cfc2011-10-06 12:44:16 +0000681 if (LocaleCompare("display",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000682 {
anthony72feaa62012-01-17 06:46:23 +0000683 (void) CloneString(&image_info->server_name,ArgOption(NULL));
684 (void) CloneString(&draw_info->server_name,image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000685 break;
686 }
anthony74b1cfc2011-10-06 12:44:16 +0000687 if (LocaleCompare("dispose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000688 {
anthony72feaa62012-01-17 06:46:23 +0000689 /* only used in setting new images */
690 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000691 break;
692 }
anthony74b1cfc2011-10-06 12:44:16 +0000693 if (LocaleCompare("dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000694 {
anthony72feaa62012-01-17 06:46:23 +0000695 /* image_info attr (on/off), quantize_info attr (on/off)
696 but also ImageInfo and quantize_info method!
697 FUTURE: merge the duality of the dithering options
698 */
699 image_info->dither = quantize_info->dither = ArgBoolean;
700 (void) SetImageOption(image_info,option,ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000701 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000702 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000703 if (quantize_info->dither_method == NoDitherMethod)
anthony72feaa62012-01-17 06:46:23 +0000704 image_info->dither = quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000705 break;
706 }
707 break;
708 }
709 case 'e':
710 {
anthony74b1cfc2011-10-06 12:44:16 +0000711 if (LocaleCompare("encoding",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000712 {
anthony72feaa62012-01-17 06:46:23 +0000713 (void) CloneString(&draw_info->encoding,ArgOption("undefined"));
714 (void) SetImageOption(image_info,option,draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000715 break;
716 }
anthony74b1cfc2011-10-06 12:44:16 +0000717 if (LocaleCompare("endian",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000718 {
anthony72feaa62012-01-17 06:46:23 +0000719 /* Both image_info attr and ImageInfo */
720 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000721 image_info->endian=(EndianType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000722 MagickEndianOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000723 break;
724 }
anthony74b1cfc2011-10-06 12:44:16 +0000725 if (LocaleCompare("extract",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000726 {
anthony72feaa62012-01-17 06:46:23 +0000727 (void) CloneString(&image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000728 break;
729 }
730 break;
731 }
732 case 'f':
733 {
anthony72feaa62012-01-17 06:46:23 +0000734 if (LocaleCompare("family",option) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000735 {
anthony72feaa62012-01-17 06:46:23 +0000736 (void) CloneString(&draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000737 break;
738 }
anthony74b1cfc2011-10-06 12:44:16 +0000739 if (LocaleCompare("fill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000740 {
anthonyfd706f92012-01-19 04:22:02 +0000741 /* Set "fill" OR "fill-pattern" in draw_info
742 The original fill color is preserved if a fill-pattern is given.
743 That way it does not effect other operations that directly using
744 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000745 */
anthony6dc09cd2011-10-12 08:56:49 +0000746 const char
anthony72feaa62012-01-17 06:46:23 +0000747 *value;
748
749 MagickBooleanType
750 status;
anthony6dc09cd2011-10-12 08:56:49 +0000751
752 ExceptionInfo
753 *sans;
754
anthonyfd706f92012-01-19 04:22:02 +0000755 PixelInfo
756 color;
757
anthony72feaa62012-01-17 06:46:23 +0000758 value = ArgOption("none");
anthony6dc09cd2011-10-12 08:56:49 +0000759 (void) SetImageOption(image_info,option,value);
anthony6dc09cd2011-10-12 08:56:49 +0000760 if (draw_info->fill_pattern != (Image *) NULL)
761 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000762
763 /* is it a color or a image? -- ignore exceptions */
764 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +0000765 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000766 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000767
anthony6dc09cd2011-10-12 08:56:49 +0000768 if (status == MagickFalse)
anthony72feaa62012-01-17 06:46:23 +0000769 draw_info->fill_pattern=GetImageCache(image_info,value,exception);
anthonyfd706f92012-01-19 04:22:02 +0000770 else
771 draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000772 break;
773 }
anthony74b1cfc2011-10-06 12:44:16 +0000774 if (LocaleCompare("filter",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000775 {
anthony72feaa62012-01-17 06:46:23 +0000776 /* SyncImageSettings() used to set per-image attribute. */
777 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000778 break;
779 }
anthonydcf510d2011-10-30 13:51:40 +0000780 if (LocaleCompare("font",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000781 {
anthony72feaa62012-01-17 06:46:23 +0000782 (void) CloneString(&draw_info->font,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000783 (void) CloneString(&image_info->font,draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000784 break;
785 }
anthony74b1cfc2011-10-06 12:44:16 +0000786 if (LocaleCompare("format",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000787 {
anthonydcf510d2011-10-30 13:51:40 +0000788 /* FUTURE: why the ping test, you could set ping after this! */
789 /*
anthony805a2d42011-09-25 08:25:12 +0000790 register const char
791 *q;
792
anthonydcf510d2011-10-30 13:51:40 +0000793 for (q=strchr(arg,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000794 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
795 image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000796 */
anthony72feaa62012-01-17 06:46:23 +0000797 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000798 break;
799 }
anthony74b1cfc2011-10-06 12:44:16 +0000800 if (LocaleCompare("fuzz",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000801 {
anthony72feaa62012-01-17 06:46:23 +0000802 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000803 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000804 SyncImageSettings() used to set per-image attribute.
805
806 Can't find anything else using image_info->fuzz directly!
anthony6613bf32011-10-15 07:24:44 +0000807 */
808 if (IfSetOption)
cristy947cb4c2011-10-20 18:41:46 +0000809 {
anthony80c37752012-01-16 01:03:11 +0000810 image_info->fuzz=StringToDoubleInterval(arg,(double)
811 QuantumRange+1.0);
anthonydcf510d2011-10-30 13:51:40 +0000812 (void) SetImageOption(image_info,option,arg);
cristy947cb4c2011-10-20 18:41:46 +0000813 break;
814 }
815 image_info->fuzz=0.0;
816 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +0000817 break;
818 }
819 break;
820 }
821 case 'g':
822 {
anthony74b1cfc2011-10-06 12:44:16 +0000823 if (LocaleCompare("gravity",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000824 {
anthony72feaa62012-01-17 06:46:23 +0000825 /* SyncImageSettings() used to set per-image attribute. */
826 (void) SetImageOption(image_info,option,ArgOption("none"));
anthony6dc09cd2011-10-12 08:56:49 +0000827 draw_info->gravity=(GravityType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000828 MagickGravityOptions,MagickFalse,ArgOption("none"));
anthony805a2d42011-09-25 08:25:12 +0000829 break;
830 }
anthony74b1cfc2011-10-06 12:44:16 +0000831 if (LocaleCompare("green-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000832 {
anthonydcf510d2011-10-30 13:51:40 +0000833 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000834 SyncImageSettings() used to set per-image attribute.
835 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000836 */
anthony72feaa62012-01-17 06:46:23 +0000837 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000838 break;
839 }
840 break;
841 }
842 case 'i':
843 {
anthony74b1cfc2011-10-06 12:44:16 +0000844 if (LocaleCompare("intent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000845 {
anthony72feaa62012-01-17 06:46:23 +0000846 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000847 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000848 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000849 */
anthony72feaa62012-01-17 06:46:23 +0000850 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000851 break;
852 }
anthony74b1cfc2011-10-06 12:44:16 +0000853 if (LocaleCompare("interlace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000854 {
anthony72feaa62012-01-17 06:46:23 +0000855 /* image_info is directly used by coders (so why an image setting?)
856 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000857 */
anthony72feaa62012-01-17 06:46:23 +0000858 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000859 image_info->interlace=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000860 MagickInterlaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000861 break;
862 }
anthony74b1cfc2011-10-06 12:44:16 +0000863 if (LocaleCompare("interline-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000864 {
anthony72feaa62012-01-17 06:46:23 +0000865 (void) SetImageOption(image_info,option, ArgOption(NULL));
866 draw_info->interline_spacing=StringToDouble(ArgOption("0"),
867 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000868 break;
869 }
anthony74b1cfc2011-10-06 12:44:16 +0000870 if (LocaleCompare("interpolate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000871 {
anthonyfd706f92012-01-19 04:22:02 +0000872 /* SyncImageSettings() used to set per-image attribute. */
anthony72feaa62012-01-17 06:46:23 +0000873 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000874 break;
875 }
cristy947cb4c2011-10-20 18:41:46 +0000876 if (LocaleCompare("interword-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000877 {
anthony72feaa62012-01-17 06:46:23 +0000878 (void) SetImageOption(image_info,option, ArgOption(NULL));
879 draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000880 break;
881 }
882 break;
883 }
884 case 'k':
885 {
anthony74b1cfc2011-10-06 12:44:16 +0000886 if (LocaleCompare("kerning",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000887 {
anthony72feaa62012-01-17 06:46:23 +0000888 (void) SetImageOption(image_info,option,ArgOption(NULL));
889 draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000890 break;
891 }
892 break;
893 }
894 case 'l':
895 {
anthony74b1cfc2011-10-06 12:44:16 +0000896 if (LocaleCompare("label",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000897 {
anthony72feaa62012-01-17 06:46:23 +0000898 /* only used for new images - not in SyncImageOptions() */
899 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000900 break;
901 }
anthony74b1cfc2011-10-06 12:44:16 +0000902 if (LocaleCompare("list",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000903 {
904 ssize_t
905 list;
906
anthony72feaa62012-01-17 06:46:23 +0000907 list=ParseCommandOption(MagickListOptions,MagickFalse,
908 ArgOption("list"));
anthony805a2d42011-09-25 08:25:12 +0000909 switch (list)
910 {
911 case MagickCoderOptions:
912 {
913 (void) ListCoderInfo((FILE *) NULL,exception);
914 break;
915 }
916 case MagickColorOptions:
917 {
918 (void) ListColorInfo((FILE *) NULL,exception);
919 break;
920 }
921 case MagickConfigureOptions:
922 {
923 (void) ListConfigureInfo((FILE *) NULL,exception);
924 break;
925 }
926 case MagickDelegateOptions:
927 {
928 (void) ListDelegateInfo((FILE *) NULL,exception);
929 break;
930 }
931 case MagickFontOptions:
932 {
933 (void) ListTypeInfo((FILE *) NULL,exception);
934 break;
935 }
936 case MagickFormatOptions:
937 {
938 (void) ListMagickInfo((FILE *) NULL,exception);
939 break;
940 }
941 case MagickLocaleOptions:
942 {
943 (void) ListLocaleInfo((FILE *) NULL,exception);
944 break;
945 }
946 case MagickLogOptions:
947 {
948 (void) ListLogInfo((FILE *) NULL,exception);
949 break;
950 }
951 case MagickMagicOptions:
952 {
953 (void) ListMagicInfo((FILE *) NULL,exception);
954 break;
955 }
956 case MagickMimeOptions:
957 {
958 (void) ListMimeInfo((FILE *) NULL,exception);
959 break;
960 }
961 case MagickModuleOptions:
962 {
963 (void) ListModuleInfo((FILE *) NULL,exception);
964 break;
965 }
966 case MagickPolicyOptions:
967 {
968 (void) ListPolicyInfo((FILE *) NULL,exception);
969 break;
970 }
971 case MagickResourceOptions:
972 {
973 (void) ListMagickResourceInfo((FILE *) NULL,exception);
974 break;
975 }
976 case MagickThresholdOptions:
977 {
978 (void) ListThresholdMaps((FILE *) NULL,exception);
979 break;
980 }
981 default:
982 {
983 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
984 exception);
985 break;
986 }
987 }
988 break;
989 }
anthony74b1cfc2011-10-06 12:44:16 +0000990 if (LocaleCompare("log",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000991 {
anthonydcf510d2011-10-30 13:51:40 +0000992 if (IfSetOption)
993 (void) SetLogFormat(arg);
anthony805a2d42011-09-25 08:25:12 +0000994 break;
995 }
anthony74b1cfc2011-10-06 12:44:16 +0000996 if (LocaleCompare("loop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000997 {
anthony72feaa62012-01-17 06:46:23 +0000998 /* SyncImageSettings() used to set per-image attribute. */
999 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001000 break;
1001 }
1002 break;
1003 }
1004 case 'm':
1005 {
anthony74b1cfc2011-10-06 12:44:16 +00001006 if (LocaleCompare("mattecolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001007 {
anthony72feaa62012-01-17 06:46:23 +00001008 /* SyncImageSettings() used to set per-image attribute. */
1009 (void) SetImageOption(image_info,option,ArgOption(NULL));
1010 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1011 &image_info->matte_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001012 break;
1013 }
anthony74b1cfc2011-10-06 12:44:16 +00001014 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001015 {
anthony31f1bf72012-01-30 12:37:22 +00001016 (void) SetImageInfoProgressMonitor(image_info, IfSetOption?
1017 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001018 break;
1019 }
anthony74b1cfc2011-10-06 12:44:16 +00001020 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001021 {
anthony72feaa62012-01-17 06:46:23 +00001022 /* Setting (for some input coders)
1023 But also a special 'type' operator
1024 */
1025 image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001026 break;
1027 }
1028 break;
1029 }
1030 case 'o':
1031 {
anthony74b1cfc2011-10-06 12:44:16 +00001032 if (LocaleCompare("orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001033 {
anthony72feaa62012-01-17 06:46:23 +00001034 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001035 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001036 FUTURE: make set meta-data operator instead.
1037 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001038 */
anthony72feaa62012-01-17 06:46:23 +00001039 (void) SetImageOption(image_info,option, ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001040 image_info->orientation=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001041 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001042 break;
1043 }
1044 }
1045 case 'p':
1046 {
anthony74b1cfc2011-10-06 12:44:16 +00001047 if (LocaleCompare("page",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001048 {
anthony72feaa62012-01-17 06:46:23 +00001049 /* Only used for new images and image generators
1050 SyncImageSettings() used to set per-image attribute. ?????
1051 That last is WRONG!!!!
1052 */
anthony805a2d42011-09-25 08:25:12 +00001053 char
1054 *canonical_page,
1055 page[MaxTextExtent];
1056
1057 const char
1058 *image_option;
1059
1060 MagickStatusType
1061 flags;
1062
1063 RectangleInfo
1064 geometry;
1065
anthonydcf510d2011-10-30 13:51:40 +00001066 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001067 {
anthony74b1cfc2011-10-06 12:44:16 +00001068 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +00001069 (void) CloneString(&image_info->page,(char *) NULL);
1070 break;
1071 }
1072 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1073 image_option=GetImageOption(image_info,"page");
1074 if (image_option != (const char *) NULL)
1075 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthonydcf510d2011-10-30 13:51:40 +00001076 canonical_page=GetPageGeometry(arg);
anthony805a2d42011-09-25 08:25:12 +00001077 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1078 canonical_page=DestroyString(canonical_page);
1079 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1080 (unsigned long) geometry.width,(unsigned long) geometry.height);
1081 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1082 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1083 (unsigned long) geometry.width,(unsigned long) geometry.height,
1084 (long) geometry.x,(long) geometry.y);
anthony74b1cfc2011-10-06 12:44:16 +00001085 (void) SetImageOption(image_info,option,page);
anthony805a2d42011-09-25 08:25:12 +00001086 (void) CloneString(&image_info->page,page);
1087 break;
1088 }
anthony74b1cfc2011-10-06 12:44:16 +00001089 if (LocaleCompare("ping",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001090 {
anthony72feaa62012-01-17 06:46:23 +00001091 image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001092 break;
1093 }
anthony74b1cfc2011-10-06 12:44:16 +00001094 if (LocaleCompare("pointsize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001095 {
anthony72feaa62012-01-17 06:46:23 +00001096 image_info->pointsize=draw_info->pointsize=
1097 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001098 break;
1099 }
anthony74b1cfc2011-10-06 12:44:16 +00001100 if (LocaleCompare("precision",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001101 {
anthony72feaa62012-01-17 06:46:23 +00001102 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001103 break;
1104 }
anthonydcf510d2011-10-30 13:51:40 +00001105 /* FUTURE: Only the 'preview' coder appears to use this
1106 * Depreciate the coder? Leaving only the 'preview' operator.
anthony74b1cfc2011-10-06 12:44:16 +00001107 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001108 {
anthonydcf510d2011-10-30 13:51:40 +00001109 image_info->preview_type=UndefinedPreview;
1110 if (IfSetOption)
1111 image_info->preview_type=(PreviewType) ParseCommandOption(
1112 MagickPreviewOptions,MagickFalse,arg);
anthony805a2d42011-09-25 08:25:12 +00001113 break;
1114 }
anthonydcf510d2011-10-30 13:51:40 +00001115 */
anthony805a2d42011-09-25 08:25:12 +00001116 break;
1117 }
1118 case 'q':
1119 {
anthony74b1cfc2011-10-06 12:44:16 +00001120 if (LocaleCompare("quality",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001121 {
anthony72feaa62012-01-17 06:46:23 +00001122 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001123 image_info->quality=UndefinedCompressionQuality;
anthony72feaa62012-01-17 06:46:23 +00001124 if (IfSetOption)
1125 image_info->quality=StringToUnsignedLong(arg);
anthony805a2d42011-09-25 08:25:12 +00001126 break;
1127 }
anthonyafbaed72011-10-26 12:05:04 +00001128 if (LocaleCompare("quantize",option) == 0)
1129 {
anthony72feaa62012-01-17 06:46:23 +00001130 /* Just a set direct in quantize_info */
anthonyafbaed72011-10-26 12:05:04 +00001131 quantize_info->colorspace=UndefinedColorspace;
1132 if (IfSetOption)
1133 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthonydcf510d2011-10-30 13:51:40 +00001134 MagickColorspaceOptions,MagickFalse,arg);
anthonyafbaed72011-10-26 12:05:04 +00001135 break;
1136 }
anthony74b1cfc2011-10-06 12:44:16 +00001137 if (LocaleCompare("quiet",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001138 {
anthonydcf510d2011-10-30 13:51:40 +00001139 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001140 static WarningHandler
1141 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001142
anthonyafbaed72011-10-26 12:05:04 +00001143 WarningHandler
1144 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001145
anthonyafbaed72011-10-26 12:05:04 +00001146 if ( tmp != (WarningHandler) NULL)
1147 warning_handler = tmp; /* remember the old handler */
1148 if (!IfSetOption) /* set the old handler */
1149 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001150 break;
1151 }
1152 break;
1153 }
1154 case 'r':
1155 {
anthony74b1cfc2011-10-06 12:44:16 +00001156 if (LocaleCompare("red-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001157 {
anthonydcf510d2011-10-30 13:51:40 +00001158 /* Image chromaticity X,Y NB: Y=X if Y not defined
1159 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001160 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001161 */
anthony72feaa62012-01-17 06:46:23 +00001162 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001163 break;
1164 }
anthonyafbaed72011-10-26 12:05:04 +00001165 if (LocaleCompare("render",option) == 0)
1166 {
1167 /* draw_info only setting */
1168 draw_info->render= IfSetOption ? MagickFalse : MagickTrue;
1169 break;
1170 }
anthony805a2d42011-09-25 08:25:12 +00001171 break;
1172 }
1173 case 's':
1174 {
anthony74b1cfc2011-10-06 12:44:16 +00001175 if (LocaleCompare("sampling-factor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001176 {
anthonyafbaed72011-10-26 12:05:04 +00001177 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony72feaa62012-01-17 06:46:23 +00001178 (void) CloneString(&image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001179 break;
1180 }
anthony74b1cfc2011-10-06 12:44:16 +00001181 if (LocaleCompare("scene",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001182 {
anthony72feaa62012-01-17 06:46:23 +00001183 /* SyncImageSettings() used to set per-image attribute.
1184 What ??? Why ????
1185 */
1186 (void) SetImageOption(image_info,option,ArgOption(NULL));
1187 image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001188 break;
1189 }
anthony74b1cfc2011-10-06 12:44:16 +00001190 if (LocaleCompare("seed",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001191 {
anthonyafbaed72011-10-26 12:05:04 +00001192 SeedPseudoRandomGenerator(
anthonydcf510d2011-10-30 13:51:40 +00001193 IfSetOption ? (size_t) StringToUnsignedLong(arg)
anthonyafbaed72011-10-26 12:05:04 +00001194 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001195 break;
1196 }
anthony74b1cfc2011-10-06 12:44:16 +00001197 if (LocaleCompare("size",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001198 {
anthonyafbaed72011-10-26 12:05:04 +00001199 /* FUTURE: string in image_info -- convert to Option ???
1200 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001201 */
anthony72feaa62012-01-17 06:46:23 +00001202 (void) CloneString(&image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001203 break;
1204 }
1205 if (LocaleCompare("stretch",option) == 0)
1206 {
anthony72feaa62012-01-17 06:46:23 +00001207 draw_info->stretch=(StretchType) ParseCommandOption(
1208 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001209 break;
1210 }
anthony74b1cfc2011-10-06 12:44:16 +00001211 if (LocaleCompare("stroke",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001212 {
anthonyafbaed72011-10-26 12:05:04 +00001213 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001214 UPDATE: ensure stroke color is not destroyed is a pattern
1215 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001216 */
1217 const char
anthony72feaa62012-01-17 06:46:23 +00001218 *value;
1219
1220 MagickBooleanType
1221 status;
anthonyafbaed72011-10-26 12:05:04 +00001222
1223 ExceptionInfo
1224 *sans;
1225
anthonyfd706f92012-01-19 04:22:02 +00001226 PixelInfo
1227 color;
1228
anthony72feaa62012-01-17 06:46:23 +00001229 value = ArgOption("none");
anthonyafbaed72011-10-26 12:05:04 +00001230 (void) SetImageOption(image_info,option,value);
anthony72feaa62012-01-17 06:46:23 +00001231 if (draw_info->stroke_pattern != (Image *) NULL)
1232 draw_info->stroke_pattern=DestroyImage(draw_info->stroke_pattern);
1233
1234 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001235 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +00001236 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001237 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001238
anthonyafbaed72011-10-26 12:05:04 +00001239 if (status == MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00001240 draw_info->stroke_pattern=GetImageCache(image_info,value,exception);
1241 else
1242 draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001243 break;
1244 }
anthony74b1cfc2011-10-06 12:44:16 +00001245 if (LocaleCompare("strokewidth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001246 {
anthony72feaa62012-01-17 06:46:23 +00001247 (void) SetImageOption(image_info,option,ArgOption(NULL));
1248 draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1249 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001250 break;
1251 }
1252 if (LocaleCompare("style",option) == 0)
1253 {
anthony72feaa62012-01-17 06:46:23 +00001254 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1255 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001256 break;
1257 }
anthony74b1cfc2011-10-06 12:44:16 +00001258 if (LocaleCompare("synchronize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001259 {
anthony72feaa62012-01-17 06:46:23 +00001260 image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001261 break;
1262 }
1263 break;
1264 }
1265 case 't':
1266 {
anthony74b1cfc2011-10-06 12:44:16 +00001267 if (LocaleCompare("taint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001268 {
anthony72feaa62012-01-17 06:46:23 +00001269 /* SyncImageSettings() used to set per-image attribute. */
anthonyafbaed72011-10-26 12:05:04 +00001270 (void) SetImageOption(image_info,option,
1271 IfSetOption ? "true" : "false");
anthony805a2d42011-09-25 08:25:12 +00001272 break;
1273 }
anthony74b1cfc2011-10-06 12:44:16 +00001274 if (LocaleCompare("texture",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001275 {
anthonyafbaed72011-10-26 12:05:04 +00001276 /* FUTURE: move image_info string to option splay-tree */
anthony72feaa62012-01-17 06:46:23 +00001277 (void) CloneString(&image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001278 break;
1279 }
1280 if (LocaleCompare("tile",option) == 0)
1281 {
anthony72feaa62012-01-17 06:46:23 +00001282 draw_info->fill_pattern=IfSetOption
1283 ?GetImageCache(image_info,arg,exception)
1284 :DestroyImage(draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001285 break;
1286 }
anthony74b1cfc2011-10-06 12:44:16 +00001287 if (LocaleCompare("tile-offset",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001288 {
anthony72feaa62012-01-17 06:46:23 +00001289 /* SyncImageSettings() used to set per-image attribute. ??? */
1290 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001291 break;
1292 }
anthony74b1cfc2011-10-06 12:44:16 +00001293 if (LocaleCompare("transparent-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001294 {
anthonyafbaed72011-10-26 12:05:04 +00001295 /* FUTURE: both image_info attribute & ImageOption in use!
1296 image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001297 SyncImageSettings() used to set per-image attribute.
1298
anthonyafbaed72011-10-26 12:05:04 +00001299 Note that +transparent-color, means fall-back to image
1300 attribute so ImageOption is deleted, not set to a default.
1301 */
anthony72feaa62012-01-17 06:46:23 +00001302 (void) SetImageOption(image_info,option,ArgOption(NULL));
1303 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1304 &image_info->transparent_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001305 break;
1306 }
anthony31f1bf72012-01-30 12:37:22 +00001307 if (LocaleCompare("treedepth",option) == 0)
1308 {
1309 (void) SetImageOption(image_info,option,ArgOption(NULL));
1310 quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1311 break;
1312 }
anthony74b1cfc2011-10-06 12:44:16 +00001313 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001314 {
anthony72feaa62012-01-17 06:46:23 +00001315 /* SyncImageSettings() used to set per-image attribute. */
1316 (void) SetImageOption(image_info,option,ArgOption(NULL));
1317 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1318 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001319 break;
1320 }
1321 break;
1322 }
1323 case 'u':
1324 {
anthony74b1cfc2011-10-06 12:44:16 +00001325 if (LocaleCompare("undercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001326 {
anthony72feaa62012-01-17 06:46:23 +00001327 (void) SetImageOption(image_info,option,ArgOption(NULL));
1328 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1329 &draw_info->undercolor,exception);
anthony805a2d42011-09-25 08:25:12 +00001330 break;
1331 }
anthony74b1cfc2011-10-06 12:44:16 +00001332 if (LocaleCompare("units",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001333 {
anthony72feaa62012-01-17 06:46:23 +00001334 /* SyncImageSettings() used to set per-image attribute.
1335 Should this effect draw_info X and Y resolution?
1336 FUTURE: this probably should be part of the density setting
1337 */
1338 (void) SetImageOption(image_info,option,ArgOption(NULL));
1339 image_info->units=(ResolutionType) ParseCommandOption(
1340 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001341 break;
1342 }
1343 break;
1344 }
1345 case 'v':
1346 {
anthony74b1cfc2011-10-06 12:44:16 +00001347 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001348 {
anthonyab3a50c2011-10-27 11:48:57 +00001349 /* FUTURE: Also an image artifact, set in Simple Operators.
1350 But artifact is only used in verbose output.
1351 */
anthony31f1bf72012-01-30 12:37:22 +00001352 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001353 image_info->verbose= ArgBoolean;
anthonyab3a50c2011-10-27 11:48:57 +00001354 image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001355 break;
1356 }
anthony74b1cfc2011-10-06 12:44:16 +00001357 if (LocaleCompare("view",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001358 {
anthony72feaa62012-01-17 06:46:23 +00001359 /* FUTURE: Convert from image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001360 Only used by coder FPX
1361 */
anthony72feaa62012-01-17 06:46:23 +00001362 (void) CloneString(&image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001363 break;
1364 }
anthony74b1cfc2011-10-06 12:44:16 +00001365 if (LocaleCompare("virtual-pixel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001366 {
anthonyfd706f92012-01-19 04:22:02 +00001367 /* SyncImageSettings() used to set per-image attribute.
1368 This is VERY deep in the image caching structure.
1369 */
anthony72feaa62012-01-17 06:46:23 +00001370 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001371 break;
1372 }
1373 break;
1374 }
1375 case 'w':
1376 {
anthonydcf510d2011-10-30 13:51:40 +00001377 if (LocaleCompare("weight",option) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001378 {
anthony72feaa62012-01-17 06:46:23 +00001379 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001380 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001381 */
anthony72feaa62012-01-17 06:46:23 +00001382 if (!IfSetOption)
1383 break;
anthonydcf510d2011-10-30 13:51:40 +00001384 draw_info->weight=StringToUnsignedLong(arg);
1385 if (LocaleCompare(arg,"all") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001386 draw_info->weight=0;
anthonydcf510d2011-10-30 13:51:40 +00001387 if (LocaleCompare(arg,"bold") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001388 draw_info->weight=700;
anthonydcf510d2011-10-30 13:51:40 +00001389 if (LocaleCompare(arg,"bolder") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001390 if (draw_info->weight <= 800)
1391 draw_info->weight+=100;
anthonydcf510d2011-10-30 13:51:40 +00001392 if (LocaleCompare(arg,"lighter") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001393 if (draw_info->weight >= 100)
1394 draw_info->weight-=100;
anthonydcf510d2011-10-30 13:51:40 +00001395 if (LocaleCompare(arg,"normal") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001396 draw_info->weight=400;
1397 break;
1398 }
anthony74b1cfc2011-10-06 12:44:16 +00001399 if (LocaleCompare("white-point",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001400 {
anthony72feaa62012-01-17 06:46:23 +00001401 /* Used as a image chromaticity setting
1402 SyncImageSettings() used to set per-image attribute.
1403 */
1404 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001405 break;
1406 }
1407 break;
1408 }
1409 default:
1410 break;
1411 }
anthonyfd706f92012-01-19 04:22:02 +00001412#undef image_info
1413#undef draw_info
1414#undef quantize_info
1415#undef exception
1416#undef IfSetOption
1417#undef ArgOption
1418#undef ArgBoolean
1419
anthony31f1bf72012-01-30 12:37:22 +00001420 return;
anthony805a2d42011-09-25 08:25:12 +00001421}
1422
1423/*
1424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1425% %
1426% %
1427% %
anthony31f1bf72012-01-30 12:37:22 +00001428+ 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 +00001429% %
1430% %
1431% %
1432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433%
anthony31f1bf72012-01-30 12:37:22 +00001434% WandSimpleOperatorImages() applys one simple image operation given to all
1435% the images in the current wand, with the settings that are saved in the
1436% CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001437%
1438% It is assumed that any per-image settings are up-to-date with respect to
1439% extra settings that have been saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001440%
anthonyd1447672012-01-19 05:33:53 +00001441% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001442%
anthony31f1bf72012-01-30 12:37:22 +00001443% void WandSimpleOperatorImages(MagickWand *wand,
anthonyfd706f92012-01-19 04:22:02 +00001444% const MagickBooleanType plus_alt_op, const char *option,
1445% const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001446%
1447% A description of each parameter follows:
1448%
anthonydcf510d2011-10-30 13:51:40 +00001449% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00001450%
anthonyfd706f92012-01-19 04:22:02 +00001451% o plus_alt_op: request the 'plus' or alturnative form of the operation
anthony805a2d42011-09-25 08:25:12 +00001452%
anthonyfd706f92012-01-19 04:22:02 +00001453% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001454%
anthonyfd706f92012-01-19 04:22:02 +00001455% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001456%
anthony31f1bf72012-01-30 12:37:22 +00001457% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001458%
anthony31f1bf72012-01-30 12:37:22 +00001459% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001460%
anthony36a8c2c2012-02-10 00:08:44 +00001461% WandSimpleOperatorImages(wand, MagickFalse,"crop","100x100+20+30",NULL);
1462% WandSimpleOperatorImages(wand, MagickTrue, "repage",NULL,NULL);
1463% WandSimpleOperatorImages(wand, MagickTrue, "distort","SRT","45");
anthony31f1bf72012-01-30 12:37:22 +00001464% if ( wand->exception->severity != UndefinedException ) {
1465% CatchException(exception);
1466% exit(1);
1467% }
anthonyfd706f92012-01-19 04:22:02 +00001468%
1469% Or for handling command line arguments EG: +/-option ["arg"]
anthonydcf510d2011-10-30 13:51:40 +00001470%
1471% argc,argv
1472% i=index in argv
1473%
1474% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
1475% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthony8b10b462012-02-08 12:32:44 +00001476% if ( flags & SimpleOperatorOptionFlag != 0 )
anthony36a8c2c2012-02-10 00:08:44 +00001477% WandSimpleOperatorImages(wand,
1478% ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
anthonyfd706f92012-01-19 04:22:02 +00001479% count>=1 ? argv[i+1] : (char *)NULL,
1480% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001481% i += count+1;
1482%
anthony805a2d42011-09-25 08:25:12 +00001483*/
anthony31f1bf72012-01-30 12:37:22 +00001484
1485/*
1486 Internal subrountine to apply one simple image operation to the current
1487 image pointed to by the wand.
1488
1489 The image in the list may be modified in three different ways...
1490 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1491 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1492 * one image replace by a list of images (-separate and -crop only!)
1493
1494 In each case the result replaces the original image in the list, as well as
1495 the pointer to the modified image (last image added if replaced by a list
1496 of images) is returned.
1497
1498 As the image pointed to may be replaced, the first image in the list may
1499 also change. GetFirstImageInList() should be used by caller if they wish
1500 return the Image pointer to the first image in list.
1501*/
anthony36a8c2c2012-02-10 00:08:44 +00001502static void WandSimpleOperatorImage(MagickWand *wand,
1503 const MagickBooleanType plus_alt_op, const char *option,
1504 const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001505{
1506 Image *
1507 new_image;
1508
anthony805a2d42011-09-25 08:25:12 +00001509 GeometryInfo
1510 geometry_info;
1511
1512 RectangleInfo
1513 geometry;
1514
1515 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001516 flags;
1517
anthonyfd706f92012-01-19 04:22:02 +00001518#define image_info (wand->image_info)
1519#define draw_info (wand->draw_info)
1520#define quantize_info (wand->quantize_info)
anthony31f1bf72012-01-30 12:37:22 +00001521#define image (wand->images)
1522#define exception (wand->exception)
1523#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001524
anthony805a2d42011-09-25 08:25:12 +00001525 assert(image_info != (const ImageInfo *) NULL);
1526 assert(image_info->signature == MagickSignature);
anthony31f1bf72012-01-30 12:37:22 +00001527 assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
1528 assert(image != (Image *) NULL); /* there is an image */
1529 assert(image->signature == MagickSignature); /* and is a valid image */
anthonydcf510d2011-10-30 13:51:40 +00001530
1531 if (wand->debug != MagickFalse)
1532 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1533
anthony805a2d42011-09-25 08:25:12 +00001534 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001535
anthonydcf510d2011-10-30 13:51:40 +00001536 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001537
anthonyfd706f92012-01-19 04:22:02 +00001538 /* FUTURE: We may need somthing a little more optimized than this!
1539 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1540 */
anthony31f1bf72012-01-30 12:37:22 +00001541 (void) SyncImageSettings(image_info,image,exception);
anthonydcf510d2011-10-30 13:51:40 +00001542
1543 switch (*option)
anthony805a2d42011-09-25 08:25:12 +00001544 {
1545 case 'a':
1546 {
anthonydcf510d2011-10-30 13:51:40 +00001547 if (LocaleCompare("adaptive-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001548 {
anthonyfd706f92012-01-19 04:22:02 +00001549 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001550 if ((flags & SigmaValue) == 0)
1551 geometry_info.sigma=1.0;
1552 if ((flags & XiValue) == 0)
1553 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001554 new_image=AdaptiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001555 geometry_info.sigma,geometry_info.xi,exception);
1556 break;
1557 }
anthonydcf510d2011-10-30 13:51:40 +00001558 if (LocaleCompare("adaptive-resize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001559 {
anthony31f1bf72012-01-30 12:37:22 +00001560 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
1561 new_image=AdaptiveResizeImage(image,geometry.width,geometry.height,
anthonyfd706f92012-01-19 04:22:02 +00001562 exception);
anthony805a2d42011-09-25 08:25:12 +00001563 break;
1564 }
anthonydcf510d2011-10-30 13:51:40 +00001565 if (LocaleCompare("adaptive-sharpen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001566 {
anthonyfd706f92012-01-19 04:22:02 +00001567 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001568 if ((flags & SigmaValue) == 0)
1569 geometry_info.sigma=1.0;
1570 if ((flags & XiValue) == 0)
1571 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001572 new_image=AdaptiveSharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001573 geometry_info.sigma,geometry_info.xi,exception);
1574 break;
1575 }
anthonydcf510d2011-10-30 13:51:40 +00001576 if (LocaleCompare("alpha",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001577 {
1578 AlphaChannelType
1579 alpha_type;
1580
anthony805a2d42011-09-25 08:25:12 +00001581 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
anthonyfd706f92012-01-19 04:22:02 +00001582 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00001583 (void) SetImageAlphaChannel(image,alpha_type,exception);
anthony805a2d42011-09-25 08:25:12 +00001584 break;
1585 }
anthonydcf510d2011-10-30 13:51:40 +00001586 if (LocaleCompare("annotate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001587 {
1588 char
1589 *text,
1590 geometry[MaxTextExtent];
1591
anthony805a2d42011-09-25 08:25:12 +00001592 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001593 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001594 if ((flags & SigmaValue) == 0)
1595 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00001596 text=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00001597 exception);
1598 if (text == (char *) NULL)
1599 break;
1600 (void) CloneString(&draw_info->text,text);
1601 text=DestroyString(text);
1602 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1603 geometry_info.xi,geometry_info.psi);
1604 (void) CloneString(&draw_info->geometry,geometry);
1605 draw_info->affine.sx=cos(DegreesToRadians(
1606 fmod(geometry_info.rho,360.0)));
1607 draw_info->affine.rx=sin(DegreesToRadians(
1608 fmod(geometry_info.rho,360.0)));
1609 draw_info->affine.ry=(-sin(DegreesToRadians(
1610 fmod(geometry_info.sigma,360.0))));
1611 draw_info->affine.sy=cos(DegreesToRadians(
1612 fmod(geometry_info.sigma,360.0)));
anthony31f1bf72012-01-30 12:37:22 +00001613 (void) AnnotateImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00001614 GetAffineMatrix(&draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001615 break;
1616 }
anthonydcf510d2011-10-30 13:51:40 +00001617 if (LocaleCompare("auto-gamma",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001618 {
anthony31f1bf72012-01-30 12:37:22 +00001619 (void) AutoGammaImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001620 break;
1621 }
anthonydcf510d2011-10-30 13:51:40 +00001622 if (LocaleCompare("auto-level",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001623 {
anthony31f1bf72012-01-30 12:37:22 +00001624 (void) AutoLevelImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001625 break;
1626 }
anthonydcf510d2011-10-30 13:51:40 +00001627 if (LocaleCompare("auto-orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001628 {
anthony31f1bf72012-01-30 12:37:22 +00001629 switch (image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001630 {
1631 case TopRightOrientation:
1632 {
anthony31f1bf72012-01-30 12:37:22 +00001633 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001634 break;
1635 }
1636 case BottomRightOrientation:
1637 {
anthony31f1bf72012-01-30 12:37:22 +00001638 new_image=RotateImage(image,180.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001639 break;
1640 }
1641 case BottomLeftOrientation:
1642 {
anthony31f1bf72012-01-30 12:37:22 +00001643 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001644 break;
1645 }
1646 case LeftTopOrientation:
1647 {
anthony31f1bf72012-01-30 12:37:22 +00001648 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001649 break;
1650 }
1651 case RightTopOrientation:
1652 {
anthony31f1bf72012-01-30 12:37:22 +00001653 new_image=RotateImage(image,90.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001654 break;
1655 }
1656 case RightBottomOrientation:
1657 {
anthony31f1bf72012-01-30 12:37:22 +00001658 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001659 break;
1660 }
1661 case LeftBottomOrientation:
1662 {
anthony31f1bf72012-01-30 12:37:22 +00001663 new_image=RotateImage(image,270.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001664 break;
1665 }
1666 default:
1667 break;
1668 }
1669 if (new_image != (Image *) NULL)
1670 new_image->orientation=TopLeftOrientation;
1671 break;
1672 }
1673 break;
1674 }
1675 case 'b':
1676 {
anthonydcf510d2011-10-30 13:51:40 +00001677 if (LocaleCompare("black-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001678 {
anthony31f1bf72012-01-30 12:37:22 +00001679 (void) BlackThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001680 break;
1681 }
anthonydcf510d2011-10-30 13:51:40 +00001682 if (LocaleCompare("blue-shift",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001683 {
anthony805a2d42011-09-25 08:25:12 +00001684 geometry_info.rho=1.5;
anthonyfd706f92012-01-19 04:22:02 +00001685 if (plus_alt_op == MagickFalse)
1686 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00001687 new_image=BlueShiftImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00001688 break;
1689 }
anthonydcf510d2011-10-30 13:51:40 +00001690 if (LocaleCompare("blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001691 {
anthony74b1cfc2011-10-06 12:44:16 +00001692 /* FUTURE: use of "bias" in a blur is non-sensible */
anthonyfd706f92012-01-19 04:22:02 +00001693 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001694 if ((flags & SigmaValue) == 0)
1695 geometry_info.sigma=1.0;
1696 if ((flags & XiValue) == 0)
1697 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001698 new_image=BlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001699 geometry_info.sigma,geometry_info.xi,exception);
1700 break;
1701 }
anthonydcf510d2011-10-30 13:51:40 +00001702 if (LocaleCompare("border",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001703 {
anthony31f1bf72012-01-30 12:37:22 +00001704 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001705 compose;
1706
1707 const char*
anthony5f867ae2011-10-09 10:28:34 +00001708 value;
1709
1710 value=GetImageOption(image_info,"compose");
1711 if (value != (const char *) NULL)
1712 compose=(CompositeOperator) ParseCommandOption(
1713 MagickComposeOptions,MagickFalse,value);
1714 else
1715 compose=OverCompositeOp; /* use Over not image->compose */
1716
anthony31f1bf72012-01-30 12:37:22 +00001717 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001718 if ((flags & SigmaValue) == 0)
1719 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00001720 new_image=BorderImage(image,&geometry,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00001721 break;
1722 }
anthonydcf510d2011-10-30 13:51:40 +00001723 if (LocaleCompare("brightness-contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001724 {
1725 double
1726 brightness,
1727 contrast;
1728
1729 GeometryInfo
1730 geometry_info;
1731
1732 MagickStatusType
1733 flags;
1734
anthonyfd706f92012-01-19 04:22:02 +00001735 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001736 brightness=geometry_info.rho;
1737 contrast=0.0;
1738 if ((flags & SigmaValue) != 0)
1739 contrast=geometry_info.sigma;
anthony31f1bf72012-01-30 12:37:22 +00001740 (void) BrightnessContrastImage(image,brightness,contrast,
anthony805a2d42011-09-25 08:25:12 +00001741 exception);
anthony805a2d42011-09-25 08:25:12 +00001742 break;
1743 }
1744 break;
1745 }
1746 case 'c':
1747 {
anthonydcf510d2011-10-30 13:51:40 +00001748 if (LocaleCompare("cdl",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001749 {
1750 char
1751 *color_correction_collection;
1752
1753 /*
1754 Color correct with a color decision list.
1755 */
anthonyfd706f92012-01-19 04:22:02 +00001756 color_correction_collection=FileToString(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00001757 if (color_correction_collection == (char *) NULL)
1758 break;
anthony31f1bf72012-01-30 12:37:22 +00001759 (void) ColorDecisionListImage(image,color_correction_collection,
anthony805a2d42011-09-25 08:25:12 +00001760 exception);
anthony805a2d42011-09-25 08:25:12 +00001761 break;
1762 }
anthonydcf510d2011-10-30 13:51:40 +00001763 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001764 {
anthonyfd706f92012-01-19 04:22:02 +00001765 /* The "channel" setting has already been set
anthonyd1447672012-01-19 05:33:53 +00001766 FUTURE: This probably should be part of WandSettingOptionInfo()
anthonyfd706f92012-01-19 04:22:02 +00001767 or SyncImageSettings().
1768 */
anthony31f1bf72012-01-30 12:37:22 +00001769 SetPixelChannelMapMask(image,image_info->channel);
anthony805a2d42011-09-25 08:25:12 +00001770 break;
1771 }
anthonydcf510d2011-10-30 13:51:40 +00001772 if (LocaleCompare("charcoal",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001773 {
anthonyfd706f92012-01-19 04:22:02 +00001774 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001775 if ((flags & SigmaValue) == 0)
1776 geometry_info.sigma=1.0;
1777 if ((flags & XiValue) == 0)
1778 geometry_info.xi=1.0;
anthony31f1bf72012-01-30 12:37:22 +00001779 new_image=CharcoalImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001780 geometry_info.sigma,geometry_info.xi,exception);
1781 break;
1782 }
anthonydcf510d2011-10-30 13:51:40 +00001783 if (LocaleCompare("chop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001784 {
anthony31f1bf72012-01-30 12:37:22 +00001785 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
1786 new_image=ChopImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001787 break;
1788 }
anthonydcf510d2011-10-30 13:51:40 +00001789 if (LocaleCompare("clamp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001790 {
anthony31f1bf72012-01-30 12:37:22 +00001791 (void) ClampImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001792 break;
1793 }
anthonydcf510d2011-10-30 13:51:40 +00001794 if (LocaleCompare("clip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001795 {
anthonyfd706f92012-01-19 04:22:02 +00001796 if (plus_alt_op == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001797 (void) ClipImage(image,exception);
anthonyfd706f92012-01-19 04:22:02 +00001798 else /* "+clip" remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001799 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001800 break;
1801 }
anthonydcf510d2011-10-30 13:51:40 +00001802 if (LocaleCompare("clip-mask",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001803 {
1804 CacheView
1805 *mask_view;
1806
1807 Image
1808 *mask_image;
1809
1810 register Quantum
1811 *restrict q;
1812
1813 register ssize_t
1814 x;
1815
1816 ssize_t
1817 y;
1818
anthonyfd706f92012-01-19 04:22:02 +00001819 if (plus_alt_op != MagickFalse)
1820 { /* "+clip-mask" Remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001821 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001822 break;
1823 }
anthonyfd706f92012-01-19 04:22:02 +00001824 mask_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001825 if (mask_image == (Image *) NULL)
1826 break;
anthonyfd706f92012-01-19 04:22:02 +00001827 if (SetImageStorageClass(mask_image,DirectClass,exception)
1828 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001829 break;
1830 /* Create a write mask from clip-mask image */
anthonyfd706f92012-01-19 04:22:02 +00001831 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001832 mask_view=AcquireCacheView(mask_image);
1833 for (y=0; y < (ssize_t) mask_image->rows; y++)
1834 {
1835 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1836 exception);
1837 if (q == (Quantum *) NULL)
1838 break;
1839 for (x=0; x < (ssize_t) mask_image->columns; x++)
1840 {
1841 if (mask_image->matte == MagickFalse)
1842 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1843 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1844 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1845 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1846 q+=GetPixelChannels(mask_image);
1847 }
1848 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1849 break;
1850 }
anthonyfd706f92012-01-19 04:22:02 +00001851 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001852 mask_view=DestroyCacheView(mask_view);
1853 mask_image->matte=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00001854 (void) SetImageMask(image,mask_image,exception);
anthony805a2d42011-09-25 08:25:12 +00001855 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001856 break;
1857 }
anthonydcf510d2011-10-30 13:51:40 +00001858 if (LocaleCompare("clip-path",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001859 {
anthony31f1bf72012-01-30 12:37:22 +00001860 (void) ClipImagePath(image,arg1,
anthonyfd706f92012-01-19 04:22:02 +00001861 (MagickBooleanType)(!(int)plus_alt_op),exception);
anthony805a2d42011-09-25 08:25:12 +00001862 break;
1863 }
anthonydcf510d2011-10-30 13:51:40 +00001864 if (LocaleCompare("colorize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001865 {
anthony31f1bf72012-01-30 12:37:22 +00001866 new_image=ColorizeImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00001867 break;
1868 }
anthonydcf510d2011-10-30 13:51:40 +00001869 if (LocaleCompare("color-matrix",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001870 {
1871 KernelInfo
1872 *kernel;
1873
anthonyfd706f92012-01-19 04:22:02 +00001874 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001875 if (kernel == (KernelInfo *) NULL)
1876 break;
anthony31f1bf72012-01-30 12:37:22 +00001877 new_image=ColorMatrixImage(image,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00001878 kernel=DestroyKernelInfo(kernel);
1879 break;
1880 }
anthonydcf510d2011-10-30 13:51:40 +00001881 if (LocaleCompare("colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001882 {
anthonyfd706f92012-01-19 04:22:02 +00001883 /* Reduce the number of colors in the image.
1884 FUTURE: also provide 'plus version with image 'color counts'
1885 */
1886 quantize_info->number_colors=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00001887 if (quantize_info->number_colors == 0)
1888 break;
anthony31f1bf72012-01-30 12:37:22 +00001889 if ((image->storage_class == DirectClass) ||
1890 image->colors > quantize_info->number_colors)
1891 (void) QuantizeImage(quantize_info,image,exception);
anthony805a2d42011-09-25 08:25:12 +00001892 else
anthony31f1bf72012-01-30 12:37:22 +00001893 (void) CompressImageColormap(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001894 break;
1895 }
anthonydcf510d2011-10-30 13:51:40 +00001896 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001897 {
anthony31f1bf72012-01-30 12:37:22 +00001898 /* WARNING: this is both a image_info setting (already done)
1899 and a operator to change image colorspace.
1900
1901 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00001902 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00001903
anthonyd2cdc862011-10-07 14:07:17 +00001904 Note that +colorspace sets "undefined" or no effect on
1905 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00001906 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00001907 */
anthony31f1bf72012-01-30 12:37:22 +00001908 (void) TransformImageColorspace(image,
1909 plus_alt_op ? RGBColorspace : image_info->colorspace,
anthony6613bf32011-10-15 07:24:44 +00001910 exception);
anthony805a2d42011-09-25 08:25:12 +00001911 break;
1912 }
anthonydcf510d2011-10-30 13:51:40 +00001913 if (LocaleCompare("contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001914 {
anthony31f1bf72012-01-30 12:37:22 +00001915 (void) ContrastImage(image,
anthonyfd706f92012-01-19 04:22:02 +00001916 (MagickBooleanType)(!(int)plus_alt_op),exception);
anthony805a2d42011-09-25 08:25:12 +00001917 break;
1918 }
anthonydcf510d2011-10-30 13:51:40 +00001919 if (LocaleCompare("contrast-stretch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001920 {
1921 double
1922 black_point,
1923 white_point;
1924
1925 MagickStatusType
1926 flags;
1927
anthonyfd706f92012-01-19 04:22:02 +00001928 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001929 black_point=geometry_info.rho;
1930 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
1931 black_point;
1932 if ((flags & PercentValue) != 0)
1933 {
anthony31f1bf72012-01-30 12:37:22 +00001934 black_point*=(double) image->columns*image->rows/100.0;
1935 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00001936 }
anthony31f1bf72012-01-30 12:37:22 +00001937 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00001938 white_point;
anthony31f1bf72012-01-30 12:37:22 +00001939 (void) ContrastStretchImage(image,black_point,white_point,
anthony805a2d42011-09-25 08:25:12 +00001940 exception);
anthony805a2d42011-09-25 08:25:12 +00001941 break;
1942 }
anthonydcf510d2011-10-30 13:51:40 +00001943 if (LocaleCompare("convolve",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001944 {
1945 KernelInfo
1946 *kernel_info;
1947
anthonyfd706f92012-01-19 04:22:02 +00001948 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001949 if (kernel_info == (KernelInfo *) NULL)
1950 break;
anthony31f1bf72012-01-30 12:37:22 +00001951 kernel_info->bias=image->bias;
1952 new_image=ConvolveImage(image,kernel_info,exception);
anthony805a2d42011-09-25 08:25:12 +00001953 kernel_info=DestroyKernelInfo(kernel_info);
1954 break;
1955 }
anthonydcf510d2011-10-30 13:51:40 +00001956 if (LocaleCompare("crop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001957 {
anthony31f1bf72012-01-30 12:37:22 +00001958 /* WARNING: This can generate multiple images! */
1959 new_image=CropImageToTiles(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001960 break;
1961 }
anthonydcf510d2011-10-30 13:51:40 +00001962 if (LocaleCompare("cycle",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001963 {
anthony31f1bf72012-01-30 12:37:22 +00001964 (void) CycleColormapImage(image,(ssize_t) StringToLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00001965 exception);
1966 break;
1967 }
1968 break;
1969 }
1970 case 'd':
1971 {
anthonydcf510d2011-10-30 13:51:40 +00001972 if (LocaleCompare("decipher",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001973 {
1974 StringInfo
1975 *passkey;
1976
anthonyfd706f92012-01-19 04:22:02 +00001977 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00001978 if (passkey != (StringInfo *) NULL)
1979 {
anthony31f1bf72012-01-30 12:37:22 +00001980 (void) PasskeyDecipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00001981 passkey=DestroyStringInfo(passkey);
1982 }
1983 break;
1984 }
anthonydcf510d2011-10-30 13:51:40 +00001985 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001986 {
anthonydcf510d2011-10-30 13:51:40 +00001987 /* The image_info->depth setting has already been set
1988 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00001989
anthonydcf510d2011-10-30 13:51:40 +00001990 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
1991 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00001992
anthonyfd706f92012-01-19 04:22:02 +00001993 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00001994 */
anthony31f1bf72012-01-30 12:37:22 +00001995 (void) SetImageDepth(image,image_info->depth,exception);
anthony805a2d42011-09-25 08:25:12 +00001996 break;
1997 }
anthonydcf510d2011-10-30 13:51:40 +00001998 if (LocaleCompare("deskew",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001999 {
2000 double
2001 threshold;
2002
anthonyfd706f92012-01-19 04:22:02 +00002003 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002004 threshold=40.0*QuantumRange/100.0;
2005 else
anthonyfd706f92012-01-19 04:22:02 +00002006 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002007 new_image=DeskewImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002008 break;
2009 }
anthonydcf510d2011-10-30 13:51:40 +00002010 if (LocaleCompare("despeckle",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002011 {
anthony31f1bf72012-01-30 12:37:22 +00002012 new_image=DespeckleImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002013 break;
2014 }
anthonydcf510d2011-10-30 13:51:40 +00002015 if (LocaleCompare("distort",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002016 {
2017 char
2018 *args,
2019 token[MaxTextExtent];
2020
2021 const char
2022 *p;
2023
2024 DistortImageMethod
2025 method;
2026
2027 double
2028 *arguments;
2029
2030 register ssize_t
2031 x;
2032
2033 size_t
2034 number_arguments;
2035
anthony805a2d42011-09-25 08:25:12 +00002036 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002037 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002038 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002039 {
anthony80c37752012-01-16 01:03:11 +00002040 double
2041 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002042 /* Special Case - Argument is actually a resize geometry!
2043 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002044 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002045 */
anthony31f1bf72012-01-30 12:37:22 +00002046 (void) ParseRegionGeometry(image,arg2,&geometry,
anthony80c37752012-01-16 01:03:11 +00002047 exception);
2048 resize_args[0]=(double) geometry.width;
2049 resize_args[1]=(double) geometry.height;
anthony31f1bf72012-01-30 12:37:22 +00002050 new_image=DistortImage(image,method,(size_t)2,
anthony80c37752012-01-16 01:03:11 +00002051 resize_args,MagickTrue,exception);
anthony805a2d42011-09-25 08:25:12 +00002052 break;
2053 }
anthonyfd706f92012-01-19 04:22:02 +00002054 /* handle percent arguments */
anthony31f1bf72012-01-30 12:37:22 +00002055 args=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002056 exception);
2057 if (args == (char *) NULL)
2058 break;
anthonyfd706f92012-01-19 04:22:02 +00002059 /* convert arguments into an array of doubles
2060 FUTURE: make this a separate function.
2061 Also make use of new 'sentinal' feature to avoid need for
2062 tokenization.
2063 */
anthony805a2d42011-09-25 08:25:12 +00002064 p=(char *) args;
2065 for (x=0; *p != '\0'; x++)
2066 {
2067 GetMagickToken(p,&p,token);
2068 if (*token == ',')
2069 GetMagickToken(p,&p,token);
2070 }
2071 number_arguments=(size_t) x;
2072 arguments=(double *) AcquireQuantumMemory(number_arguments,
2073 sizeof(*arguments));
2074 if (arguments == (double *) NULL)
2075 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002076 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002077 (void) ResetMagickMemory(arguments,0,number_arguments*
2078 sizeof(*arguments));
2079 p=(char *) args;
2080 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2081 {
2082 GetMagickToken(p,&p,token);
2083 if (*token == ',')
2084 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002085 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002086 }
2087 args=DestroyString(args);
anthony31f1bf72012-01-30 12:37:22 +00002088 new_image=DistortImage(image,method,number_arguments,arguments,
anthonyfd706f92012-01-19 04:22:02 +00002089 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002090 arguments=(double *) RelinquishMagickMemory(arguments);
2091 break;
2092 }
anthonydcf510d2011-10-30 13:51:40 +00002093 if (LocaleCompare("draw",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002094 {
anthonyfd706f92012-01-19 04:22:02 +00002095 (void) CloneString(&draw_info->primitive,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002096 (void) DrawImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00002097 (void) CloneString(&draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002098 break;
2099 }
2100 break;
2101 }
2102 case 'e':
2103 {
anthonydcf510d2011-10-30 13:51:40 +00002104 if (LocaleCompare("edge",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002105 {
anthonyfd706f92012-01-19 04:22:02 +00002106 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002107 if ((flags & SigmaValue) == 0)
2108 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002109 new_image=EdgeImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002110 geometry_info.sigma,exception);
2111 break;
2112 }
anthonydcf510d2011-10-30 13:51:40 +00002113 if (LocaleCompare("emboss",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002114 {
anthonyfd706f92012-01-19 04:22:02 +00002115 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002116 if ((flags & SigmaValue) == 0)
2117 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002118 new_image=EmbossImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002119 geometry_info.sigma,exception);
2120 break;
2121 }
anthonydcf510d2011-10-30 13:51:40 +00002122 if (LocaleCompare("encipher",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002123 {
2124 StringInfo
2125 *passkey;
2126
anthonyfd706f92012-01-19 04:22:02 +00002127 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002128 if (passkey != (StringInfo *) NULL)
2129 {
anthony31f1bf72012-01-30 12:37:22 +00002130 (void) PasskeyEncipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002131 passkey=DestroyStringInfo(passkey);
2132 }
2133 break;
2134 }
anthonydcf510d2011-10-30 13:51:40 +00002135 if (LocaleCompare("enhance",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002136 {
anthony31f1bf72012-01-30 12:37:22 +00002137 new_image=EnhanceImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002138 break;
2139 }
anthonydcf510d2011-10-30 13:51:40 +00002140 if (LocaleCompare("equalize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002141 {
anthony31f1bf72012-01-30 12:37:22 +00002142 (void) EqualizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002143 break;
2144 }
anthonydcf510d2011-10-30 13:51:40 +00002145 if (LocaleCompare("evaluate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002146 {
2147 double
2148 constant;
2149
2150 MagickEvaluateOperator
2151 op;
2152
anthony805a2d42011-09-25 08:25:12 +00002153 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002154 MagickEvaluateOptions,MagickFalse,arg1);
2155 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002156 (void) EvaluateImage(image,op,constant,exception);
anthony805a2d42011-09-25 08:25:12 +00002157 break;
2158 }
anthonydcf510d2011-10-30 13:51:40 +00002159 if (LocaleCompare("extent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002160 {
anthony31f1bf72012-01-30 12:37:22 +00002161 flags=ParseGravityGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002162 if (geometry.width == 0)
anthony31f1bf72012-01-30 12:37:22 +00002163 geometry.width=image->columns;
anthony805a2d42011-09-25 08:25:12 +00002164 if (geometry.height == 0)
anthony31f1bf72012-01-30 12:37:22 +00002165 geometry.height=image->rows;
2166 new_image=ExtentImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002167 break;
2168 }
2169 break;
2170 }
2171 case 'f':
2172 {
anthonydcf510d2011-10-30 13:51:40 +00002173 if (LocaleCompare("features",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002174 {
anthony31f1bf72012-01-30 12:37:22 +00002175 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2176 if (plus_alt_op != MagickFalse)
2177 {
2178 (void) DeleteImageArtifact(image,"identify:features");
2179 break;
2180 }
2181 (void) SetImageArtifact(image,"identify:features","true");
2182 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002183 break;
2184 }
anthonydcf510d2011-10-30 13:51:40 +00002185 if (LocaleCompare("flip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002186 {
anthony31f1bf72012-01-30 12:37:22 +00002187 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002188 break;
2189 }
anthonydcf510d2011-10-30 13:51:40 +00002190 if (LocaleCompare("flop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002191 {
anthony31f1bf72012-01-30 12:37:22 +00002192 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002193 break;
2194 }
anthonydcf510d2011-10-30 13:51:40 +00002195 if (LocaleCompare("floodfill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002196 {
2197 PixelInfo
2198 target;
2199
anthony31f1bf72012-01-30 12:37:22 +00002200 (void) ParsePageGeometry(image,arg1,&geometry,exception);
anthonyfd706f92012-01-19 04:22:02 +00002201 (void) QueryColorCompliance(arg2,AllCompliance,&target,exception);
anthony31f1bf72012-01-30 12:37:22 +00002202 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
anthonyfd706f92012-01-19 04:22:02 +00002203 geometry.y,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002204 break;
2205 }
anthonydcf510d2011-10-30 13:51:40 +00002206 if (LocaleCompare("frame",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002207 {
2208 FrameInfo
2209 frame_info;
2210
anthony31f1bf72012-01-30 12:37:22 +00002211 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002212 compose;
2213
2214 const char*
2215 value;
2216
2217 value=GetImageOption(image_info,"compose");
2218 if (value != (const char *) NULL)
2219 compose=(CompositeOperator) ParseCommandOption(
2220 MagickComposeOptions,MagickFalse,value);
2221 else
2222 compose=OverCompositeOp; /* use Over not image->compose */
2223
anthony31f1bf72012-01-30 12:37:22 +00002224 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002225 frame_info.width=geometry.width;
2226 frame_info.height=geometry.height;
2227 if ((flags & HeightValue) == 0)
2228 frame_info.height=geometry.width;
2229 frame_info.outer_bevel=geometry.x;
2230 frame_info.inner_bevel=geometry.y;
2231 frame_info.x=(ssize_t) frame_info.width;
2232 frame_info.y=(ssize_t) frame_info.height;
anthony31f1bf72012-01-30 12:37:22 +00002233 frame_info.width=image->columns+2*frame_info.width;
2234 frame_info.height=image->rows+2*frame_info.height;
2235 new_image=FrameImage(image,&frame_info,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00002236 break;
2237 }
anthonydcf510d2011-10-30 13:51:40 +00002238 if (LocaleCompare("function",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002239 {
2240 char
2241 *arguments,
2242 token[MaxTextExtent];
2243
2244 const char
2245 *p;
2246
2247 double
2248 *parameters;
2249
2250 MagickFunction
2251 function;
2252
2253 register ssize_t
2254 x;
2255
2256 size_t
2257 number_parameters;
2258
cristy947cb4c2011-10-20 18:41:46 +00002259 /*
2260 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002261 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002262 */
anthony805a2d42011-09-25 08:25:12 +00002263 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002264 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002265 arguments=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002266 exception);
2267 if (arguments == (char *) NULL)
2268 break;
2269 p=(char *) arguments;
2270 for (x=0; *p != '\0'; x++)
2271 {
2272 GetMagickToken(p,&p,token);
2273 if (*token == ',')
2274 GetMagickToken(p,&p,token);
2275 }
2276 number_parameters=(size_t) x;
2277 parameters=(double *) AcquireQuantumMemory(number_parameters,
2278 sizeof(*parameters));
2279 if (parameters == (double *) NULL)
2280 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002281 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002282 (void) ResetMagickMemory(parameters,0,number_parameters*
2283 sizeof(*parameters));
2284 p=(char *) arguments;
2285 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2286 {
2287 GetMagickToken(p,&p,token);
2288 if (*token == ',')
2289 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002290 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002291 }
2292 arguments=DestroyString(arguments);
anthony31f1bf72012-01-30 12:37:22 +00002293 (void) FunctionImage(image,function,number_parameters,parameters,
anthony805a2d42011-09-25 08:25:12 +00002294 exception);
2295 parameters=(double *) RelinquishMagickMemory(parameters);
2296 break;
2297 }
2298 break;
2299 }
2300 case 'g':
2301 {
anthonydcf510d2011-10-30 13:51:40 +00002302 if (LocaleCompare("gamma",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002303 {
anthony31f1bf72012-01-30 12:37:22 +00002304 if (plus_alt_op != MagickFalse)
2305 image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002306 else
anthony31f1bf72012-01-30 12:37:22 +00002307 (void) GammaImage(image,StringToDouble(arg1,(char **) NULL),
anthonyfd706f92012-01-19 04:22:02 +00002308 exception);
anthony805a2d42011-09-25 08:25:12 +00002309 break;
2310 }
anthonydcf510d2011-10-30 13:51:40 +00002311 if ((LocaleCompare("gaussian-blur",option) == 0) ||
2312 (LocaleCompare("gaussian",option) == 0))
anthony805a2d42011-09-25 08:25:12 +00002313 {
anthonyfd706f92012-01-19 04:22:02 +00002314 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002315 if ((flags & SigmaValue) == 0)
2316 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002317 new_image=GaussianBlurImage(image,geometry_info.rho,
cristyd89705a2012-01-20 02:52:24 +00002318 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002319 break;
2320 }
anthonydcf510d2011-10-30 13:51:40 +00002321 if (LocaleCompare("geometry",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002322 {
anthonyfd706f92012-01-19 04:22:02 +00002323 /*
anthony31f1bf72012-01-30 12:37:22 +00002324 Record Image offset for composition. (A Setting)
2325 Resize last image. (ListOperator)
2326 FUTURE: Why if no 'offset' does this resize ALL images?
2327 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002328 */
anthony31f1bf72012-01-30 12:37:22 +00002329 if (plus_alt_op != MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00002330 { /* remove the previous composition geometry offset! */
anthony31f1bf72012-01-30 12:37:22 +00002331 if (image->geometry != (char *) NULL)
2332 image->geometry=DestroyString(image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002333 break;
2334 }
anthony31f1bf72012-01-30 12:37:22 +00002335 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002336 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony31f1bf72012-01-30 12:37:22 +00002337 (void) CloneString(&image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002338 else
anthony31f1bf72012-01-30 12:37:22 +00002339 new_image=ResizeImage(image,geometry.width,geometry.height,
2340 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002341 break;
2342 }
anthony805a2d42011-09-25 08:25:12 +00002343 break;
2344 }
2345 case 'h':
2346 {
anthonydcf510d2011-10-30 13:51:40 +00002347 if (LocaleCompare("highlight-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002348 {
anthony31f1bf72012-01-30 12:37:22 +00002349 (void) SetImageArtifact(image,option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002350 break;
2351 }
2352 break;
2353 }
2354 case 'i':
2355 {
anthonydcf510d2011-10-30 13:51:40 +00002356 if (LocaleCompare("identify",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002357 {
anthony31f1bf72012-01-30 12:37:22 +00002358 const char
2359 *format,
anthony805a2d42011-09-25 08:25:12 +00002360 *text;
2361
anthony31f1bf72012-01-30 12:37:22 +00002362 format=GetImageOption(image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002363 if (format == (char *) NULL)
2364 {
anthony31f1bf72012-01-30 12:37:22 +00002365 (void) IdentifyImage(image,stdout,image_info->verbose,
anthony805a2d42011-09-25 08:25:12 +00002366 exception);
2367 break;
2368 }
anthony31f1bf72012-01-30 12:37:22 +00002369 text=InterpretImageProperties(image_info,image,format,exception);
anthony805a2d42011-09-25 08:25:12 +00002370 if (text == (char *) NULL)
2371 break;
2372 (void) fputs(text,stdout);
2373 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002374 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002375 break;
2376 }
anthonydcf510d2011-10-30 13:51:40 +00002377 if (LocaleCompare("implode",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002378 {
anthonyfd706f92012-01-19 04:22:02 +00002379 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002380 new_image=ImplodeImage(image,geometry_info.rho,
2381 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002382 break;
2383 }
anthonyfd706f92012-01-19 04:22:02 +00002384 if (LocaleCompare("interpolative-resize",option) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002385 {
anthony31f1bf72012-01-30 12:37:22 +00002386 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2387 new_image=InterpolativeResizeImage(image,geometry.width,
2388 geometry.height,image->interpolate,exception);
cristy947cb4c2011-10-20 18:41:46 +00002389 break;
2390 }
anthony805a2d42011-09-25 08:25:12 +00002391 break;
2392 }
2393 case 'l':
2394 {
anthonydcf510d2011-10-30 13:51:40 +00002395 if (LocaleCompare("lat",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002396 {
anthonyfd706f92012-01-19 04:22:02 +00002397 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002398 if ((flags & PercentValue) != 0)
2399 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002400 new_image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
2401 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2402 exception);
anthony805a2d42011-09-25 08:25:12 +00002403 break;
2404 }
anthonydcf510d2011-10-30 13:51:40 +00002405 if (LocaleCompare("level",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002406 {
2407 MagickRealType
2408 black_point,
2409 gamma,
2410 white_point;
2411
2412 MagickStatusType
2413 flags;
2414
anthonyfd706f92012-01-19 04:22:02 +00002415 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002416 black_point=geometry_info.rho;
2417 white_point=(MagickRealType) QuantumRange;
2418 if ((flags & SigmaValue) != 0)
2419 white_point=geometry_info.sigma;
2420 gamma=1.0;
2421 if ((flags & XiValue) != 0)
2422 gamma=geometry_info.xi;
2423 if ((flags & PercentValue) != 0)
2424 {
2425 black_point*=(MagickRealType) (QuantumRange/100.0);
2426 white_point*=(MagickRealType) (QuantumRange/100.0);
2427 }
2428 if ((flags & SigmaValue) == 0)
2429 white_point=(MagickRealType) QuantumRange-black_point;
anthony31f1bf72012-01-30 12:37:22 +00002430 if (plus_alt_op || ((flags & AspectValue) != 0))
2431 (void) LevelizeImage(image,black_point,white_point,gamma,
anthony805a2d42011-09-25 08:25:12 +00002432 exception);
2433 else
anthony31f1bf72012-01-30 12:37:22 +00002434 (void) LevelImage(image,black_point,white_point,gamma,
anthony805a2d42011-09-25 08:25:12 +00002435 exception);
anthony805a2d42011-09-25 08:25:12 +00002436 break;
2437 }
anthonydcf510d2011-10-30 13:51:40 +00002438 if (LocaleCompare("level-colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002439 {
2440 char
2441 token[MaxTextExtent];
2442
2443 const char
2444 *p;
2445
2446 PixelInfo
2447 black_point,
2448 white_point;
2449
anthonyfd706f92012-01-19 04:22:02 +00002450 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002451 GetMagickToken(p,&p,token); /* get black point color */
2452 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002453 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002454 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002455 else
cristy269c9412011-10-13 23:41:15 +00002456 (void) QueryColorCompliance("#000000",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002457 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002458 if (isalpha((int) token[0]) || (token[0] == '#'))
2459 GetMagickToken(p,&p,token);
2460 if (*token == '\0')
2461 white_point=black_point; /* set everything to that color */
2462 else
2463 {
2464 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2465 GetMagickToken(p,&p,token); /* Get white point color. */
2466 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002467 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002468 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002469 else
cristy269c9412011-10-13 23:41:15 +00002470 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002471 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002472 }
anthony31f1bf72012-01-30 12:37:22 +00002473 (void) LevelImageColors(image,&black_point,&white_point,
2474 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002475 break;
2476 }
anthonydcf510d2011-10-30 13:51:40 +00002477 if (LocaleCompare("linear-stretch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002478 {
2479 double
2480 black_point,
2481 white_point;
2482
2483 MagickStatusType
2484 flags;
2485
anthonyfd706f92012-01-19 04:22:02 +00002486 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002487 black_point=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002488 white_point=(MagickRealType) image->columns*image->rows;
anthony805a2d42011-09-25 08:25:12 +00002489 if ((flags & SigmaValue) != 0)
2490 white_point=geometry_info.sigma;
2491 if ((flags & PercentValue) != 0)
2492 {
anthony31f1bf72012-01-30 12:37:22 +00002493 black_point*=(double) image->columns*image->rows/100.0;
2494 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002495 }
2496 if ((flags & SigmaValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00002497 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002498 black_point;
anthony31f1bf72012-01-30 12:37:22 +00002499 (void) LinearStretchImage(image,black_point,white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002500 break;
2501 }
anthonydcf510d2011-10-30 13:51:40 +00002502 if (LocaleCompare("liquid-rescale",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002503 {
anthony31f1bf72012-01-30 12:37:22 +00002504 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002505 if ((flags & XValue) == 0)
2506 geometry.x=1;
2507 if ((flags & YValue) == 0)
2508 geometry.y=0;
anthony31f1bf72012-01-30 12:37:22 +00002509 new_image=LiquidRescaleImage(image,geometry.width,
anthony805a2d42011-09-25 08:25:12 +00002510 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2511 break;
2512 }
anthonydcf510d2011-10-30 13:51:40 +00002513 if (LocaleCompare("lowlight-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002514 {
anthony31f1bf72012-01-30 12:37:22 +00002515 (void) SetImageArtifact(image,option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002516 break;
2517 }
2518 break;
2519 }
2520 case 'm':
2521 {
anthonydcf510d2011-10-30 13:51:40 +00002522 if (LocaleCompare("map",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002523 {
2524 Image
2525 *remap_image;
2526
anthony31f1bf72012-01-30 12:37:22 +00002527 /* DEPRECIATED use -remap */
anthonyfd706f92012-01-19 04:22:02 +00002528 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002529 if (remap_image == (Image *) NULL)
2530 break;
anthony31f1bf72012-01-30 12:37:22 +00002531 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002532 remap_image=DestroyImage(remap_image);
2533 break;
2534 }
anthonydcf510d2011-10-30 13:51:40 +00002535 if (LocaleCompare("mask",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002536 {
2537 Image
2538 *mask;
2539
anthony31f1bf72012-01-30 12:37:22 +00002540 if (plus_alt_op != MagickFalse)
2541 { /* Remove a mask. */
2542 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002543 break;
2544 }
anthony31f1bf72012-01-30 12:37:22 +00002545 /* Set the image mask. */
anthonyfd706f92012-01-19 04:22:02 +00002546 mask=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002547 if (mask == (Image *) NULL)
2548 break;
anthony31f1bf72012-01-30 12:37:22 +00002549 (void) SetImageMask(image,mask,exception);
anthony805a2d42011-09-25 08:25:12 +00002550 mask=DestroyImage(mask);
2551 break;
2552 }
anthonydcf510d2011-10-30 13:51:40 +00002553 if (LocaleCompare("matte",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002554 {
anthony31f1bf72012-01-30 12:37:22 +00002555 /* DEPRECIATED */
2556 (void) SetImageAlphaChannel(image,plus_alt_op ?
2557 DeactivateAlphaChannel:SetAlphaChannel ,exception);
anthony805a2d42011-09-25 08:25:12 +00002558 break;
2559 }
anthonydcf510d2011-10-30 13:51:40 +00002560 if (LocaleCompare("mode",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002561 {
anthonyfd706f92012-01-19 04:22:02 +00002562 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002563 if ((flags & SigmaValue) == 0)
2564 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002565 new_image=StatisticImage(image,ModeStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002566 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2567 break;
2568 }
anthonydcf510d2011-10-30 13:51:40 +00002569 if (LocaleCompare("modulate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002570 {
anthony31f1bf72012-01-30 12:37:22 +00002571 (void) ModulateImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002572 break;
2573 }
anthonydcf510d2011-10-30 13:51:40 +00002574 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002575 {
anthony31f1bf72012-01-30 12:37:22 +00002576 (void) SetImageProgressMonitor(image, plus_alt_op?
2577 (MagickProgressMonitor) NULL:MonitorProgress,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002578 break;
2579 }
anthonydcf510d2011-10-30 13:51:40 +00002580 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002581 {
anthony31f1bf72012-01-30 12:37:22 +00002582 (void) SetImageType(image,BilevelType,exception);
anthony805a2d42011-09-25 08:25:12 +00002583 break;
2584 }
anthonydcf510d2011-10-30 13:51:40 +00002585 if (LocaleCompare("morphology",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002586 {
2587 char
2588 token[MaxTextExtent];
2589
2590 const char
2591 *p;
2592
2593 KernelInfo
2594 *kernel;
2595
2596 MorphologyMethod
2597 method;
2598
2599 ssize_t
2600 iterations;
2601
anthonyfd706f92012-01-19 04:22:02 +00002602 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002603 GetMagickToken(p,&p,token);
2604 method=(MorphologyMethod) ParseCommandOption(
2605 MagickMorphologyOptions,MagickFalse,token);
2606 iterations=1L;
2607 GetMagickToken(p,&p,token);
2608 if ((*p == ':') || (*p == ','))
2609 GetMagickToken(p,&p,token);
2610 if ((*p != '\0'))
2611 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002612 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002613 if (kernel == (KernelInfo *) NULL)
2614 {
2615 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002616 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002617 break;
2618 }
anthony31f1bf72012-01-30 12:37:22 +00002619 new_image=MorphologyImage(image,method,iterations,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00002620 kernel=DestroyKernelInfo(kernel);
2621 break;
2622 }
anthonydcf510d2011-10-30 13:51:40 +00002623 if (LocaleCompare("motion-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002624 {
anthonyfd706f92012-01-19 04:22:02 +00002625 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002626 if ((flags & SigmaValue) == 0)
2627 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002628 new_image=MotionBlurImage(image,geometry_info.rho,
2629 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2630 exception);
anthony805a2d42011-09-25 08:25:12 +00002631 break;
2632 }
2633 break;
2634 }
2635 case 'n':
2636 {
anthonydcf510d2011-10-30 13:51:40 +00002637 if (LocaleCompare("negate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002638 {
anthony31f1bf72012-01-30 12:37:22 +00002639 (void) NegateImage(image, plus_alt_op, exception);
anthony805a2d42011-09-25 08:25:12 +00002640 break;
2641 }
anthonydcf510d2011-10-30 13:51:40 +00002642 if (LocaleCompare("noise",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002643 {
anthony31f1bf72012-01-30 12:37:22 +00002644 if (plus_alt_op == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002645 {
anthonyfd706f92012-01-19 04:22:02 +00002646 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002647 if ((flags & SigmaValue) == 0)
2648 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002649 new_image=StatisticImage(image,NonpeakStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002650 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2651 }
2652 else
2653 {
2654 NoiseType
2655 noise;
2656
anthony31f1bf72012-01-30 12:37:22 +00002657 double
2658 attenuate;
2659
2660 const char*
2661 value;
2662
anthony805a2d42011-09-25 08:25:12 +00002663 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002664 MagickFalse,arg1),
2665
2666 value=GetImageOption(image_info,"attenuate");
2667 if (value != (const char *) NULL)
2668 attenuate=StringToDouble(value,(char **) NULL);
2669 else
2670 attenuate=1.0;
2671
2672 new_image=AddNoiseImage(image,noise,attenuate,exception);
anthony805a2d42011-09-25 08:25:12 +00002673 }
2674 break;
2675 }
anthonydcf510d2011-10-30 13:51:40 +00002676 if (LocaleCompare("normalize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002677 {
anthony31f1bf72012-01-30 12:37:22 +00002678 (void) NormalizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002679 break;
2680 }
2681 break;
2682 }
2683 case 'o':
2684 {
anthonydcf510d2011-10-30 13:51:40 +00002685 if (LocaleCompare("opaque",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002686 {
2687 PixelInfo
2688 target;
2689
anthony31f1bf72012-01-30 12:37:22 +00002690 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
2691 (void) OpaquePaintImage(image,&target,&draw_info->fill,plus_alt_op,
2692 exception);
anthony805a2d42011-09-25 08:25:12 +00002693 break;
2694 }
anthonydcf510d2011-10-30 13:51:40 +00002695 if (LocaleCompare("ordered-dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002696 {
anthony31f1bf72012-01-30 12:37:22 +00002697 (void) OrderedPosterizeImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002698 break;
2699 }
2700 break;
2701 }
2702 case 'p':
2703 {
anthonydcf510d2011-10-30 13:51:40 +00002704 if (LocaleCompare("paint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002705 {
anthonyfd706f92012-01-19 04:22:02 +00002706 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002707 new_image=OilPaintImage(image,geometry_info.rho,geometry_info.sigma,
2708 exception);
anthony805a2d42011-09-25 08:25:12 +00002709 break;
2710 }
anthonydcf510d2011-10-30 13:51:40 +00002711 if (LocaleCompare("polaroid",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002712 {
cristye9e3d382011-12-14 01:50:13 +00002713 const char
2714 *caption;
2715
anthony805a2d42011-09-25 08:25:12 +00002716 double
2717 angle;
2718
anthony31f1bf72012-01-30 12:37:22 +00002719 if (plus_alt_op != MagickFalse)
2720 {
2721 RandomInfo
2722 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002723
anthony31f1bf72012-01-30 12:37:22 +00002724 random_info=AcquireRandomInfo();
2725 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2726 random_info=DestroyRandomInfo(random_info);
2727 }
2728 else
anthony805a2d42011-09-25 08:25:12 +00002729 {
2730 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002731 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002732 angle=geometry_info.rho;
2733 }
anthony31f1bf72012-01-30 12:37:22 +00002734 caption=GetImageProperty(image,"caption",exception);
2735 new_image=PolaroidImage(image,draw_info,caption,angle,
2736 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002737 break;
2738 }
anthonydcf510d2011-10-30 13:51:40 +00002739 if (LocaleCompare("posterize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002740 {
anthony31f1bf72012-01-30 12:37:22 +00002741 (void) ParseGeometry(arg1,&geometry_info);
2742 (void) PosterizeImage(image,(size_t) geometry_info.rho,
2743 quantize_info->dither,exception);
anthony805a2d42011-09-25 08:25:12 +00002744 break;
2745 }
anthonydcf510d2011-10-30 13:51:40 +00002746 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002747 {
2748 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002749 preview_type;
anthony170fce92011-10-20 11:50:23 +00002750
anthony31f1bf72012-01-30 12:37:22 +00002751 /* FUTURE: should be a 'Genesis' option?
2752 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002753 */
anthony31f1bf72012-01-30 12:37:22 +00002754 preview_type=UndefinedPreview;
2755 if (plus_alt_op == MagickFalse)
2756 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2757 MagickFalse,arg1);
2758 new_image=PreviewImage(image,preview_type,exception);
anthony805a2d42011-09-25 08:25:12 +00002759 break;
2760 }
anthonydcf510d2011-10-30 13:51:40 +00002761 if (LocaleCompare("profile",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002762 {
2763 const char
2764 *name;
2765
2766 const StringInfo
2767 *profile;
2768
2769 Image
2770 *profile_image;
2771
2772 ImageInfo
2773 *profile_info;
2774
anthony31f1bf72012-01-30 12:37:22 +00002775 if (plus_alt_op != MagickFalse)
2776 { /* Remove a profile from the image. */
2777 (void) ProfileImage(image,arg1,(const unsigned char *)
cristy092d71c2011-10-14 18:01:29 +00002778 NULL,0,exception);
anthony805a2d42011-09-25 08:25:12 +00002779 break;
2780 }
anthony31f1bf72012-01-30 12:37:22 +00002781 /* Associate a profile with the image. */
anthony805a2d42011-09-25 08:25:12 +00002782 profile_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00002783 profile=GetImageProfile(image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002784 if (profile != (StringInfo *) NULL)
2785 profile_info->profile=(void *) CloneStringInfo(profile);
anthonyfd706f92012-01-19 04:22:02 +00002786 profile_image=GetImageCache(profile_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002787 profile_info=DestroyImageInfo(profile_info);
2788 if (profile_image == (Image *) NULL)
2789 {
2790 StringInfo
2791 *profile;
2792
2793 profile_info=CloneImageInfo(image_info);
anthonyfd706f92012-01-19 04:22:02 +00002794 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002795 MaxTextExtent);
2796 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2797 if (profile != (StringInfo *) NULL)
2798 {
anthony31f1bf72012-01-30 12:37:22 +00002799 (void) ProfileImage(image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002800 GetStringInfoDatum(profile),(size_t)
cristy092d71c2011-10-14 18:01:29 +00002801 GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002802 profile=DestroyStringInfo(profile);
2803 }
2804 profile_info=DestroyImageInfo(profile_info);
2805 break;
2806 }
2807 ResetImageProfileIterator(profile_image);
2808 name=GetNextImageProfile(profile_image);
2809 while (name != (const char *) NULL)
2810 {
2811 profile=GetImageProfile(profile_image,name);
2812 if (profile != (StringInfo *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002813 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
cristy092d71c2011-10-14 18:01:29 +00002814 (size_t) GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002815 name=GetNextImageProfile(profile_image);
2816 }
2817 profile_image=DestroyImage(profile_image);
2818 break;
2819 }
2820 break;
2821 }
anthony805a2d42011-09-25 08:25:12 +00002822 case 'r':
2823 {
anthonydcf510d2011-10-30 13:51:40 +00002824 if (LocaleCompare("radial-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002825 {
anthonyfd706f92012-01-19 04:22:02 +00002826 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002827 new_image=RadialBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002828 geometry_info.sigma,exception);
2829 break;
2830 }
anthonydcf510d2011-10-30 13:51:40 +00002831 if (LocaleCompare("raise",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002832 {
anthony31f1bf72012-01-30 12:37:22 +00002833 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002834 if ((flags & SigmaValue) == 0)
2835 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00002836 (void) RaiseImage(image,&geometry,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002837 break;
2838 }
anthonydcf510d2011-10-30 13:51:40 +00002839 if (LocaleCompare("random-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002840 {
anthony31f1bf72012-01-30 12:37:22 +00002841 (void) RandomThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002842 break;
2843 }
anthonydcf510d2011-10-30 13:51:40 +00002844 if (LocaleCompare("remap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002845 {
2846 Image
2847 *remap_image;
2848
anthonyfd706f92012-01-19 04:22:02 +00002849 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002850 if (remap_image == (Image *) NULL)
2851 break;
anthony31f1bf72012-01-30 12:37:22 +00002852 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002853 remap_image=DestroyImage(remap_image);
2854 break;
2855 }
anthonydcf510d2011-10-30 13:51:40 +00002856 if (LocaleCompare("repage",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002857 {
anthony31f1bf72012-01-30 12:37:22 +00002858 if (plus_alt_op == MagickFalse)
2859 (void) ResetImagePage(image,arg1);
2860 else
2861 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
anthony805a2d42011-09-25 08:25:12 +00002862 break;
2863 }
anthonydcf510d2011-10-30 13:51:40 +00002864 if (LocaleCompare("resample",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002865 {
anthony31f1bf72012-01-30 12:37:22 +00002866 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00002867 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002868 if ((flags & SigmaValue) == 0)
2869 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002870 new_image=ResampleImage(image,geometry_info.rho,
2871 geometry_info.sigma,image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002872 break;
2873 }
anthonydcf510d2011-10-30 13:51:40 +00002874 if (LocaleCompare("resize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002875 {
anthonyafbaed72011-10-26 12:05:04 +00002876 /* FUTURE: remove blur argument - no longer used */
anthony31f1bf72012-01-30 12:37:22 +00002877 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2878 new_image=ResizeImage(image,geometry.width,geometry.height,
2879 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002880 break;
2881 }
anthonydcf510d2011-10-30 13:51:40 +00002882 if (LocaleCompare("roll",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002883 {
anthony31f1bf72012-01-30 12:37:22 +00002884 (void) ParsePageGeometry(image,arg1,&geometry,exception);
2885 new_image=RollImage(image,geometry.x,geometry.y,exception);
anthony805a2d42011-09-25 08:25:12 +00002886 break;
2887 }
anthonydcf510d2011-10-30 13:51:40 +00002888 if (LocaleCompare("rotate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002889 {
anthonyfd706f92012-01-19 04:22:02 +00002890 if (strchr(arg1,'>') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002891 if (image->columns <= image->rows)
anthony805a2d42011-09-25 08:25:12 +00002892 break;
anthonyfd706f92012-01-19 04:22:02 +00002893 if (strchr(arg1,'<') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002894 if (image->columns >= image->rows)
anthony805a2d42011-09-25 08:25:12 +00002895 break;
anthonyafbaed72011-10-26 12:05:04 +00002896
anthonyfd706f92012-01-19 04:22:02 +00002897 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002898 new_image=RotateImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00002899 break;
2900 }
2901 break;
2902 }
2903 case 's':
2904 {
anthonydcf510d2011-10-30 13:51:40 +00002905 if (LocaleCompare("sample",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002906 {
anthony31f1bf72012-01-30 12:37:22 +00002907 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2908 new_image=SampleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00002909 exception);
2910 break;
2911 }
anthonydcf510d2011-10-30 13:51:40 +00002912 if (LocaleCompare("scale",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002913 {
anthony31f1bf72012-01-30 12:37:22 +00002914 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2915 new_image=ScaleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00002916 exception);
2917 break;
2918 }
anthonydcf510d2011-10-30 13:51:40 +00002919 if (LocaleCompare("selective-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002920 {
anthonyfd706f92012-01-19 04:22:02 +00002921 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002922 if ((flags & PercentValue) != 0)
2923 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002924 new_image=SelectiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002925 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
2926 break;
2927 }
anthonydcf510d2011-10-30 13:51:40 +00002928 if (LocaleCompare("separate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002929 {
anthony31f1bf72012-01-30 12:37:22 +00002930 /* WARNING: This can generate multiple images! */
2931 new_image=SeparateImages(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002932 break;
2933 }
anthonydcf510d2011-10-30 13:51:40 +00002934 if (LocaleCompare("sepia-tone",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002935 {
2936 double
2937 threshold;
2938
anthonyfd706f92012-01-19 04:22:02 +00002939 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002940 new_image=SepiaToneImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002941 break;
2942 }
anthonydcf510d2011-10-30 13:51:40 +00002943 if (LocaleCompare("segment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002944 {
anthonyfd706f92012-01-19 04:22:02 +00002945 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002946 if ((flags & SigmaValue) == 0)
2947 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002948 (void) SegmentImage(image,image->colorspace,
anthony805a2d42011-09-25 08:25:12 +00002949 image_info->verbose,geometry_info.rho,geometry_info.sigma,
2950 exception);
2951 break;
2952 }
anthonydcf510d2011-10-30 13:51:40 +00002953 if (LocaleCompare("set",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002954 {
2955 char
2956 *value;
2957
anthony31f1bf72012-01-30 12:37:22 +00002958 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002959 {
anthonyfd706f92012-01-19 04:22:02 +00002960 if (LocaleNCompare(arg1,"registry:",9) == 0)
2961 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00002962 else
anthony31f1bf72012-01-30 12:37:22 +00002963 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00002964 {
anthonyfd706f92012-01-19 04:22:02 +00002965 (void) DeleteImageOption(image_info,arg1+7);
anthony31f1bf72012-01-30 12:37:22 +00002966 (void) DeleteImageArtifact(image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00002967 }
2968 else
anthony31f1bf72012-01-30 12:37:22 +00002969 (void) DeleteImageProperty(image,arg1);
anthony805a2d42011-09-25 08:25:12 +00002970 break;
2971 }
anthony31f1bf72012-01-30 12:37:22 +00002972 value=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002973 exception);
2974 if (value == (char *) NULL)
2975 break;
anthonyfd706f92012-01-19 04:22:02 +00002976 if (LocaleNCompare(arg1,"registry:",9) == 0)
2977 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony805a2d42011-09-25 08:25:12 +00002978 exception);
2979 else
anthonyfd706f92012-01-19 04:22:02 +00002980 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00002981 {
anthonyfd706f92012-01-19 04:22:02 +00002982 (void) SetImageOption(image_info,arg1+7,value);
anthony31f1bf72012-01-30 12:37:22 +00002983 (void) SetImageArtifact(image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00002984 }
2985 else
anthony31f1bf72012-01-30 12:37:22 +00002986 (void) SetImageProperty(image,arg1,value,exception);
anthony805a2d42011-09-25 08:25:12 +00002987 value=DestroyString(value);
2988 break;
2989 }
anthonydcf510d2011-10-30 13:51:40 +00002990 if (LocaleCompare("shade",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002991 {
anthonyfd706f92012-01-19 04:22:02 +00002992 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002993 if ((flags & SigmaValue) == 0)
2994 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002995 new_image=ShadeImage(image,normal_op,geometry_info.rho,
2996 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002997 break;
2998 }
anthonydcf510d2011-10-30 13:51:40 +00002999 if (LocaleCompare("shadow",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003000 {
anthonyfd706f92012-01-19 04:22:02 +00003001 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003002 if ((flags & SigmaValue) == 0)
3003 geometry_info.sigma=1.0;
3004 if ((flags & XiValue) == 0)
3005 geometry_info.xi=4.0;
3006 if ((flags & PsiValue) == 0)
3007 geometry_info.psi=4.0;
anthony31f1bf72012-01-30 12:37:22 +00003008 new_image=ShadowImage(image,geometry_info.rho,
3009 geometry_info.sigma,image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003010 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
3011 exception);
anthony805a2d42011-09-25 08:25:12 +00003012 break;
3013 }
anthonydcf510d2011-10-30 13:51:40 +00003014 if (LocaleCompare("sharpen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003015 {
anthonyfd706f92012-01-19 04:22:02 +00003016 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003017 if ((flags & SigmaValue) == 0)
3018 geometry_info.sigma=1.0;
3019 if ((flags & XiValue) == 0)
3020 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00003021 new_image=SharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003022 geometry_info.sigma,geometry_info.xi,exception);
3023 break;
3024 }
anthonydcf510d2011-10-30 13:51:40 +00003025 if (LocaleCompare("shave",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003026 {
anthony31f1bf72012-01-30 12:37:22 +00003027 flags=ParsePageGeometry(image,arg1,&geometry,exception);
3028 new_image=ShaveImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003029 break;
3030 }
anthonydcf510d2011-10-30 13:51:40 +00003031 if (LocaleCompare("shear",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003032 {
anthonyfd706f92012-01-19 04:22:02 +00003033 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003034 if ((flags & SigmaValue) == 0)
3035 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00003036 new_image=ShearImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003037 geometry_info.sigma,exception);
3038 break;
3039 }
anthonydcf510d2011-10-30 13:51:40 +00003040 if (LocaleCompare("sigmoidal-contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003041 {
anthonyfd706f92012-01-19 04:22:02 +00003042 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003043 if ((flags & SigmaValue) == 0)
3044 geometry_info.sigma=(double) QuantumRange/2.0;
3045 if ((flags & PercentValue) != 0)
3046 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3047 100.0;
anthony31f1bf72012-01-30 12:37:22 +00003048 (void) SigmoidalContrastImage(image,normal_op,geometry_info.rho,
3049 geometry_info.sigma,
anthony805a2d42011-09-25 08:25:12 +00003050 exception);
3051 break;
3052 }
anthonydcf510d2011-10-30 13:51:40 +00003053 if (LocaleCompare("sketch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003054 {
anthonyfd706f92012-01-19 04:22:02 +00003055 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003056 if ((flags & SigmaValue) == 0)
3057 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003058 new_image=SketchImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003059 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3060 break;
3061 }
anthonydcf510d2011-10-30 13:51:40 +00003062 if (LocaleCompare("solarize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003063 {
anthony31f1bf72012-01-30 12:37:22 +00003064 (void) SolarizeImage(image,StringToDoubleInterval(arg1,(double)
3065 QuantumRange+1.0),exception);
anthony805a2d42011-09-25 08:25:12 +00003066 break;
3067 }
anthonydcf510d2011-10-30 13:51:40 +00003068 if (LocaleCompare("sparse-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003069 {
3070 SparseColorMethod
3071 method;
3072
3073 char
3074 *arguments;
3075
anthony805a2d42011-09-25 08:25:12 +00003076 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003077 MagickSparseColorOptions,MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003078 arguments=InterpretImageProperties(image_info,image,arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00003079 if (arguments == (char *) NULL)
3080 break;
anthony31f1bf72012-01-30 12:37:22 +00003081 new_image=SparseColorOption(image,method,arguments,exception);
anthony805a2d42011-09-25 08:25:12 +00003082 arguments=DestroyString(arguments);
3083 break;
3084 }
anthonydcf510d2011-10-30 13:51:40 +00003085 if (LocaleCompare("splice",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003086 {
anthony31f1bf72012-01-30 12:37:22 +00003087 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
3088 new_image=SpliceImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003089 break;
3090 }
anthonydcf510d2011-10-30 13:51:40 +00003091 if (LocaleCompare("spread",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003092 {
anthonyfd706f92012-01-19 04:22:02 +00003093 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003094 new_image=SpreadImage(image,geometry_info.rho,image->interpolate,
3095 exception);
anthony805a2d42011-09-25 08:25:12 +00003096 break;
3097 }
anthonydcf510d2011-10-30 13:51:40 +00003098 if (LocaleCompare("statistic",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003099 {
3100 StatisticType
3101 type;
3102
anthony805a2d42011-09-25 08:25:12 +00003103 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003104 MagickFalse,arg1);
3105 (void) ParseGeometry(arg2,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003106 new_image=StatisticImage(image,type,(size_t) geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003107 (size_t) geometry_info.sigma,exception);
3108 break;
3109 }
anthonydcf510d2011-10-30 13:51:40 +00003110 if (LocaleCompare("strip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003111 {
anthony31f1bf72012-01-30 12:37:22 +00003112 (void) StripImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003113 break;
3114 }
anthonydcf510d2011-10-30 13:51:40 +00003115 if (LocaleCompare("swirl",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003116 {
anthonyfd706f92012-01-19 04:22:02 +00003117 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003118 new_image=SwirlImage(image,geometry_info.rho,
3119 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003120 break;
3121 }
3122 break;
3123 }
3124 case 't':
3125 {
anthonydcf510d2011-10-30 13:51:40 +00003126 if (LocaleCompare("threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003127 {
3128 double
3129 threshold;
3130
anthony31f1bf72012-01-30 12:37:22 +00003131 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003132 threshold=(double) QuantumRange/2;
3133 else
anthonyfd706f92012-01-19 04:22:02 +00003134 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003135 (void) BilevelImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003136 break;
3137 }
anthonydcf510d2011-10-30 13:51:40 +00003138 if (LocaleCompare("thumbnail",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003139 {
anthony31f1bf72012-01-30 12:37:22 +00003140 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3141 new_image=ThumbnailImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003142 exception);
3143 break;
3144 }
anthonydcf510d2011-10-30 13:51:40 +00003145 if (LocaleCompare("tint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003146 {
anthony31f1bf72012-01-30 12:37:22 +00003147 new_image=TintImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00003148 break;
3149 }
anthonydcf510d2011-10-30 13:51:40 +00003150 if (LocaleCompare("transform",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003151 {
anthonyfd706f92012-01-19 04:22:02 +00003152 /* DEPRECIATED */
anthony31f1bf72012-01-30 12:37:22 +00003153 new_image=AffineTransformImage(image,&draw_info->affine,
anthony805a2d42011-09-25 08:25:12 +00003154 exception);
3155 break;
3156 }
anthonydcf510d2011-10-30 13:51:40 +00003157 if (LocaleCompare("transparent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003158 {
3159 PixelInfo
3160 target;
3161
anthony31f1bf72012-01-30 12:37:22 +00003162 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
3163 (void) TransparentPaintImage(image,&target,(Quantum)
3164 TransparentAlpha,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003165 break;
3166 }
anthonydcf510d2011-10-30 13:51:40 +00003167 if (LocaleCompare("transpose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003168 {
anthony31f1bf72012-01-30 12:37:22 +00003169 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003170 break;
3171 }
anthonydcf510d2011-10-30 13:51:40 +00003172 if (LocaleCompare("transverse",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003173 {
anthony31f1bf72012-01-30 12:37:22 +00003174 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003175 break;
3176 }
anthonydcf510d2011-10-30 13:51:40 +00003177 if (LocaleCompare("trim",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003178 {
anthony31f1bf72012-01-30 12:37:22 +00003179 new_image=TrimImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003180 break;
3181 }
anthonydcf510d2011-10-30 13:51:40 +00003182 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003183 {
anthonyab3a50c2011-10-27 11:48:57 +00003184 /* Note that "type" setting should have already been defined */
anthony31f1bf72012-01-30 12:37:22 +00003185 (void) SetImageType(image,image_info->type,exception);
anthony805a2d42011-09-25 08:25:12 +00003186 break;
3187 }
3188 break;
3189 }
3190 case 'u':
3191 {
anthonydcf510d2011-10-30 13:51:40 +00003192 if (LocaleCompare("unique",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003193 {
anthony31f1bf72012-01-30 12:37:22 +00003194 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
3195 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003196 {
anthony31f1bf72012-01-30 12:37:22 +00003197 (void) DeleteImageArtifact(image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003198 break;
3199 }
anthony31f1bf72012-01-30 12:37:22 +00003200 (void) SetImageArtifact(image,"identify:unique-colors","true");
3201 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003202 break;
3203 }
anthonydcf510d2011-10-30 13:51:40 +00003204 if (LocaleCompare("unique-colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003205 {
anthony31f1bf72012-01-30 12:37:22 +00003206 new_image=UniqueImageColors(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003207 break;
3208 }
anthonydcf510d2011-10-30 13:51:40 +00003209 if (LocaleCompare("unsharp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003210 {
anthonyfd706f92012-01-19 04:22:02 +00003211 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003212 if ((flags & SigmaValue) == 0)
3213 geometry_info.sigma=1.0;
3214 if ((flags & XiValue) == 0)
3215 geometry_info.xi=1.0;
3216 if ((flags & PsiValue) == 0)
3217 geometry_info.psi=0.05;
anthony31f1bf72012-01-30 12:37:22 +00003218 new_image=UnsharpMaskImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003219 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3220 break;
3221 }
3222 break;
3223 }
3224 case 'v':
3225 {
anthonydcf510d2011-10-30 13:51:40 +00003226 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003227 {
anthony31f1bf72012-01-30 12:37:22 +00003228 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3229 three places! ImageArtifact ImageOption image_info->verbose
3230 Some how new images also get this artifact -- how???
3231 */
3232 (void) SetImageArtifact(image,option,
3233 (plus_alt_op != MagickFalse) ? "false" : "true" );
anthony805a2d42011-09-25 08:25:12 +00003234 break;
3235 }
anthonydcf510d2011-10-30 13:51:40 +00003236 if (LocaleCompare("vignette",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003237 {
anthonyfd706f92012-01-19 04:22:02 +00003238 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003239 if ((flags & SigmaValue) == 0)
3240 geometry_info.sigma=1.0;
3241 if ((flags & XiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003242 geometry_info.xi=0.1*image->columns;
anthony805a2d42011-09-25 08:25:12 +00003243 if ((flags & PsiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003244 geometry_info.psi=0.1*image->rows;
3245 new_image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
3246 image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3247 (ssize_t) ceil(geometry_info.psi-0.5),exception);
anthony805a2d42011-09-25 08:25:12 +00003248 break;
3249 }
anthony805a2d42011-09-25 08:25:12 +00003250 break;
3251 }
3252 case 'w':
3253 {
anthonydcf510d2011-10-30 13:51:40 +00003254 if (LocaleCompare("wave",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003255 {
anthonyfd706f92012-01-19 04:22:02 +00003256 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003257 if ((flags & SigmaValue) == 0)
3258 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003259 new_image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
3260 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003261 break;
3262 }
anthonydcf510d2011-10-30 13:51:40 +00003263 if (LocaleCompare("white-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003264 {
anthony31f1bf72012-01-30 12:37:22 +00003265 (void) WhiteThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003266 break;
3267 }
3268 break;
3269 }
3270 default:
3271 break;
3272 }
3273 /*
3274 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003275 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003276 */
3277 if (new_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003278 ReplaceImageInListReturnLast(&image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003279
anthony31f1bf72012-01-30 12:37:22 +00003280 return;
anthonyfd706f92012-01-19 04:22:02 +00003281#undef image_info
3282#undef draw_info
3283#undef quantize_info
anthony31f1bf72012-01-30 12:37:22 +00003284#undef image
anthonyfd706f92012-01-19 04:22:02 +00003285#undef exception
anthony31f1bf72012-01-30 12:37:22 +00003286#undef normal_op
3287}
anthonyfd706f92012-01-19 04:22:02 +00003288
anthony31f1bf72012-01-30 12:37:22 +00003289WandExport void WandSimpleOperatorImages(MagickWand *wand,
3290 const MagickBooleanType plus_alt_op, const char *option,
3291 const char *arg1, const char *arg2)
3292{
3293 size_t
3294 n;
3295
3296 register ssize_t
3297 i;
3298
3299 assert(wand->image_info != (const ImageInfo *) NULL);
3300 assert(wand->image_info->signature == MagickSignature);
3301 assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
3302 assert(wand->images != (Image *) NULL); /* there is one image */
3303
3304 i=0;
3305 n=GetImageListLength(wand->images);
3306 wand->images=GetFirstImageInList(wand->images);
3307 for ( ; ; )
3308 {
3309 WandSimpleOperatorImage(wand, plus_alt_op, option, arg1, arg2);
3310 if ( wand->images->next == (Image *) NULL )
3311 break;
3312 wand->images=wand->images->next;
3313 i++;
3314 }
3315 wand->images=GetFirstImageInList(wand->images);
3316 return;
anthony805a2d42011-09-25 08:25:12 +00003317}
3318
3319/*
3320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3321% %
3322% %
3323% %
anthony31f1bf72012-01-30 12:37:22 +00003324+ 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 +00003325% %
3326% %
3327% %
3328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3329%
anthony31f1bf72012-01-30 12:37:22 +00003330% WandListOperatorImages() applies a single operation that is apply to the
3331% entire image list as a whole. The result is often a complete replacment
3332% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003333%
3334% The format of the MogrifyImage method is:
3335%
anthony36a8c2c2012-02-10 00:08:44 +00003336% void WandListOperatorImages(MagickWand *wand,
3337% const MagickBooleanType plus_alt_op,const char *option,
anthony31f1bf72012-01-30 12:37:22 +00003338% const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003339%
3340% A description of each parameter follows:
3341%
anthony31f1bf72012-01-30 12:37:22 +00003342% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003343%
anthony8b10b462012-02-08 12:32:44 +00003344% o plus_alt_op: request the 'plus' or alturnative form of the operation
3345%
anthony36a8c2c2012-02-10 00:08:44 +00003346% o option: The option string for the operation
3347%
anthony31f1bf72012-01-30 12:37:22 +00003348% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003349%
anthony8b10b462012-02-08 12:32:44 +00003350% NOTE: only "limit" currently uses two arguments.
3351%
3352% Example usage...
3353%
3354% WandListOperatorImages(wand,"read", MagickFalse,"rose:",NULL);
3355% WandListOperatorImages(wand,"duplicate",MagickFalse,"3",NULL);
3356% WandListOperatorImages(wand,"append",MagickTrue,NULL,NULL);
3357% if ( wand->exception->severity != UndefinedException ) {
3358% CatchException(exception);
3359% exit(1);
3360% }
3361%
3362% Or for handling command line arguments EG: +/-option ["arg"]
3363%
3364% argc,argv
3365% i=index in argv
3366%
3367% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
3368% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
3369% if ( flags & ListOperatorOptionFlag != 0 )
anthony36a8c2c2012-02-10 00:08:44 +00003370% WandListOperatorImages(wand,
3371% ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
anthony8b10b462012-02-08 12:32:44 +00003372% count>=1 ? argv[i+1] : (char *)NULL,
3373% count>=2 ? argv[i+2] : (char *)NULL );
3374% i += count+1;
3375%
anthony805a2d42011-09-25 08:25:12 +00003376*/
anthony36a8c2c2012-02-10 00:08:44 +00003377WandExport void WandListOperatorImages(MagickWand *wand,
3378 const MagickBooleanType plus_alt_op,const char *option,
3379 const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003380{
anthony31f1bf72012-01-30 12:37:22 +00003381 Image
3382 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003383
anthony31f1bf72012-01-30 12:37:22 +00003384#define image_info (wand->image_info)
3385#define draw_info (wand->draw_info)
3386#define quantize_info (wand->quantize_info)
3387#define images (wand->images)
3388#define exception (wand->exception)
3389#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
anthony805a2d42011-09-25 08:25:12 +00003390
anthony31f1bf72012-01-30 12:37:22 +00003391 assert(image_info != (const ImageInfo *) NULL);
anthony805a2d42011-09-25 08:25:12 +00003392 assert(image_info->signature == MagickSignature);
anthony31f1bf72012-01-30 12:37:22 +00003393 assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
3394 assert(images != (Image *) NULL); /* there is an image */
3395 assert(images->signature == MagickSignature); /* and is a valid image */
anthony805a2d42011-09-25 08:25:12 +00003396
anthony31f1bf72012-01-30 12:37:22 +00003397 if (wand->debug != MagickFalse)
3398 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3399
3400 (void) SyncImagesSettings(image_info,images,exception);
3401
3402 new_images=NewImageList();
3403
3404 switch (*option)
anthony805a2d42011-09-25 08:25:12 +00003405 {
3406 case 'a':
3407 {
anthony31f1bf72012-01-30 12:37:22 +00003408 if (LocaleCompare("append",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003409 {
anthony31f1bf72012-01-30 12:37:22 +00003410 new_images=AppendImages(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003411 break;
3412 }
anthony31f1bf72012-01-30 12:37:22 +00003413 if (LocaleCompare("average",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003414 {
anthony31f1bf72012-01-30 12:37:22 +00003415 /* DEPRECIATED - use -evaluate-sequence Mean */
3416 WandListOperatorImages(wand,plus_alt_op,"evaluate-sequence","Mean",
3417 NULL);
anthony805a2d42011-09-25 08:25:12 +00003418 break;
3419 }
3420 break;
3421 }
3422 case 'c':
3423 {
anthony31f1bf72012-01-30 12:37:22 +00003424 if (LocaleCompare("clut",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003425 {
anthony31f1bf72012-01-30 12:37:22 +00003426 /* FUTURE - make this a compose option (and thus layers compose )
3427 or perhaps compose last image over all other images.
3428 */
anthony805a2d42011-09-25 08:25:12 +00003429 Image
anthony31f1bf72012-01-30 12:37:22 +00003430 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003431
anthony31f1bf72012-01-30 12:37:22 +00003432 new_images=RemoveFirstImageFromList(&images);
3433 clut_image=RemoveLastImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003434 if (clut_image == (Image *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003435 break;
anthony31f1bf72012-01-30 12:37:22 +00003436 (void) ClutImage(new_images,clut_image,images->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003437 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003438 break;
3439 }
anthony31f1bf72012-01-30 12:37:22 +00003440 if (LocaleCompare("coalesce",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003441 {
anthony31f1bf72012-01-30 12:37:22 +00003442 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003443 break;
3444 }
anthony31f1bf72012-01-30 12:37:22 +00003445 if (LocaleCompare("combine",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003446 {
anthony31f1bf72012-01-30 12:37:22 +00003447 new_images=CombineImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003448 break;
3449 }
anthony31f1bf72012-01-30 12:37:22 +00003450 if (LocaleCompare("composite",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003451 {
3452 Image
3453 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003454 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003455
3456 RectangleInfo
3457 geometry;
3458
anthony31f1bf72012-01-30 12:37:22 +00003459 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003460 compose;
3461
3462 const char*
3463 value;
3464
3465 value=GetImageOption(image_info,"compose");
3466 if (value != (const char *) NULL)
3467 compose=(CompositeOperator) ParseCommandOption(
3468 MagickComposeOptions,MagickFalse,value);
3469 else
anthony31f1bf72012-01-30 12:37:22 +00003470 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003471
anthony31f1bf72012-01-30 12:37:22 +00003472 new_images=RemoveFirstImageFromList(&images);
3473 source_image=RemoveFirstImageFromList(&images);
3474 if (source_image == (Image *) NULL)
3475 break;
3476 /* FUTURE - this should not be here! - should be part of -geometry */
3477 (void) TransformImage(&source_image,(char *) NULL,
3478 source_image->geometry,exception);
anthony5f867ae2011-10-09 10:28:34 +00003479
anthony31f1bf72012-01-30 12:37:22 +00003480 SetGeometry(source_image,&geometry);
3481 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3482 GravityAdjustGeometry(new_images->columns,new_images->rows,
3483 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003484
anthony31f1bf72012-01-30 12:37:22 +00003485 mask_image=RemoveFirstImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003486 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003487 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003488 if ((compose == DisplaceCompositeOp) ||
3489 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003490 { /* Merge Y displacement into X displace/distort map. */
3491 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony6613bf32011-10-15 07:24:44 +00003492 mask_image,0,0,exception);
anthony805a2d42011-09-25 08:25:12 +00003493 mask_image=DestroyImage(mask_image);
3494 }
3495 else
3496 {
3497 /*
3498 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003499 */
cristy1539afd2012-01-30 01:32:59 +00003500 (void) NegateImage(mask_image,MagickFalse,exception);
anthony31f1bf72012-01-30 12:37:22 +00003501 (void) SetImageMask(new_images,mask_image,exception);
cristy1539afd2012-01-30 01:32:59 +00003502 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003503 }
3504 }
anthony31f1bf72012-01-30 12:37:22 +00003505 (void) CompositeImage(new_images,compose,source_image,geometry.x,
3506 geometry.y,exception);
3507 (void) SetImageMask(new_images,(Image *) NULL,exception);
3508 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003509 break;
3510 }
3511 break;
3512 }
3513 case 'd':
3514 {
anthony31f1bf72012-01-30 12:37:22 +00003515 if (LocaleCompare("deconstruct",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003516 {
anthony31f1bf72012-01-30 12:37:22 +00003517 /* DEPRECIATED - use -layers CompareAny */
3518 WandListOperatorImages(wand,plus_alt_op,"layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003519 break;
3520 }
anthony31f1bf72012-01-30 12:37:22 +00003521 if (LocaleCompare("delete",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003522 {
anthony31f1bf72012-01-30 12:37:22 +00003523 if (plus_alt_op != MagickFalse)
3524 DeleteImages(&images,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003525 else
anthony31f1bf72012-01-30 12:37:22 +00003526 DeleteImages(&images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003527 break;
3528 }
anthony31f1bf72012-01-30 12:37:22 +00003529 if (LocaleCompare("duplicate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003530 {
anthony31f1bf72012-01-30 12:37:22 +00003531 if (plus_alt_op != MagickFalse)
anthony36a8c2c2012-02-10 00:08:44 +00003532 new_images=DuplicateImages(images,1,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003533 else
3534 {
3535 const char
3536 *p;
3537
3538 size_t
3539 number_duplicates;
3540
anthony31f1bf72012-01-30 12:37:22 +00003541 number_duplicates=(size_t) StringToLong(arg1);
3542 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003543 if (p == (const char *) NULL)
anthony36a8c2c2012-02-10 00:08:44 +00003544 new_images=DuplicateImages(images,number_duplicates,
anthony805a2d42011-09-25 08:25:12 +00003545 "-1",exception);
3546 else
anthony36a8c2c2012-02-10 00:08:44 +00003547 new_images=DuplicateImages(images,number_duplicates,p,
anthony805a2d42011-09-25 08:25:12 +00003548 exception);
3549 }
anthony36a8c2c2012-02-10 00:08:44 +00003550 AppendImageToList(&images, new_images);
3551 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003552 break;
3553 }
3554 break;
3555 }
3556 case 'e':
3557 {
anthony31f1bf72012-01-30 12:37:22 +00003558 if (LocaleCompare("evaluate-sequence",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003559 {
anthony805a2d42011-09-25 08:25:12 +00003560 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003561 method;
anthony805a2d42011-09-25 08:25:12 +00003562
anthony31f1bf72012-01-30 12:37:22 +00003563 method=(MagickEvaluateOperator) ParseCommandOption(
3564 MagickEvaluateOptions,MagickFalse,arg1);
3565 new_images=EvaluateImages(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003566 break;
3567 }
3568 break;
3569 }
3570 case 'f':
3571 {
anthony31f1bf72012-01-30 12:37:22 +00003572 if (LocaleCompare("fft",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003573 {
anthony31f1bf72012-01-30 12:37:22 +00003574 new_images=ForwardFourierTransformImage(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003575 break;
3576 }
anthony31f1bf72012-01-30 12:37:22 +00003577 if (LocaleCompare("flatten",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003578 {
anthony31f1bf72012-01-30 12:37:22 +00003579 /* DEPRECIATED use -layers mosaic instead */
3580 WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
anthony805a2d42011-09-25 08:25:12 +00003581 break;
3582 }
anthony31f1bf72012-01-30 12:37:22 +00003583 if (LocaleCompare("fx",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003584 {
anthony31f1bf72012-01-30 12:37:22 +00003585 new_images=FxImage(images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003586 break;
3587 }
3588 break;
3589 }
3590 case 'h':
3591 {
anthony31f1bf72012-01-30 12:37:22 +00003592 if (LocaleCompare("hald-clut",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003593 {
anthony31f1bf72012-01-30 12:37:22 +00003594 /* FUTURE - make this a compose option (and thus layers compose )
3595 or perhaps compose last image over all other images.
3596 */
anthony805a2d42011-09-25 08:25:12 +00003597 Image
anthony31f1bf72012-01-30 12:37:22 +00003598 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003599
anthony31f1bf72012-01-30 12:37:22 +00003600 new_images=RemoveFirstImageFromList(&images);
3601 hald_image=RemoveLastImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003602 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003603 break;
3604 (void) HaldClutImage(new_images,hald_image,exception);
anthony805a2d42011-09-25 08:25:12 +00003605 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003606 break;
3607 }
3608 break;
3609 }
3610 case 'i':
3611 {
anthony31f1bf72012-01-30 12:37:22 +00003612 if (LocaleCompare("ift",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003613 {
3614 Image
anthony805a2d42011-09-25 08:25:12 +00003615 *magnitude_image,
3616 *phase_image;
3617
anthony31f1bf72012-01-30 12:37:22 +00003618 magnitude_image=RemoveFirstImageFromList(&images);
3619 phase_image=RemoveFirstImageFromList(&images);
3620 if (phase_image == (Image *) NULL)
3621 break;
3622 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3623 normal_op,exception);
3624 magnitude_image=DestroyImage(magnitude_image);
3625 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003626 break;
3627 }
anthony31f1bf72012-01-30 12:37:22 +00003628 if (LocaleCompare("insert",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003629 {
3630 Image
anthony31f1bf72012-01-30 12:37:22 +00003631 *insert_image,
3632 *index_image;
3633
3634 ssize_t
3635 index;
anthony805a2d42011-09-25 08:25:12 +00003636
3637 index=0;
anthony31f1bf72012-01-30 12:37:22 +00003638 insert_image=RemoveLastImageFromList(&images);
3639 if (plus_alt_op == MagickFalse)
3640 index=(ssize_t) StringToLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00003641 if (index == 0)
anthony31f1bf72012-01-30 12:37:22 +00003642 PrependImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003643 else
anthony31f1bf72012-01-30 12:37:22 +00003644 if (index == (ssize_t) GetImageListLength(images))
3645 AppendImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003646 else
3647 {
anthony31f1bf72012-01-30 12:37:22 +00003648 index_image=GetImageFromList(images,index-1);
3649 if (index_image == (Image *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003650 {
3651 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00003652 OptionError,"NoSuchImage","`%s'",arg1);
anthony805a2d42011-09-25 08:25:12 +00003653 break;
3654 }
anthony31f1bf72012-01-30 12:37:22 +00003655 InsertImageInList(&index_image,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003656 }
anthony31f1bf72012-01-30 12:37:22 +00003657 images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003658 break;
3659 }
anthony805a2d42011-09-25 08:25:12 +00003660 break;
3661 }
3662 case 'l':
3663 {
anthony31f1bf72012-01-30 12:37:22 +00003664 if (LocaleCompare("layers",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003665 {
anthony805a2d42011-09-25 08:25:12 +00003666 ImageLayerMethod
3667 method;
3668
anthony805a2d42011-09-25 08:25:12 +00003669 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003670 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003671 switch (method)
3672 {
3673 case CoalesceLayer:
3674 {
anthony31f1bf72012-01-30 12:37:22 +00003675 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003676 break;
3677 }
3678 case CompareAnyLayer:
3679 case CompareClearLayer:
3680 case CompareOverlayLayer:
3681 default:
3682 {
anthony31f1bf72012-01-30 12:37:22 +00003683 new_images=CompareImagesLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003684 break;
3685 }
3686 case MergeLayer:
3687 case FlattenLayer:
3688 case MosaicLayer:
3689 case TrimBoundsLayer:
3690 {
anthony31f1bf72012-01-30 12:37:22 +00003691 new_images=MergeImageLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003692 break;
3693 }
3694 case DisposeLayer:
3695 {
anthony31f1bf72012-01-30 12:37:22 +00003696 new_images=DisposeImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003697 break;
3698 }
3699 case OptimizeImageLayer:
3700 {
anthony31f1bf72012-01-30 12:37:22 +00003701 new_images=OptimizeImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003702 break;
3703 }
3704 case OptimizePlusLayer:
3705 {
anthony31f1bf72012-01-30 12:37:22 +00003706 new_images=OptimizePlusImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003707 break;
3708 }
3709 case OptimizeTransLayer:
3710 {
anthony31f1bf72012-01-30 12:37:22 +00003711 OptimizeImageTransparency(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003712 break;
3713 }
3714 case RemoveDupsLayer:
3715 {
anthony31f1bf72012-01-30 12:37:22 +00003716 RemoveDuplicateLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003717 break;
3718 }
3719 case RemoveZeroLayer:
3720 {
anthony31f1bf72012-01-30 12:37:22 +00003721 RemoveZeroDelayLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003722 break;
3723 }
3724 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003725 { /* General Purpose, GIF Animation Optimizer. */
3726 new_images=CoalesceImages(images,exception);
3727 if (new_images == (Image *) NULL)
3728 break;
3729 images=DestroyImageList(images);
3730 images=OptimizeImageLayers(new_images,exception);
3731 if (images == (Image *) NULL)
3732 break;
3733 new_images=DestroyImageList(new_images);
3734 OptimizeImageTransparency(images,exception);
3735 (void) RemapImages(quantize_info,images,(Image *) NULL,
anthony805a2d42011-09-25 08:25:12 +00003736 exception);
3737 break;
3738 }
3739 case CompositeLayer:
3740 {
anthony805a2d42011-09-25 08:25:12 +00003741 Image
3742 *source;
3743
3744 RectangleInfo
3745 geometry;
3746
anthony31f1bf72012-01-30 12:37:22 +00003747 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003748 compose;
3749
3750 const char*
3751 value;
3752
3753 value=GetImageOption(image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003754 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003755 if (value != (const char *) NULL)
3756 compose=(CompositeOperator) ParseCommandOption(
3757 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003758
anthony31f1bf72012-01-30 12:37:22 +00003759 /* Split image sequence at the first 'NULL:' image. */
3760 source=images;
anthony805a2d42011-09-25 08:25:12 +00003761 while (source != (Image *) NULL)
3762 {
3763 source=GetNextImageInList(source);
3764 if ((source != (Image *) NULL) &&
3765 (LocaleCompare(source->magick,"NULL") == 0))
3766 break;
3767 }
3768 if (source != (Image *) NULL)
3769 {
3770 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3771 (GetNextImageInList(source) == (Image *) NULL))
3772 source=(Image *) NULL;
3773 else
anthony31f1bf72012-01-30 12:37:22 +00003774 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003775 source=SplitImageList(source->previous);
3776 DeleteImageFromList(&source);
3777 }
3778 }
3779 if (source == (Image *) NULL)
3780 {
3781 (void) ThrowMagickException(exception,GetMagickModule(),
3782 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003783 break;
3784 }
anthony31f1bf72012-01-30 12:37:22 +00003785 /* Adjust offset with gravity and virtual canvas. */
3786 SetGeometry(images,&geometry);
3787 (void) ParseAbsoluteGeometry(images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003788 geometry.width=source->page.width != 0 ?
3789 source->page.width : source->columns;
3790 geometry.height=source->page.height != 0 ?
3791 source->page.height : source->rows;
anthony31f1bf72012-01-30 12:37:22 +00003792 GravityAdjustGeometry(images->page.width != 0 ?
3793 images->page.width : images->columns,
3794 images->page.height != 0 ? images->page.height :
3795 images->rows,images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003796
anthony31f1bf72012-01-30 12:37:22 +00003797 /* Compose the two image sequences together */
3798 CompositeLayers(images,compose,source,geometry.x,geometry.y,
anthony805a2d42011-09-25 08:25:12 +00003799 exception);
3800 source=DestroyImageList(source);
3801 break;
3802 }
3803 }
anthony805a2d42011-09-25 08:25:12 +00003804 break;
3805 }
anthony72feaa62012-01-17 06:46:23 +00003806 if (LocaleCompare("limit",option) == 0)
3807 {
3808 MagickSizeType
3809 limit;
3810
3811 ResourceType
3812 type;
3813
anthony72feaa62012-01-17 06:46:23 +00003814 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003815 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003816 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003817 if (LocaleCompare("unlimited",arg2) != 0)
3818 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003819 (void) SetMagickResourceLimit(type,limit);
3820 break;
3821 }
anthony805a2d42011-09-25 08:25:12 +00003822 break;
3823 }
3824 case 'm':
3825 {
anthony31f1bf72012-01-30 12:37:22 +00003826 if (LocaleCompare("map",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003827 {
anthony31f1bf72012-01-30 12:37:22 +00003828 /* DEPRECIATED use +remap */
3829 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00003830 break;
3831 }
anthony31f1bf72012-01-30 12:37:22 +00003832 if (LocaleCompare("morph",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003833 {
3834 Image
3835 *morph_image;
3836
anthony31f1bf72012-01-30 12:37:22 +00003837 morph_image=MorphImages(images,StringToUnsignedLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00003838 exception);
3839 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003840 break;
3841 images=DestroyImageList(images);
3842 images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00003843 break;
3844 }
anthony31f1bf72012-01-30 12:37:22 +00003845 if (LocaleCompare("mosaic",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003846 {
anthony31f1bf72012-01-30 12:37:22 +00003847 /* DEPRECIATED use -layers mosaic instead */
3848 WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
anthony805a2d42011-09-25 08:25:12 +00003849 break;
3850 }
3851 break;
3852 }
3853 case 'p':
3854 {
anthony31f1bf72012-01-30 12:37:22 +00003855 if (LocaleCompare("print",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003856 {
3857 char
3858 *string;
3859
anthony31f1bf72012-01-30 12:37:22 +00003860 string=InterpretImageProperties(image_info,images,arg1,
anthony805a2d42011-09-25 08:25:12 +00003861 exception);
3862 if (string == (char *) NULL)
3863 break;
3864 (void) FormatLocaleFile(stdout,"%s",string);
3865 string=DestroyString(string);
3866 }
anthony31f1bf72012-01-30 12:37:22 +00003867 if (LocaleCompare("process",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003868 {
3869 char
3870 **arguments;
3871
3872 int
3873 j,
3874 number_arguments;
3875
anthony31f1bf72012-01-30 12:37:22 +00003876 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00003877 if (arguments == (char **) NULL)
3878 break;
anthony31f1bf72012-01-30 12:37:22 +00003879 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003880 {
3881 char
3882 breaker,
3883 quote,
3884 *token;
3885
3886 const char
3887 *arguments;
3888
3889 int
3890 next,
3891 status;
3892
3893 size_t
3894 length;
3895
3896 TokenInfo
3897 *token_info;
3898
3899 /*
3900 Support old style syntax, filter="-option arg".
3901 */
anthony31f1bf72012-01-30 12:37:22 +00003902 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00003903 token=(char *) NULL;
3904 if (~length >= (MaxTextExtent-1))
3905 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
3906 sizeof(*token));
3907 if (token == (char *) NULL)
3908 break;
3909 next=0;
anthony31f1bf72012-01-30 12:37:22 +00003910 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00003911 token_info=AcquireTokenInfo();
3912 status=Tokenizer(token_info,0,token,length,arguments,"","=",
3913 "\"",'\0',&breaker,&next,&quote);
3914 token_info=DestroyTokenInfo(token_info);
3915 if (status == 0)
3916 {
3917 const char
3918 *argv;
3919
3920 argv=(&(arguments[next]));
anthony31f1bf72012-01-30 12:37:22 +00003921 (void) InvokeDynamicImageFilter(token,&images,1,&argv,
anthony805a2d42011-09-25 08:25:12 +00003922 exception);
3923 }
3924 token=DestroyString(token);
3925 break;
3926 }
3927 (void) SubstituteString(&arguments[1],"-","");
anthony31f1bf72012-01-30 12:37:22 +00003928 (void) InvokeDynamicImageFilter(arguments[1],&images,
anthony805a2d42011-09-25 08:25:12 +00003929 number_arguments-2,(const char **) arguments+2,exception);
3930 for (j=0; j < number_arguments; j++)
3931 arguments[j]=DestroyString(arguments[j]);
3932 arguments=(char **) RelinquishMagickMemory(arguments);
3933 break;
3934 }
3935 break;
3936 }
3937 case 'r':
3938 {
anthony36a8c2c2012-02-10 00:08:44 +00003939 if (LocaleCompare("read",option) == 0)
3940 {
3941 CopyMagickString(image_info->filename,arg1,MaxTextExtent);
3942 if (image_info->ping != MagickFalse)
3943 new_images=PingImages(image_info,exception);
3944 else
3945 new_images=ReadImages(image_info,exception);
3946 AppendImageToList(&images, new_images);
3947 new_images=(Image *) NULL;
3948 break;
3949 }
anthony31f1bf72012-01-30 12:37:22 +00003950 if (LocaleCompare("remap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003951 {
anthony31f1bf72012-01-30 12:37:22 +00003952 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3953 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3954 break;
3955 }
3956 if (LocaleCompare("reverse",option) == 0)
3957 {
3958 ReverseImageList(&images);
anthony805a2d42011-09-25 08:25:12 +00003959 break;
3960 }
3961 break;
3962 }
3963 case 's':
3964 {
anthony31f1bf72012-01-30 12:37:22 +00003965 if (LocaleCompare("smush",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003966 {
3967 Image
3968 *smush_image;
3969
3970 ssize_t
3971 offset;
3972
anthony31f1bf72012-01-30 12:37:22 +00003973 offset=(ssize_t) StringToLong(arg1);
3974 smush_image=SmushImages(images,normal_op,offset,exception);
anthony805a2d42011-09-25 08:25:12 +00003975 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003976 break;
3977 images=DestroyImageList(images);
3978 images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00003979 break;
3980 }
anthony31f1bf72012-01-30 12:37:22 +00003981 if (LocaleCompare("swap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003982 {
3983 Image
3984 *p,
3985 *q,
3986 *swap;
3987
3988 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00003989 index,
anthony805a2d42011-09-25 08:25:12 +00003990 swap_index;
3991
anthony31f1bf72012-01-30 12:37:22 +00003992 index=-1;
3993 swap_index=-2;
3994 if (plus_alt_op == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003995 {
3996 GeometryInfo
3997 geometry_info;
3998
3999 MagickStatusType
4000 flags;
4001
4002 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004003 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004004 index=(ssize_t) geometry_info.rho;
4005 if ((flags & SigmaValue) != 0)
4006 swap_index=(ssize_t) geometry_info.sigma;
4007 }
anthony31f1bf72012-01-30 12:37:22 +00004008 p=GetImageFromList(images,index);
4009 q=GetImageFromList(images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004010 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4011 {
4012 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00004013 OptionError,"NoSuchImage","`%s'",images->filename);
anthony805a2d42011-09-25 08:25:12 +00004014 break;
4015 }
4016 if (p == q)
4017 break;
4018 swap=CloneImage(p,0,0,MagickTrue,exception);
4019 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4020 ReplaceImageInList(&q,swap);
anthony31f1bf72012-01-30 12:37:22 +00004021 images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004022 break;
4023 }
4024 break;
4025 }
4026 case 'w':
4027 {
anthony31f1bf72012-01-30 12:37:22 +00004028 if (LocaleCompare("write",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00004029 {
4030 char
4031 key[MaxTextExtent];
4032
4033 Image
4034 *write_images;
4035
4036 ImageInfo
4037 *write_info;
4038
anthony31f1bf72012-01-30 12:37:22 +00004039 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004040 (void) DeleteImageRegistry(key);
anthony31f1bf72012-01-30 12:37:22 +00004041 write_images=images;
4042 if (plus_alt_op != MagickFalse)
4043 write_images=CloneImageList(images,exception);
anthony805a2d42011-09-25 08:25:12 +00004044 write_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00004045 (void) WriteImages(write_info,write_images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00004046 write_info=DestroyImageInfo(write_info);
anthony31f1bf72012-01-30 12:37:22 +00004047 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00004048 write_images=DestroyImageList(write_images);
4049 break;
4050 }
4051 break;
4052 }
4053 default:
4054 break;
4055 }
anthony31f1bf72012-01-30 12:37:22 +00004056 if (new_images == (Image *) NULL)
4057 return;
anthony805a2d42011-09-25 08:25:12 +00004058
anthony31f1bf72012-01-30 12:37:22 +00004059 if (images != (Image *) NULL)
4060 images=DestroyImageList(images);
4061 images=new_images;
4062 return;
4063
4064#undef image_info
4065#undef draw_info
4066#undef quantize_info
4067#undef images
4068#undef exception
4069#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004070}
cristy8d951092012-02-08 18:54:56 +00004071#endif