blob: 0439387ad7317833188d094d8757a5abee155c2a [file] [log] [blame]
anthony805a2d42011-09-25 08:25:12 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% OOO PPPP EEEE RRRR AA TTTTTT III OOO N N %
7% O O P P E R R A A TT I O O NN N %
8% O O PPPP EEE RRRR AAAA TT I O O N N N %
9% O O P E R R A A TT I O O N NN %
10% OOO P EEEE R RR A A TT III OOO N N %
11% %
12% %
13% MagickWand Module Methods %
14% %
15% Software Design %
16% John Cristy %
cristy0a0ca4f2011-09-28 01:15:28 +000017% September 2011 %
anthony805a2d42011-09-25 08:25:12 +000018% %
19% %
20% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% Apply the given options (settings, and simple, or sequence operations) to
37% the given image(s) according to the current "image_info" and "draw_info"
38% settings.
39%
40% The final goal is to allow the execution in a strict one option at a time
41% manner that is needed for 'pipelining and file scripting' of options in
42% IMv7.
43%
44% Anthony Thyssen, Sept 2011
45*/
cristyc689f1f2011-10-05 21:13:24 +000046#if 0
anthony805a2d42011-09-25 08:25:12 +000047
48/*
49 Include declarations.
50*/
51#include "MagickWand/studio.h"
52#include "MagickWand/MagickWand.h"
53#include "MagickWand/mogrify-private.h"
54#include "MagickCore/monitor-private.h"
55#include "MagickCore/thread-private.h"
56#include "MagickCore/string-private.h"
57
58/*
59 Define declarations.
60*/
61#define UndefinedCompressionQuality 0UL
62/*
63 Constant declaration. (temporary exports)
64*/
65static const char
66 BackgroundColor[] = "#fff", /* white */
67 BorderColor[] = "#dfdfdf", /* gray */
68 MatteColor[] = "#bdbdbd"; /* gray */
69
70/*
71** Function to report on the progress of image operations
72*/
73static MagickBooleanType MonitorProgress(const char *text,
74 const MagickOffsetType offset,const MagickSizeType extent,
75 void *wand_unused(client_data))
76{
77 char
78 message[MaxTextExtent],
79 tag[MaxTextExtent];
80
81 const char
82 *locale_message;
83
84 register char
85 *p;
86
87 if (extent < 2)
88 return(MagickTrue);
89 (void) CopyMagickMemory(tag,text,MaxTextExtent);
90 p=strrchr(tag,'/');
91 if (p != (char *) NULL)
92 *p='\0';
93 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
94 locale_message=GetLocaleMessage(message);
95 if (locale_message == message)
96 locale_message=tag;
97 if (p == (char *) NULL)
98 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
99 locale_message,(long) offset,(unsigned long) extent,(long)
100 (100L*offset/(extent-1)));
101 else
102 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
103 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
104 (100L*offset/(extent-1)));
105 if (offset == (MagickOffsetType) (extent-1))
106 (void) FormatLocaleFile(stderr,"\n");
107 (void) fflush(stderr);
108 return(MagickTrue);
109}
110
111/*
112** GetImageCache() will read an image into a image cache if not already
113** present then return the image that is in the cache under that filename.
114*/
115static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
116 ExceptionInfo *exception)
117{
118 char
119 key[MaxTextExtent];
120
121 ExceptionInfo
122 *sans_exception;
123
124 Image
125 *image;
126
127 ImageInfo
128 *read_info;
129
130 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
131 sans_exception=AcquireExceptionInfo();
132 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
133 sans_exception=DestroyExceptionInfo(sans_exception);
134 if (image != (Image *) NULL)
135 return(image);
136 read_info=CloneImageInfo(image_info);
137 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
138 image=ReadImage(read_info,exception);
139 read_info=DestroyImageInfo(read_info);
140 if (image != (Image *) NULL)
141 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
142 return(image);
143}
144
145/*
anthonya89dd172011-10-04 13:29:35 +0000146 SparseColorOption() parse the complex -sparse-color argument into an
147 an array of floating point values than call SparseColorImage().
148 Argument is a complex mix of floating-point pixel coodinates, and color
149 specifications (or direct floating point numbers). The number of floats
150 needed to represent a color varies depending on teh current channel
151 setting.
anthony805a2d42011-09-25 08:25:12 +0000152*/
153static Image *SparseColorOption(const Image *image,
154 const SparseColorMethod method,const char *arguments,
155 const MagickBooleanType color_from_image,ExceptionInfo *exception)
156{
157 char
158 token[MaxTextExtent];
159
160 const char
161 *p;
162
163 double
164 *sparse_arguments;
165
166 Image
167 *sparse_image;
168
169 PixelInfo
170 color;
171
172 MagickBooleanType
173 error;
174
175 register size_t
176 x;
177
178 size_t
179 number_arguments,
180 number_colors;
181
182 assert(image != (Image *) NULL);
183 assert(image->signature == MagickSignature);
184 if (image->debug != MagickFalse)
185 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
186 assert(exception != (ExceptionInfo *) NULL);
187 assert(exception->signature == MagickSignature);
188 /*
189 Limit channels according to image - and add up number of color channel.
190 */
191 number_colors=0;
192 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
193 number_colors++;
194 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
195 number_colors++;
196 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
197 number_colors++;
198 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
199 (image->colorspace == CMYKColorspace))
200 number_colors++;
201 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
202 (image->matte != MagickFalse))
203 number_colors++;
204
205 /*
206 Read string, to determine number of arguments needed,
207 */
208 p=arguments;
209 x=0;
210 while( *p != '\0' )
211 {
212 GetMagickToken(p,&p,token);
213 if ( token[0] == ',' ) continue;
214 if ( isalpha((int) token[0]) || token[0] == '#' ) {
215 if ( color_from_image ) {
216 (void) ThrowMagickException(exception,GetMagickModule(),
217 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
218 "Color arg given, when colors are coming from image");
219 return( (Image *)NULL);
220 }
221 x += number_colors; /* color argument */
222 }
223 else {
224 x++; /* floating point argument */
225 }
226 }
227 error=MagickTrue;
228 if ( color_from_image ) {
229 /* just the control points are being given */
230 error = ( x % 2 != 0 ) ? MagickTrue : MagickFalse;
231 number_arguments=(x/2)*(2+number_colors);
232 }
233 else {
234 /* control points and color values */
235 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
236 number_arguments=x;
237 }
238 if ( error ) {
239 (void) ThrowMagickException(exception,GetMagickModule(),
240 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
241 "Invalid number of Arguments");
242 return( (Image *)NULL);
243 }
244
245 /* Allocate and fill in the floating point arguments */
246 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
247 sizeof(*sparse_arguments));
248 if (sparse_arguments == (double *) NULL) {
249 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
250 "MemoryAllocationFailed","%s","SparseColorOption");
251 return( (Image *)NULL);
252 }
253 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
254 sizeof(*sparse_arguments));
255 p=arguments;
256 x=0;
257 while( *p != '\0' && x < number_arguments ) {
258 /* X coordinate */
259 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
260 if ( token[0] == '\0' ) break;
261 if ( isalpha((int) token[0]) || token[0] == '#' ) {
262 (void) ThrowMagickException(exception,GetMagickModule(),
263 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
264 "Color found, instead of X-coord");
265 error = MagickTrue;
266 break;
267 }
268 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
269 /* Y coordinate */
270 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
271 if ( token[0] == '\0' ) break;
272 if ( isalpha((int) token[0]) || token[0] == '#' ) {
273 (void) ThrowMagickException(exception,GetMagickModule(),
274 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
275 "Color found, instead of Y-coord");
276 error = MagickTrue;
277 break;
278 }
279 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
280 /* color values for this control point */
281#if 0
282 if ( (color_from_image ) {
283 /* get color from image */
284 /* HOW??? */
285 }
286 else
287#endif
288 {
289 /* color name or function given in string argument */
290 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
291 if ( token[0] == '\0' ) break;
292 if ( isalpha((int) token[0]) || token[0] == '#' ) {
293 /* Color string given */
anthony1afdc7a2011-10-05 11:54:28 +0000294 (void) QueryMagickColorCompliance(token,AllCompliance,&color,
anthonya89dd172011-10-04 13:29:35 +0000295 exception);
anthony805a2d42011-09-25 08:25:12 +0000296 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
297 sparse_arguments[x++] = QuantumScale*color.red;
298 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
299 sparse_arguments[x++] = QuantumScale*color.green;
300 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
301 sparse_arguments[x++] = QuantumScale*color.blue;
302 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
303 (image->colorspace == CMYKColorspace))
304 sparse_arguments[x++] = QuantumScale*color.black;
305 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
306 (image->matte != MagickFalse))
307 sparse_arguments[x++] = QuantumScale*color.alpha;
308 }
309 else {
310 /* Colors given as a set of floating point values - experimental */
311 /* NB: token contains the first floating point value to use! */
312 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
313 {
314 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
316 break;
317 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
318 token[0] = ','; /* used this token - get another */
319 }
320 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
321 {
322 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324 break;
325 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
326 token[0] = ','; /* used this token - get another */
327 }
328 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
329 {
330 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
331 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
332 break;
333 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
334 token[0] = ','; /* used this token - get another */
335 }
336 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
337 (image->colorspace == CMYKColorspace))
338 {
339 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
340 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
341 break;
342 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
343 token[0] = ','; /* used this token - get another */
344 }
345 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
346 (image->matte != MagickFalse))
347 {
348 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
349 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
350 break;
351 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
352 token[0] = ','; /* used this token - get another */
353 }
354 }
355 }
356 }
357 if ( number_arguments != x && !error ) {
358 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
359 "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
360 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
361 return( (Image *)NULL);
362 }
363 if ( error )
364 return( (Image *)NULL);
365
366 /* Call the Interpolation function with the parsed arguments */
367 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
368 exception);
369 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
370 return( sparse_image );
371}
372
373/*
374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375% %
376% %
377% %
anthony1afdc7a2011-10-05 11:54:28 +0000378+ A p p l y S e t t i n g O p t i o n %
anthony805a2d42011-09-25 08:25:12 +0000379% %
380% %
381% %
382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383%
anthony1afdc7a2011-10-05 11:54:28 +0000384% ApplySettingOption() saves the given single settings option into a CLI wand
385% holding the image_info, draw_info, quantize_info structures that is later
386% used for reading, processing, and writing images.
anthony805a2d42011-09-25 08:25:12 +0000387%
anthony1afdc7a2011-10-05 11:54:28 +0000388% No image in the wand is actually modified (setting options only)
anthony805a2d42011-09-25 08:25:12 +0000389%
anthony1afdc7a2011-10-05 11:54:28 +0000390% The format of the ApplySettingOption method is:
391%
392% MagickBooleanType ApplySettingOption(MagickWand *wand,
anthony805a2d42011-09-25 08:25:12 +0000393% const int argc, const char **argv,ExceptionInfo *exception)
394%
395% A description of each parameter follows:
396%
anthony1afdc7a2011-10-05 11:54:28 +0000397% o wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000398%
399% o argc: Specifies a pointer to an integer describing the number of
400% elements in the argument vector.
401%
402% o argv: Specifies a pointer to a text array containing the command line
403% arguments.
404%
405% o exception: return any errors or warnings in this structure.
406%
407*/
anthony74b1cfc2011-10-06 12:44:16 +0000408WandExport MagickBooleanType ApplySettingsOption(ImageInfo *image_info,
cristy0a0ca4f2011-09-28 01:15:28 +0000409 const int argc,const char **argv,ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000410{
411 GeometryInfo
412 geometry_info;
413
anthony1afdc7a2011-10-05 11:54:28 +0000414 ImageInfo
415 *image_info;
416
417 DrawInfo
anthony74b1cfc2011-10-06 12:44:16 +0000418 *draw_info;
419
420 const char
421 *option;
anthony1afdc7a2011-10-05 11:54:28 +0000422
423 assert(wand != (MagickWand *) NULL);
424 assert(wand->signature == WandSignature);
425 assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
426 assert(wand->quantize_info == (QuantizeInfo *) NULL);
427 if (wand->debug != MagickFalse)
428 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
anthony805a2d42011-09-25 08:25:12 +0000429 if (argc < 0)
430 return(MagickTrue);
anthony1afdc7a2011-10-05 11:54:28 +0000431
anthony74b1cfc2011-10-06 12:44:16 +0000432 option=argv[0]+1;
anthony1afdc7a2011-10-05 11:54:28 +0000433 image_info=wand->image_info;
434 draw_info=wand->_info;
435
anthony74b1cfc2011-10-06 12:44:16 +0000436#define DeleteOption (const char*)NULL
437#define IfSetOption ((*argv[0])=='-')
438
439 switch (*option)
anthony805a2d42011-09-25 08:25:12 +0000440 {
441 case 'a':
442 {
anthony74b1cfc2011-10-06 12:44:16 +0000443 if (LocaleCompare("adjoin",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000444 {
anthony74b1cfc2011-10-06 12:44:16 +0000445 image_info->adjoin = IfSetOption ? MagickTrue : MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000446 break;
447 }
anthony74b1cfc2011-10-06 12:44:16 +0000448 if (LocaleCompare("affine",option) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000449 {
anthony74b1cfc2011-10-06 12:44:16 +0000450 if (IfSetOption)
anthony1afdc7a2011-10-05 11:54:28 +0000451 (void) ParseAffineGeometry(argv[1],draw_info->affine,
452 exception);
anthony74b1cfc2011-10-06 12:44:16 +0000453 else
454 GetAffineMatrix(draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000455 break;
456 }
anthony74b1cfc2011-10-06 12:44:16 +0000457 if (LocaleCompare("antialias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000458 {
anthony1afdc7a2011-10-05 11:54:28 +0000459 image_info->antialias =
460 draw_info->stroke_antialias =
461 draw_info->text_antialias =
anthony74b1cfc2011-10-06 12:44:16 +0000462 IfSetOption ? MagickTrue : MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000463 break;
464 }
anthony74b1cfc2011-10-06 12:44:16 +0000465 if (LocaleCompare("authenticate",option) == 0)
anthony5f867ae2011-10-09 10:28:34 +0000466 {
anthony74b1cfc2011-10-06 12:44:16 +0000467 (void) SetImageOption(image_info,option,
468 IfSetOption ? argv[1] : DeleteOption);
anthony805a2d42011-09-25 08:25:12 +0000469 break;
470 }
471 break;
472 }
473 case 'b':
474 {
anthony74b1cfc2011-10-06 12:44:16 +0000475 if (LocaleCompare("background",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000476 {
anthony74b1cfc2011-10-06 12:44:16 +0000477 /* FUTURE: both image_info attribute & ImageOption in use!
478 Note that +background, means fall-back to image attribute
479 so ImageOption is deleted, not set to a default.
480 */
481 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000482 {
anthony74b1cfc2011-10-06 12:44:16 +0000483 (void) DeleteImageOption(image_info,option);
anthony1afdc7a2011-10-05 11:54:28 +0000484 (void) QueryColorCompliance(BackgroundColor,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000485 image_info->background_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000486 break;
487 }
anthony74b1cfc2011-10-06 12:44:16 +0000488 (void) SetImageOption(image_info,option,argv[1]);
anthony1afdc7a2011-10-05 11:54:28 +0000489 (void) QueryColorCompliance(argv[1],AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000490 image_info->background_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000491 break;
492 }
anthony74b1cfc2011-10-06 12:44:16 +0000493 if (LocaleCompare("bias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000494 {
anthony74b1cfc2011-10-06 12:44:16 +0000495 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
496 as it is actually rarely used except in direct convolve
497 Usage outside direct convolve is actally non-sensible!
498 */
499 (void) SetImageOption(image_info,option,
500 IfSetOption ? argv[1] : "0");
anthony805a2d42011-09-25 08:25:12 +0000501 break;
502 }
anthony74b1cfc2011-10-06 12:44:16 +0000503 if (LocaleCompare("black-point-compensation",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000504 {
anthony74b1cfc2011-10-06 12:44:16 +0000505 (void) SetImageOption(image_info,option,
506 IfSetOption ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +0000507 break;
508 }
anthony74b1cfc2011-10-06 12:44:16 +0000509 if (LocaleCompare("blue-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000510 {
anthony74b1cfc2011-10-06 12:44:16 +0000511 (void) SetImageOption(image_info,option,
512 IfSetOption ? argv[1] : "0" );
anthony805a2d42011-09-25 08:25:12 +0000513 break;
514 }
anthony74b1cfc2011-10-06 12:44:16 +0000515 if (LocaleCompare("bordercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000516 {
anthony74b1cfc2011-10-06 12:44:16 +0000517 /* FUTURE: both image_info attribute & ImageOption in use! */
518 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000519 {
anthony74b1cfc2011-10-06 12:44:16 +0000520 (void) SetImageOption(image_info,option,argv[1]);
521 (void) QueryColorCompliance(argv[1],AllCompliece,
522 &image_info->border_color,exception);
523 (void) QueryColorCompliance(argv[1],AllCompliance,
524 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000525 break;
526 }
anthony74b1cfc2011-10-06 12:44:16 +0000527 (void) DeleteImageOption(image_info,option);
528 (void) QueryColorCompliance(BorderColor,AllCompliance,
529 &image_info->border_color,exception);
530 (void) QueryColorCompliance(BorderColor,AllCompliance,
531 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000532 break;
533 }
anthony74b1cfc2011-10-06 12:44:16 +0000534 if (LocaleCompare("box",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000535 {
anthony74b1cfc2011-10-06 12:44:16 +0000536 const char
537 *value = IfSetOption ? argv[1] : "none";
538 (void) SetImageOption(image_info,option,value);
539 (void) QueryColorCompliance(value,AllCompliance,
540 &draw_info->undercolor,exception);
anthony805a2d42011-09-25 08:25:12 +0000541 break;
542 }
543 break;
544 }
545 case 'c':
546 {
anthony74b1cfc2011-10-06 12:44:16 +0000547 if (LocaleCompare("cache",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000548 {
549 MagickSizeType
550 limit;
551
552 limit=MagickResourceInfinity;
553 if (LocaleCompare("unlimited",argv[1]) != 0)
554 limit=(MagickSizeType) SiPrefixToDouble(argv[1],100.0);
555 (void) SetMagickResourceLimit(MemoryResource,limit);
556 (void) SetMagickResourceLimit(MapResource,2*limit);
557 break;
558 }
anthony74b1cfc2011-10-06 12:44:16 +0000559 if (LocaleCompare("caption",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000560 {
anthony74b1cfc2011-10-06 12:44:16 +0000561 (void) SetImageOption(image_info,option,
562 IfSetOption ? argv[1] : DeleteOption);
anthony805a2d42011-09-25 08:25:12 +0000563 break;
564 }
anthony74b1cfc2011-10-06 12:44:16 +0000565 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000566 {
anthony74b1cfc2011-10-06 12:44:16 +0000567 image_info->channel=(ChannelType) (
568 IfSetOption ? ParseChannelOption(argv[1]) : DefaultChannels );
anthony965524b2011-10-07 12:34:14 +0000569 /* This is also a SimpleImageOperator */
anthony805a2d42011-09-25 08:25:12 +0000570 break;
571 }
anthony74b1cfc2011-10-06 12:44:16 +0000572 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000573 {
anthony965524b2011-10-07 12:34:14 +0000574 /* This is also a SimpleImageOperator */
anthonyd2cdc862011-10-07 14:07:17 +0000575 /* Undefined colorspace means don't modify images */
anthony965524b2011-10-07 12:34:14 +0000576 image_info->colorspace=UndefinedColorspace;
anthonyd2cdc862011-10-07 14:07:17 +0000577 if (IfSetOption)
578 image_info->colorspace=(ColorspaceType) ParseCommandOption(
579 MagickColorspaceOptions,MagickFalse,argv[1])
anthony805a2d42011-09-25 08:25:12 +0000580 break;
581 }
anthony74b1cfc2011-10-06 12:44:16 +0000582 if (LocaleCompare("comment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000583 {
anthony965524b2011-10-07 12:34:14 +0000584 (void) SetImageOption(image_info,option,
585 IfSetOption ? argv[1] : DeleteOption);
anthony805a2d42011-09-25 08:25:12 +0000586 break;
587 }
anthony74b1cfc2011-10-06 12:44:16 +0000588 if (LocaleCompare("compose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000589 {
anthony965524b2011-10-07 12:34:14 +0000590 /* FUTURE: What should be used? image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000591 The former is more efficent, but Crisy prefers the latter!
anthony965524b2011-10-07 12:34:14 +0000592 */
anthony5f867ae2011-10-09 10:28:34 +0000593 (void) SetImageOption(image_info,option,
594 IfSetOption ? argv[1] : DeleteOption);
anthony965524b2011-10-07 12:34:14 +0000595 image_info->compose=(CompositeOperator) ParseCommandOption(
anthony5f867ae2011-10-09 10:28:34 +0000596 MagickComposeOptions,MagickFalse,
597 IfSetOption ? argv[1] : "undefined");
anthony805a2d42011-09-25 08:25:12 +0000598 break;
599 }
anthony74b1cfc2011-10-06 12:44:16 +0000600 if (LocaleCompare("compress",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000601 {
anthony5f867ae2011-10-09 10:28:34 +0000602 /* FUTURE: What should be used? image_info or ImageOption ???
603 The former is more efficent, but Crisy prefers the latter!
604
605 The coders appears to use image_info, not Image_Option
606 however the image attribute (for save) is set from the
607 ImageOption!
608 */
609 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000610 {
anthony5f867ae2011-10-09 10:28:34 +0000611 image_info->compression=(CompressionType) ParseCommandOption(
612 MagickCompressOptions,MagickFalse,argv[1]);
613 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000614 break;
615 }
anthony5f867ae2011-10-09 10:28:34 +0000616 image_info->compression=UndefinedCompression;
617 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000618 break;
619 }
620 break;
621 }
622 case 'd':
623 {
anthony74b1cfc2011-10-06 12:44:16 +0000624 if (LocaleCompare("debug",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000625 {
anthony5f867ae2011-10-09 10:28:34 +0000626 if (IfSetOption)
627 (void) SetLogEventMask(IfSetOption?argv[1]:"none");
628 image_info->debug=IsEventLogging(); /* extract logging*/
629 wand->debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000630 break;
631 }
anthony74b1cfc2011-10-06 12:44:16 +0000632 if (LocaleCompare("define",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000633 {
anthony5f867ae2011-10-09 10:28:34 +0000634 /* FUTURE both -set and -define sets ImageOption
635 But differs in that -set tried to set image properity (attribute)
636 */
anthony805a2d42011-09-25 08:25:12 +0000637 if (LocaleNCompare(argv[1],"registry:",9) == 0)
638 {
anthony5f867ae2011-10-09 10:28:34 +0000639 if (IfSetOption)
640 (void) DefineImageRegistry(StringRegistryType,argv[1]+9,
641 exception);
642 else
643 (void) DefineImageOption(image_info,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000644 break;
645 }
anthony5f867ae2011-10-09 10:28:34 +0000646 if (IfSetOption)
647 (void) DefineImageOption(image_info,argv[1]);
648 else
649 (void) DeleteImageOption(image_info,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000650 break;
651 }
anthony74b1cfc2011-10-06 12:44:16 +0000652 if (LocaleCompare("delay",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000653 {
anthony5f867ae2011-10-09 10:28:34 +0000654 /* transfered to new images only via AcquireImage()
655 -set delay must be used to set attributes directly.
656 */
657 (void) SetImageOption(image_info,option,
658 IfSetOption ? argv[1] : "0");
anthony805a2d42011-09-25 08:25:12 +0000659 break;
660 }
anthony74b1cfc2011-10-06 12:44:16 +0000661 if (LocaleCompare("density",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000662 {
anthony5f867ae2011-10-09 10:28:34 +0000663 /* FUTURE: At this time everyone is using image_info string
664 The Image Option is not being used.
anthony805a2d42011-09-25 08:25:12 +0000665 */
anthony5f867ae2011-10-09 10:28:34 +0000666 if (IsSetOption)
anthony805a2d42011-09-25 08:25:12 +0000667 {
anthony5f867ae2011-10-09 10:28:34 +0000668 (void) CloneString(&image_info->density,argv[1]);
669 (void) CloneString(&draw_info->density,argv[1]);
670 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000671 break;
672 }
anthony5f867ae2011-10-09 10:28:34 +0000673 if (image_info->density != (char *) NULL)
674 image_info->density=DestroyString(image_info->density);
675 if (draw_info->density != (char *) NULL)
676 draw_info->density=DestroyString(draw_info->density);
677 (void) SetImageOption(image_info,option,"72");
anthony805a2d42011-09-25 08:25:12 +0000678 break;
679 }
anthony74b1cfc2011-10-06 12:44:16 +0000680 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000681 {
anthony5f867ae2011-10-09 10:28:34 +0000682 /* This is also a SimpleImageOperator! */
683 image_info->depth=IsSetOption?StringToUnsignedLong(argv[1])
684 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000685 break;
686 }
anthony74b1cfc2011-10-06 12:44:16 +0000687 if (LocaleCompare("direction",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000688 {
anthony5f867ae2011-10-09 10:28:34 +0000689 /* Image Option is only used to det draw_info */
690 (void) SetImageOption(image_info,option,
691 IfSetOption ? argv[1] : "undefined");
692 draw_info->direction=(DirectionType) ParseCommandOption(
693 MagickDirectionOptions,MagickFalse,
694 IfSetOption ? argv[1] : "undefined");
anthony805a2d42011-09-25 08:25:12 +0000695 break;
696 }
anthony74b1cfc2011-10-06 12:44:16 +0000697 if (LocaleCompare("display",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000698 {
anthony5f867ae2011-10-09 10:28:34 +0000699 if (IfSetOption)
700 (void) CloneString(&image_info->server_name,argv[1]);
701 else
702 if (image_info->server_name != (char *) NULL)
703 image_info->server_name=DestroyString(image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000704 break;
705 }
anthony74b1cfc2011-10-06 12:44:16 +0000706 if (LocaleCompare("dispose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000707 {
anthony5f867ae2011-10-09 10:28:34 +0000708 (void) SetImageOption(image_info,option,
709 IfSetOption ? argv[1] : "undefined");
anthony805a2d42011-09-25 08:25:12 +0000710 break;
711 }
anthony74b1cfc2011-10-06 12:44:16 +0000712 if (LocaleCompare("dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000713 {
anthony5f867ae2011-10-09 10:28:34 +0000714 /* FUTURE: Merge boolean image_info->dither with Dither type */
715 (void) SetImageOption(image_info,option,
716 IfSetOption ? argv[1] : "none");
717 image_info->dither = quantize_info->dither =
718 IfSetOption?MagickTrue:MagickFalse;
719 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
720 MagickDitherOptions,MagickFalse,
721 IfSetOption ? argv[1] : "none");
722 if (quantize_info->dither_method == NoDitherMethod)
723 image_info->dither=quantize_info->dither=MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000724 break;
725 }
726 break;
727 }
728 case 'e':
729 {
anthony74b1cfc2011-10-06 12:44:16 +0000730 if (LocaleCompare("encoding",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000731 {
732 if (*argv[0] == '+')
733 {
anthony74b1cfc2011-10-06 12:44:16 +0000734 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000735 break;
736 }
anthony74b1cfc2011-10-06 12:44:16 +0000737 (void) SetImageOption(image_info,option,argv[1]);
anthony5f867ae2011-10-09 10:28:34 +0000738 (void) CloneString(&draw_info->encoding,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000739 break;
740 }
anthony74b1cfc2011-10-06 12:44:16 +0000741 if (LocaleCompare("endian",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000742 {
743 if (*argv[0] == '+')
744 {
745 image_info->endian=UndefinedEndian;
anthony74b1cfc2011-10-06 12:44:16 +0000746 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000747 break;
748 }
749 image_info->endian=(EndianType) ParseCommandOption(
750 MagickEndianOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +0000751 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000752 break;
753 }
anthony74b1cfc2011-10-06 12:44:16 +0000754 if (LocaleCompare("extract",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000755 {
756 /*
757 Set image extract geometry.
758 */
759 if (*argv[0] == '+')
760 {
761 if (image_info->extract != (char *) NULL)
762 image_info->extract=DestroyString(image_info->extract);
763 break;
764 }
765 (void) CloneString(&image_info->extract,argv[1]);
766 break;
767 }
768 break;
769 }
770 case 'f':
771 {
anthony74b1cfc2011-10-06 12:44:16 +0000772 if (LocaleCompare("fill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000773 {
774 if (*argv[0] == '+')
775 {
anthony74b1cfc2011-10-06 12:44:16 +0000776 (void) SetImageOption(image_info,option,"none");
anthony805a2d42011-09-25 08:25:12 +0000777 break;
778 }
anthony74b1cfc2011-10-06 12:44:16 +0000779 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000780 break;
781 }
anthony74b1cfc2011-10-06 12:44:16 +0000782 if (LocaleCompare("filter",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000783 {
784 if (*argv[0] == '+')
785 {
anthony74b1cfc2011-10-06 12:44:16 +0000786 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000787 break;
788 }
anthony74b1cfc2011-10-06 12:44:16 +0000789 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000790 break;
791 }
anthony74b1cfc2011-10-06 12:44:16 +0000792 if (LocaleCompare("font",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000793 {
794 if (*argv[0] == '+')
795 {
796 if (image_info->font != (char *) NULL)
797 image_info->font=DestroyString(image_info->font);
798 break;
799 }
800 (void) CloneString(&image_info->font,argv[1]);
801 break;
802 }
anthony74b1cfc2011-10-06 12:44:16 +0000803 if (LocaleCompare("format",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000804 {
805 register const char
806 *q;
807
808 for (q=strchr(argv[1],'%'); q != (char *) NULL; q=strchr(q+1,'%'))
809 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
810 image_info->ping=MagickFalse;
anthony74b1cfc2011-10-06 12:44:16 +0000811 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000812 break;
813 }
anthony74b1cfc2011-10-06 12:44:16 +0000814 if (LocaleCompare("fuzz",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000815 {
816 if (*argv[0] == '+')
817 {
818 image_info->fuzz=0.0;
anthony74b1cfc2011-10-06 12:44:16 +0000819 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +0000820 break;
821 }
822 image_info->fuzz=SiPrefixToDouble(argv[1],(double) QuantumRange+
823 1.0);
anthony74b1cfc2011-10-06 12:44:16 +0000824 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000825 break;
826 }
827 break;
828 }
829 case 'g':
830 {
anthony74b1cfc2011-10-06 12:44:16 +0000831 if (LocaleCompare("gravity",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000832 {
833 if (*argv[0] == '+')
834 {
anthony74b1cfc2011-10-06 12:44:16 +0000835 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000836 break;
837 }
anthony74b1cfc2011-10-06 12:44:16 +0000838 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000839 break;
840 }
anthony74b1cfc2011-10-06 12:44:16 +0000841 if (LocaleCompare("green-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000842 {
843 if (*argv[0] == '+')
844 {
anthony74b1cfc2011-10-06 12:44:16 +0000845 (void) SetImageOption(image_info,option,"0.0");
anthony805a2d42011-09-25 08:25:12 +0000846 break;
847 }
anthony74b1cfc2011-10-06 12:44:16 +0000848 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000849 break;
850 }
851 break;
852 }
853 case 'i':
854 {
anthony74b1cfc2011-10-06 12:44:16 +0000855 if (LocaleCompare("intent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000856 {
857 if (*argv[0] == '+')
858 {
anthony74b1cfc2011-10-06 12:44:16 +0000859 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000860 break;
861 }
anthony74b1cfc2011-10-06 12:44:16 +0000862 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000863 break;
864 }
anthony74b1cfc2011-10-06 12:44:16 +0000865 if (LocaleCompare("interlace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000866 {
867 if (*argv[0] == '+')
868 {
869 image_info->interlace=UndefinedInterlace;
anthony74b1cfc2011-10-06 12:44:16 +0000870 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000871 break;
872 }
873 image_info->interlace=(InterlaceType) ParseCommandOption(
874 MagickInterlaceOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +0000875 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000876 break;
877 }
anthony74b1cfc2011-10-06 12:44:16 +0000878 if (LocaleCompare("interline-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000879 {
880 if (*argv[0] == '+')
881 {
anthony74b1cfc2011-10-06 12:44:16 +0000882 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000883 break;
884 }
anthony74b1cfc2011-10-06 12:44:16 +0000885 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000886 break;
887 }
anthony74b1cfc2011-10-06 12:44:16 +0000888 if (LocaleCompare("interpolate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000889 {
890 if (*argv[0] == '+')
891 {
anthony74b1cfc2011-10-06 12:44:16 +0000892 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000893 break;
894 }
anthony74b1cfc2011-10-06 12:44:16 +0000895 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000896 break;
897 }
anthony74b1cfc2011-10-06 12:44:16 +0000898 if (LocaleCompare("interword-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000899 {
900 if (*argv[0] == '+')
901 {
anthony74b1cfc2011-10-06 12:44:16 +0000902 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000903 break;
904 }
anthony74b1cfc2011-10-06 12:44:16 +0000905 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000906 break;
907 }
908 break;
909 }
910 case 'k':
911 {
anthony74b1cfc2011-10-06 12:44:16 +0000912 if (LocaleCompare("kerning",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000913 {
914 if (*argv[0] == '+')
915 {
anthony74b1cfc2011-10-06 12:44:16 +0000916 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000917 break;
918 }
anthony74b1cfc2011-10-06 12:44:16 +0000919 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000920 break;
921 }
922 break;
923 }
924 case 'l':
925 {
anthony74b1cfc2011-10-06 12:44:16 +0000926 if (LocaleCompare("label",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000927 {
928 if (*argv[0] == '+')
929 {
anthony74b1cfc2011-10-06 12:44:16 +0000930 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +0000931 break;
932 }
anthony74b1cfc2011-10-06 12:44:16 +0000933 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000934 break;
935 }
anthony74b1cfc2011-10-06 12:44:16 +0000936 if (LocaleCompare("limit",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000937 {
938 MagickSizeType
939 limit;
940
941 ResourceType
942 type;
943
944 if (*argv[0] == '+')
945 break;
946 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
947 MagickFalse,argv[1]);
948 limit=MagickResourceInfinity;
949 if (LocaleCompare("unlimited",argv[2]) != 0)
950 limit=(MagickSizeType) SiPrefixToDouble(argv[2],100.0);
951 (void) SetMagickResourceLimit(type,limit);
952 break;
953 }
anthony74b1cfc2011-10-06 12:44:16 +0000954 if (LocaleCompare("list",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000955 {
956 ssize_t
957 list;
958
959 /*
960 Display configuration list.
961 */
962 list=ParseCommandOption(MagickListOptions,MagickFalse,argv[1]);
963 switch (list)
964 {
965 case MagickCoderOptions:
966 {
967 (void) ListCoderInfo((FILE *) NULL,exception);
968 break;
969 }
970 case MagickColorOptions:
971 {
972 (void) ListColorInfo((FILE *) NULL,exception);
973 break;
974 }
975 case MagickConfigureOptions:
976 {
977 (void) ListConfigureInfo((FILE *) NULL,exception);
978 break;
979 }
980 case MagickDelegateOptions:
981 {
982 (void) ListDelegateInfo((FILE *) NULL,exception);
983 break;
984 }
985 case MagickFontOptions:
986 {
987 (void) ListTypeInfo((FILE *) NULL,exception);
988 break;
989 }
990 case MagickFormatOptions:
991 {
992 (void) ListMagickInfo((FILE *) NULL,exception);
993 break;
994 }
995 case MagickLocaleOptions:
996 {
997 (void) ListLocaleInfo((FILE *) NULL,exception);
998 break;
999 }
1000 case MagickLogOptions:
1001 {
1002 (void) ListLogInfo((FILE *) NULL,exception);
1003 break;
1004 }
1005 case MagickMagicOptions:
1006 {
1007 (void) ListMagicInfo((FILE *) NULL,exception);
1008 break;
1009 }
1010 case MagickMimeOptions:
1011 {
1012 (void) ListMimeInfo((FILE *) NULL,exception);
1013 break;
1014 }
1015 case MagickModuleOptions:
1016 {
1017 (void) ListModuleInfo((FILE *) NULL,exception);
1018 break;
1019 }
1020 case MagickPolicyOptions:
1021 {
1022 (void) ListPolicyInfo((FILE *) NULL,exception);
1023 break;
1024 }
1025 case MagickResourceOptions:
1026 {
1027 (void) ListMagickResourceInfo((FILE *) NULL,exception);
1028 break;
1029 }
1030 case MagickThresholdOptions:
1031 {
1032 (void) ListThresholdMaps((FILE *) NULL,exception);
1033 break;
1034 }
1035 default:
1036 {
1037 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
1038 exception);
1039 break;
1040 }
1041 }
1042 break;
1043 }
anthony74b1cfc2011-10-06 12:44:16 +00001044 if (LocaleCompare("log",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001045 {
1046 if (*argv[0] == '+')
1047 break;
1048 (void) SetLogFormat(argv[1]);
1049 break;
1050 }
anthony74b1cfc2011-10-06 12:44:16 +00001051 if (LocaleCompare("loop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001052 {
1053 if (*argv[0] == '+')
1054 {
anthony74b1cfc2011-10-06 12:44:16 +00001055 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001056 break;
1057 }
anthony74b1cfc2011-10-06 12:44:16 +00001058 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001059 break;
1060 }
1061 break;
1062 }
1063 case 'm':
1064 {
anthony74b1cfc2011-10-06 12:44:16 +00001065 if (LocaleCompare("matte",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001066 {
1067 if (*argv[0] == '+')
1068 {
anthony74b1cfc2011-10-06 12:44:16 +00001069 (void) SetImageOption(image_info,option,"false");
anthony805a2d42011-09-25 08:25:12 +00001070 break;
1071 }
anthony74b1cfc2011-10-06 12:44:16 +00001072 (void) SetImageOption(image_info,option,"true");
anthony805a2d42011-09-25 08:25:12 +00001073 break;
1074 }
anthony74b1cfc2011-10-06 12:44:16 +00001075 if (LocaleCompare("mattecolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001076 {
1077 if (*argv[0] == '+')
1078 {
anthony74b1cfc2011-10-06 12:44:16 +00001079 (void) SetImageOption(image_info,option,argv[1]);
anthony1afdc7a2011-10-05 11:54:28 +00001080 (void) QueryColorCompliance(MatteColor,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00001081 &image_info->matte_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001082 break;
1083 }
anthony74b1cfc2011-10-06 12:44:16 +00001084 (void) SetImageOption(image_info,option,argv[1]);
anthony1afdc7a2011-10-05 11:54:28 +00001085 (void) QueryColorCompliance(argv[1],AllCompliance,&image_info->matte_color,
anthony805a2d42011-09-25 08:25:12 +00001086 exception);
1087 break;
1088 }
anthony74b1cfc2011-10-06 12:44:16 +00001089 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001090 {
1091 (void) SetImageInfoProgressMonitor(image_info,MonitorProgress,
1092 (void *) NULL);
1093 break;
1094 }
anthony74b1cfc2011-10-06 12:44:16 +00001095 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001096 {
1097 image_info->monochrome=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1098 break;
1099 }
1100 break;
1101 }
1102 case 'o':
1103 {
anthony74b1cfc2011-10-06 12:44:16 +00001104 if (LocaleCompare("orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001105 {
1106 if (*argv[0] == '+')
1107 {
1108 image_info->orientation=UndefinedOrientation;
anthony74b1cfc2011-10-06 12:44:16 +00001109 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +00001110 break;
1111 }
1112 image_info->orientation=(OrientationType) ParseCommandOption(
1113 MagickOrientationOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001114 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001115 break;
1116 }
1117 }
1118 case 'p':
1119 {
anthony74b1cfc2011-10-06 12:44:16 +00001120 if (LocaleCompare("page",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001121 {
1122 char
1123 *canonical_page,
1124 page[MaxTextExtent];
1125
1126 const char
1127 *image_option;
1128
1129 MagickStatusType
1130 flags;
1131
1132 RectangleInfo
1133 geometry;
1134
1135 if (*argv[0] == '+')
1136 {
anthony74b1cfc2011-10-06 12:44:16 +00001137 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +00001138 (void) CloneString(&image_info->page,(char *) NULL);
1139 break;
1140 }
1141 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1142 image_option=GetImageOption(image_info,"page");
1143 if (image_option != (const char *) NULL)
1144 flags=ParseAbsoluteGeometry(image_option,&geometry);
1145 canonical_page=GetPageGeometry(argv[1]);
1146 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1147 canonical_page=DestroyString(canonical_page);
1148 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1149 (unsigned long) geometry.width,(unsigned long) geometry.height);
1150 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1151 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1152 (unsigned long) geometry.width,(unsigned long) geometry.height,
1153 (long) geometry.x,(long) geometry.y);
anthony74b1cfc2011-10-06 12:44:16 +00001154 (void) SetImageOption(image_info,option,page);
anthony805a2d42011-09-25 08:25:12 +00001155 (void) CloneString(&image_info->page,page);
1156 break;
1157 }
anthony74b1cfc2011-10-06 12:44:16 +00001158 if (LocaleCompare("pen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001159 {
1160 if (*argv[0] == '+')
1161 {
anthony74b1cfc2011-10-06 12:44:16 +00001162 (void) SetImageOption(image_info,option,"none");
anthony805a2d42011-09-25 08:25:12 +00001163 break;
1164 }
anthony74b1cfc2011-10-06 12:44:16 +00001165 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001166 break;
1167 }
anthony74b1cfc2011-10-06 12:44:16 +00001168 if (LocaleCompare("ping",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001169 {
1170 image_info->ping=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1171 break;
1172 }
anthony74b1cfc2011-10-06 12:44:16 +00001173 if (LocaleCompare("pointsize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001174 {
1175 if (*argv[0] == '+')
1176 geometry_info.rho=0.0;
1177 else
1178 (void) ParseGeometry(argv[1],&geometry_info);
1179 image_info->pointsize=geometry_info.rho;
1180 break;
1181 }
anthony74b1cfc2011-10-06 12:44:16 +00001182 if (LocaleCompare("precision",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001183 {
1184 (void) SetMagickPrecision(StringToInteger(argv[1]));
1185 break;
1186 }
anthony74b1cfc2011-10-06 12:44:16 +00001187 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001188 {
1189 /*
1190 Preview image.
1191 */
1192 if (*argv[0] == '+')
1193 {
1194 image_info->preview_type=UndefinedPreview;
1195 break;
1196 }
1197 image_info->preview_type=(PreviewType) ParseCommandOption(
1198 MagickPreviewOptions,MagickFalse,argv[1]);
1199 break;
1200 }
1201 break;
1202 }
1203 case 'q':
1204 {
anthony74b1cfc2011-10-06 12:44:16 +00001205 if (LocaleCompare("quality",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001206 {
1207 /*
1208 Set image compression quality.
1209 */
1210 if (*argv[0] == '+')
1211 {
1212 image_info->quality=UndefinedCompressionQuality;
anthony74b1cfc2011-10-06 12:44:16 +00001213 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001214 break;
1215 }
1216 image_info->quality=StringToUnsignedLong(argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001217 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001218 break;
1219 }
anthony74b1cfc2011-10-06 12:44:16 +00001220 if (LocaleCompare("quiet",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001221 {
1222 static WarningHandler
1223 warning_handler = (WarningHandler) NULL;
1224
1225 if (*argv[0] == '+')
1226 {
1227 /*
1228 Restore error or warning messages.
1229 */
1230 warning_handler=SetWarningHandler(warning_handler);
1231 break;
1232 }
1233 /*
1234 Suppress error or warning messages.
1235 */
1236 warning_handler=SetWarningHandler((WarningHandler) NULL);
1237 break;
1238 }
1239 break;
1240 }
1241 case 'r':
1242 {
anthony74b1cfc2011-10-06 12:44:16 +00001243 if (LocaleCompare("red-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001244 {
1245 if (*argv[0] == '+')
1246 {
anthony74b1cfc2011-10-06 12:44:16 +00001247 (void) SetImageOption(image_info,option,"0.0");
anthony805a2d42011-09-25 08:25:12 +00001248 break;
1249 }
anthony74b1cfc2011-10-06 12:44:16 +00001250 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001251 break;
1252 }
1253 break;
1254 }
1255 case 's':
1256 {
anthony74b1cfc2011-10-06 12:44:16 +00001257 if (LocaleCompare("sampling-factor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001258 {
1259 /*
1260 Set image sampling factor.
1261 */
1262 if (*argv[0] == '+')
1263 {
1264 if (image_info->sampling_factor != (char *) NULL)
1265 image_info->sampling_factor=DestroyString(
1266 image_info->sampling_factor);
1267 break;
1268 }
1269 (void) CloneString(&image_info->sampling_factor,argv[1]);
1270 break;
1271 }
anthony74b1cfc2011-10-06 12:44:16 +00001272 if (LocaleCompare("scene",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001273 {
1274 /*
1275 Set image scene.
1276 */
1277 if (*argv[0] == '+')
1278 {
1279 image_info->scene=0;
anthony74b1cfc2011-10-06 12:44:16 +00001280 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001281 break;
1282 }
1283 image_info->scene=StringToUnsignedLong(argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001284 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001285 break;
1286 }
anthony74b1cfc2011-10-06 12:44:16 +00001287 if (LocaleCompare("seed",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001288 {
1289 size_t
1290 seed;
1291
1292 if (*argv[0] == '+')
1293 {
1294 seed=(size_t) time((time_t *) NULL);
1295 SeedPseudoRandomGenerator(seed);
1296 break;
1297 }
1298 seed=StringToUnsignedLong(argv[1]);
1299 SeedPseudoRandomGenerator(seed);
1300 break;
1301 }
anthony74b1cfc2011-10-06 12:44:16 +00001302 if (LocaleCompare("size",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001303 {
anthony74b1cfc2011-10-06 12:44:16 +00001304 /* FUTURE: convert to ImageOption
1305 Look at special handling for "size" in SetImageOption()
1306 */
anthony805a2d42011-09-25 08:25:12 +00001307 if (*argv[0] == '+')
1308 {
1309 if (image_info->size != (char *) NULL)
1310 image_info->size=DestroyString(image_info->size);
1311 break;
1312 }
1313 (void) CloneString(&image_info->size,argv[1]);
1314 break;
1315 }
anthony74b1cfc2011-10-06 12:44:16 +00001316 if (LocaleCompare("stroke",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001317 {
1318 if (*argv[0] == '+')
1319 {
anthony74b1cfc2011-10-06 12:44:16 +00001320 (void) SetImageOption(image_info,option,"none");
anthony805a2d42011-09-25 08:25:12 +00001321 break;
1322 }
anthony74b1cfc2011-10-06 12:44:16 +00001323 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001324 break;
1325 }
anthony74b1cfc2011-10-06 12:44:16 +00001326 if (LocaleCompare("strokewidth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001327 {
1328 if (*argv[0] == '+')
1329 {
anthony74b1cfc2011-10-06 12:44:16 +00001330 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001331 break;
1332 }
anthony74b1cfc2011-10-06 12:44:16 +00001333 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001334 break;
1335 }
anthony74b1cfc2011-10-06 12:44:16 +00001336 if (LocaleCompare("synchronize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001337 {
1338 if (*argv[0] == '+')
1339 {
1340 image_info->synchronize=MagickFalse;
1341 break;
1342 }
1343 image_info->synchronize=MagickTrue;
1344 break;
1345 }
1346 break;
1347 }
1348 case 't':
1349 {
anthony74b1cfc2011-10-06 12:44:16 +00001350 if (LocaleCompare("taint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001351 {
1352 if (*argv[0] == '+')
1353 {
anthony74b1cfc2011-10-06 12:44:16 +00001354 (void) SetImageOption(image_info,option,"false");
anthony805a2d42011-09-25 08:25:12 +00001355 break;
1356 }
anthony74b1cfc2011-10-06 12:44:16 +00001357 (void) SetImageOption(image_info,option,"true");
anthony805a2d42011-09-25 08:25:12 +00001358 break;
1359 }
anthony74b1cfc2011-10-06 12:44:16 +00001360 if (LocaleCompare("texture",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001361 {
1362 if (*argv[0] == '+')
1363 {
1364 if (image_info->texture != (char *) NULL)
1365 image_info->texture=DestroyString(image_info->texture);
1366 break;
1367 }
1368 (void) CloneString(&image_info->texture,argv[1]);
1369 break;
1370 }
anthony74b1cfc2011-10-06 12:44:16 +00001371 if (LocaleCompare("tile-offset",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001372 {
1373 if (*argv[0] == '+')
1374 {
anthony74b1cfc2011-10-06 12:44:16 +00001375 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001376 break;
1377 }
anthony74b1cfc2011-10-06 12:44:16 +00001378 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001379 break;
1380 }
anthony74b1cfc2011-10-06 12:44:16 +00001381 if (LocaleCompare("transparent-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001382 {
1383 if (*argv[0] == '+')
1384 {
anthony1afdc7a2011-10-05 11:54:28 +00001385 (void) QueryColorCompliance("none",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00001386 &image_info->transparent_color,exception);
anthony74b1cfc2011-10-06 12:44:16 +00001387 (void) SetImageOption(image_info,option,"none");
anthony805a2d42011-09-25 08:25:12 +00001388 break;
1389 }
anthony1afdc7a2011-10-05 11:54:28 +00001390 (void) QueryColorCompliance("none",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00001391 &image_info->transparent_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001392 exception);
anthony74b1cfc2011-10-06 12:44:16 +00001393 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001394 break;
1395 }
anthony74b1cfc2011-10-06 12:44:16 +00001396 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001397 {
1398 if (*argv[0] == '+')
1399 {
1400 image_info->type=UndefinedType;
anthony74b1cfc2011-10-06 12:44:16 +00001401 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +00001402 break;
1403 }
1404 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1405 MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001406 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001407 break;
1408 }
1409 break;
1410 }
1411 case 'u':
1412 {
anthony74b1cfc2011-10-06 12:44:16 +00001413 if (LocaleCompare("undercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001414 {
1415 if (*argv[0] == '+')
1416 {
anthony74b1cfc2011-10-06 12:44:16 +00001417 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +00001418 break;
1419 }
anthony74b1cfc2011-10-06 12:44:16 +00001420 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001421 break;
1422 }
anthony74b1cfc2011-10-06 12:44:16 +00001423 if (LocaleCompare("units",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001424 {
1425 if (*argv[0] == '+')
1426 {
1427 image_info->units=UndefinedResolution;
anthony74b1cfc2011-10-06 12:44:16 +00001428 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +00001429 break;
1430 }
1431 image_info->units=(ResolutionType) ParseCommandOption(
1432 MagickResolutionOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001433 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001434 break;
1435 }
1436 break;
1437 }
1438 case 'v':
1439 {
anthony74b1cfc2011-10-06 12:44:16 +00001440 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001441 {
1442 if (*argv[0] == '+')
1443 {
1444 image_info->verbose=MagickFalse;
1445 break;
1446 }
1447 image_info->verbose=MagickTrue;
1448 image_info->ping=MagickFalse;
1449 break;
1450 }
anthony74b1cfc2011-10-06 12:44:16 +00001451 if (LocaleCompare("view",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001452 {
1453 if (*argv[0] == '+')
1454 {
1455 if (image_info->view != (char *) NULL)
1456 image_info->view=DestroyString(image_info->view);
1457 break;
1458 }
1459 (void) CloneString(&image_info->view,argv[1]);
1460 break;
1461 }
anthony74b1cfc2011-10-06 12:44:16 +00001462 if (LocaleCompare("virtual-pixel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001463 {
1464 if (*argv[0] == '+')
1465 {
1466 image_info->virtual_pixel_method=UndefinedVirtualPixelMethod;
anthony74b1cfc2011-10-06 12:44:16 +00001467 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +00001468 break;
1469 }
1470 image_info->virtual_pixel_method=(VirtualPixelMethod)
1471 ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001472 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001473 break;
1474 }
1475 break;
1476 }
1477 case 'w':
1478 {
anthony74b1cfc2011-10-06 12:44:16 +00001479 if (LocaleCompare("white-point",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001480 {
1481 if (*argv[0] == '+')
1482 {
anthony74b1cfc2011-10-06 12:44:16 +00001483 (void) SetImageOption(image_info,option,"0.0");
anthony805a2d42011-09-25 08:25:12 +00001484 break;
1485 }
anthony74b1cfc2011-10-06 12:44:16 +00001486 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001487 break;
1488 }
1489 break;
1490 }
1491 default:
1492 break;
1493 }
1494 return(MagickTrue);
1495}
1496
1497/*
1498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1499% %
1500% %
1501% %
anthony74b1cfc2011-10-06 12:44:16 +00001502+ A p p l y I m a g e O p e r a t o r %
anthony805a2d42011-09-25 08:25:12 +00001503% %
1504% %
1505% %
1506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1507%
anthony74b1cfc2011-10-06 12:44:16 +00001508% ApplyImageOperator() apply one simple image operation to just the current
1509% image.
anthony805a2d42011-09-25 08:25:12 +00001510%
1511% The image in the list may be modified in three different ways...
1512%
1513% * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1514% * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1515% * replace by a list of images (-separate and -crop only!)
1516%
1517% In each case the result is returned into the list, and the pointer to the
1518% modified image (last image added if replaced by a list of images) is
1519% returned. As the image pointed to may be replaced, the first image in the
1520% list may also change. GetFirstImageInList() should be used by caller if
1521% they wish return the Image pointer to the first image in list.
1522%
anthony74b1cfc2011-10-06 12:44:16 +00001523% The format of the ApplyImageOperator method is:
anthony805a2d42011-09-25 08:25:12 +00001524%
anthony74b1cfc2011-10-06 12:44:16 +00001525% MagickBooleanType ApplyImageOperator(MagickWand *wand,
1526% const int argc,const char **argv)
anthony805a2d42011-09-25 08:25:12 +00001527%
1528% A description of each parameter follows:
1529%
anthony74b1cfc2011-10-06 12:44:16 +00001530% o wand: The CLI wand holding all the settings and pointer to image
anthony805a2d42011-09-25 08:25:12 +00001531%
1532% o argc: Specifies a pointer to an integer describing the number of
1533% elements in the argument vector.
1534%
1535% o argv: Specifies a pointer to a text array containing the command line
1536% arguments.
1537%
anthony805a2d42011-09-25 08:25:12 +00001538% o exception: return any errors or warnings in this structure.
1539%
1540*/
anthony74b1cfc2011-10-06 12:44:16 +00001541MagickExport MagickBooleanType ApplyImageOperator(MagickWand *wand,
1542 const int wand_unused(argc), const char **argv, ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +00001543{
1544 Image *
1545 new_image;
1546
1547 ChannelType
1548 channel;
1549
anthony5f867ae2011-10-09 10:28:34 +00001550 ComposeOperation
1551 compose;
1552
anthony805a2d42011-09-25 08:25:12 +00001553 const char
1554 *format;
1555
1556 DrawInfo
1557 *draw_info;
1558
1559 GeometryInfo
1560 geometry_info;
1561
1562 RectangleInfo
1563 geometry;
1564
1565 MagickStatusType
1566 status;
1567
1568 PixelInfo
1569 fill;
1570
1571 MagickStatusType
1572 flags;
1573
1574 QuantizeInfo
1575 *quantize_info;
1576
1577 assert(image_info != (const ImageInfo *) NULL);
1578 assert(image_info->signature == MagickSignature);
1579 assert(image != (Image **) NULL);
1580 assert((*image)->signature == MagickSignature);
1581 if ((*image)->debug != MagickFalse)
1582 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
anthonya89dd172011-10-04 13:29:35 +00001583 if (argc < 0)
1584 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00001585 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
1586 quantize_info=AcquireQuantizeInfo(image_info);
1587 SetGeometryInfo(&geometry_info);
1588 GetPixelInfo(*image,&fill);
1589 SetPixelInfoPacket(*image,&(*image)->background_color,&fill);
1590 channel=image_info->channel;
1591 format=GetImageOption(image_info,"format");
1592
1593 new_image = (Image *)NULL;
1594
1595 switch (*(argv[0]+1))
1596 {
1597 case 'a':
1598 {
1599 if (LocaleCompare("adaptive-blur",argv[0]+1) == 0)
1600 {
anthony805a2d42011-09-25 08:25:12 +00001601 (void) SyncImageSettings(image_info,*image);
1602 flags=ParseGeometry(argv[1],&geometry_info);
1603 if ((flags & SigmaValue) == 0)
1604 geometry_info.sigma=1.0;
1605 if ((flags & XiValue) == 0)
1606 geometry_info.xi=0.0;
1607 new_image=AdaptiveBlurImage(*image,geometry_info.rho,
1608 geometry_info.sigma,geometry_info.xi,exception);
1609 break;
1610 }
1611 if (LocaleCompare("adaptive-resize",argv[0]+1) == 0)
1612 {
anthony1afdc7a2011-10-05 11:54:28 +00001613 /* FUTURE: this is really a "interpolate-resize" operator
1614 "adaptive-resize" uses a fixed "Mesh" interpolation
anthony805a2d42011-09-25 08:25:12 +00001615 */
1616 (void) SyncImageSettings(image_info,*image);
1617 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
1618 new_image=AdaptiveResizeImage(*image,geometry.width,
anthonya89dd172011-10-04 13:29:35 +00001619 geometry.height,interpolate_method,exception);
anthony805a2d42011-09-25 08:25:12 +00001620 break;
1621 }
1622 if (LocaleCompare("adaptive-sharpen",argv[0]+1) == 0)
1623 {
1624 /*
1625 Adaptive sharpen image.
1626 */
1627 (void) SyncImageSettings(image_info,*image);
1628 flags=ParseGeometry(argv[1],&geometry_info);
1629 if ((flags & SigmaValue) == 0)
1630 geometry_info.sigma=1.0;
1631 if ((flags & XiValue) == 0)
1632 geometry_info.xi=0.0;
1633 new_image=AdaptiveSharpenImage(*image,geometry_info.rho,
1634 geometry_info.sigma,geometry_info.xi,exception);
1635 break;
1636 }
anthony805a2d42011-09-25 08:25:12 +00001637 if (LocaleCompare("alpha",argv[0]+1) == 0)
1638 {
1639 AlphaChannelType
1640 alpha_type;
1641
1642 (void) SyncImageSettings(image_info,*image);
1643 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
1644 MagickFalse,argv[1]);
1645 (void) SetImageAlphaChannel(*image,alpha_type,exception);
1646 break;
1647 }
1648 if (LocaleCompare("annotate",argv[0]+1) == 0)
1649 {
1650 char
1651 *text,
1652 geometry[MaxTextExtent];
1653
anthony805a2d42011-09-25 08:25:12 +00001654 (void) SyncImageSettings(image_info,*image);
1655 SetGeometryInfo(&geometry_info);
1656 flags=ParseGeometry(argv[1],&geometry_info);
1657 if ((flags & SigmaValue) == 0)
1658 geometry_info.sigma=geometry_info.rho;
1659 text=InterpretImageProperties(image_info,*image,argv[2],
1660 exception);
1661 if (text == (char *) NULL)
1662 break;
1663 (void) CloneString(&draw_info->text,text);
1664 text=DestroyString(text);
1665 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1666 geometry_info.xi,geometry_info.psi);
1667 (void) CloneString(&draw_info->geometry,geometry);
1668 draw_info->affine.sx=cos(DegreesToRadians(
1669 fmod(geometry_info.rho,360.0)));
1670 draw_info->affine.rx=sin(DegreesToRadians(
1671 fmod(geometry_info.rho,360.0)));
1672 draw_info->affine.ry=(-sin(DegreesToRadians(
1673 fmod(geometry_info.sigma,360.0))));
1674 draw_info->affine.sy=cos(DegreesToRadians(
1675 fmod(geometry_info.sigma,360.0)));
1676 (void) AnnotateImage(*image,draw_info,exception);
1677 break;
1678 }
anthony805a2d42011-09-25 08:25:12 +00001679 if (LocaleCompare("auto-gamma",argv[0]+1) == 0)
1680 {
1681 /*
1682 Auto Adjust Gamma of image based on its mean
1683 */
1684 (void) SyncImageSettings(image_info,*image);
1685 (void) AutoGammaImage(*image,exception);
1686 break;
1687 }
1688 if (LocaleCompare("auto-level",argv[0]+1) == 0)
1689 {
1690 /*
1691 Perfectly Normalize (max/min stretch) the image
1692 */
1693 (void) SyncImageSettings(image_info,*image);
1694 (void) AutoLevelImage(*image,exception);
1695 break;
1696 }
1697 if (LocaleCompare("auto-orient",argv[0]+1) == 0)
1698 {
1699 (void) SyncImageSettings(image_info,*image);
1700 switch ((*image)->orientation)
1701 {
1702 case TopRightOrientation:
1703 {
1704 new_image=FlopImage(*image,exception);
1705 break;
1706 }
1707 case BottomRightOrientation:
1708 {
1709 new_image=RotateImage(*image,180.0,exception);
1710 break;
1711 }
1712 case BottomLeftOrientation:
1713 {
1714 new_image=FlipImage(*image,exception);
1715 break;
1716 }
1717 case LeftTopOrientation:
1718 {
1719 new_image=TransposeImage(*image,exception);
1720 break;
1721 }
1722 case RightTopOrientation:
1723 {
1724 new_image=RotateImage(*image,90.0,exception);
1725 break;
1726 }
1727 case RightBottomOrientation:
1728 {
1729 new_image=TransverseImage(*image,exception);
1730 break;
1731 }
1732 case LeftBottomOrientation:
1733 {
1734 new_image=RotateImage(*image,270.0,exception);
1735 break;
1736 }
1737 default:
1738 break;
1739 }
1740 if (new_image != (Image *) NULL)
1741 new_image->orientation=TopLeftOrientation;
1742 break;
1743 }
1744 break;
1745 }
1746 case 'b':
1747 {
1748 if (LocaleCompare("black-threshold",argv[0]+1) == 0)
1749 {
anthony805a2d42011-09-25 08:25:12 +00001750 (void) SyncImageSettings(image_info,*image);
1751 (void) BlackThresholdImage(*image,argv[1],exception);
1752 InheritException(exception,&(*image)->exception);
1753 break;
1754 }
1755 if (LocaleCompare("blue-shift",argv[0]+1) == 0)
1756 {
anthony805a2d42011-09-25 08:25:12 +00001757 (void) SyncImageSettings(image_info,*image);
1758 geometry_info.rho=1.5;
1759 if (*argv[0] == '-')
1760 flags=ParseGeometry(argv[1],&geometry_info);
1761 new_image=BlueShiftImage(*image,geometry_info.rho,exception);
1762 break;
1763 }
1764 if (LocaleCompare("blur",argv[0]+1) == 0)
1765 {
anthony74b1cfc2011-10-06 12:44:16 +00001766 /* FUTURE: use of "bias" in a blur is non-sensible */
anthony805a2d42011-09-25 08:25:12 +00001767 (void) SyncImageSettings(image_info,*image);
1768 flags=ParseGeometry(argv[1],&geometry_info);
1769 if ((flags & SigmaValue) == 0)
1770 geometry_info.sigma=1.0;
1771 if ((flags & XiValue) == 0)
1772 geometry_info.xi=0.0;
1773 new_image=BlurImage(*image,geometry_info.rho,
1774 geometry_info.sigma,geometry_info.xi,exception);
1775 break;
1776 }
1777 if (LocaleCompare("border",argv[0]+1) == 0)
1778 {
anthony5f867ae2011-10-09 10:28:34 +00001779 ComposeOperator
1780 compose;
1781
1782 const char*
1783 const char*
1784 value;
1785
1786 value=GetImageOption(image_info,"compose");
1787 if (value != (const char *) NULL)
1788 compose=(CompositeOperator) ParseCommandOption(
1789 MagickComposeOptions,MagickFalse,value);
1790 else
1791 compose=OverCompositeOp; /* use Over not image->compose */
1792
anthony805a2d42011-09-25 08:25:12 +00001793 (void) SyncImageSettings(image_info,*image);
1794 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
1795 if ((flags & SigmaValue) == 0)
1796 geometry.height=geometry.width;
anthonya89dd172011-10-04 13:29:35 +00001797 new_image=BorderImage(*image,&geometry,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00001798 break;
1799 }
anthony805a2d42011-09-25 08:25:12 +00001800 if (LocaleCompare("brightness-contrast",argv[0]+1) == 0)
1801 {
1802 double
1803 brightness,
1804 contrast;
1805
1806 GeometryInfo
1807 geometry_info;
1808
1809 MagickStatusType
1810 flags;
1811
anthony805a2d42011-09-25 08:25:12 +00001812 (void) SyncImageSettings(image_info,*image);
1813 flags=ParseGeometry(argv[1],&geometry_info);
1814 brightness=geometry_info.rho;
1815 contrast=0.0;
1816 if ((flags & SigmaValue) != 0)
1817 contrast=geometry_info.sigma;
1818 (void) BrightnessContrastImage(*image,brightness,contrast,
1819 exception);
1820 InheritException(exception,&(*image)->exception);
1821 break;
1822 }
1823 break;
1824 }
1825 case 'c':
1826 {
1827 if (LocaleCompare("cdl",argv[0]+1) == 0)
1828 {
1829 char
1830 *color_correction_collection;
1831
1832 /*
1833 Color correct with a color decision list.
1834 */
1835 (void) SyncImageSettings(image_info,*image);
1836 color_correction_collection=FileToString(argv[1],~0,exception);
1837 if (color_correction_collection == (char *) NULL)
1838 break;
1839 (void) ColorDecisionListImage(*image,color_correction_collection,
1840 exception);
1841 InheritException(exception,&(*image)->exception);
1842 break;
1843 }
1844 if (LocaleCompare("channel",argv[0]+1) == 0)
1845 {
anthony74b1cfc2011-10-06 12:44:16 +00001846 /* The "channel" setting has already been set */
1847 SetPixelChannelMap(*image,image_info->channel);
anthony805a2d42011-09-25 08:25:12 +00001848 break;
1849 }
1850 if (LocaleCompare("charcoal",argv[0]+1) == 0)
1851 {
anthony805a2d42011-09-25 08:25:12 +00001852 (void) SyncImageSettings(image_info,*image);
1853 flags=ParseGeometry(argv[1],&geometry_info);
1854 if ((flags & SigmaValue) == 0)
1855 geometry_info.sigma=1.0;
1856 if ((flags & XiValue) == 0)
1857 geometry_info.xi=1.0;
1858 new_image=CharcoalImage(*image,geometry_info.rho,
1859 geometry_info.sigma,geometry_info.xi,exception);
1860 break;
1861 }
1862 if (LocaleCompare("chop",argv[0]+1) == 0)
1863 {
anthony805a2d42011-09-25 08:25:12 +00001864 (void) SyncImageSettings(image_info,*image);
1865 (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
1866 new_image=ChopImage(*image,&geometry,exception);
1867 break;
1868 }
1869 if (LocaleCompare("clamp",argv[0]+1) == 0)
1870 {
anthony805a2d42011-09-25 08:25:12 +00001871 (void) SyncImageSettings(image_info,*image);
1872 (void) ClampImage(*image);
1873 InheritException(exception,&(*image)->exception);
1874 break;
1875 }
1876 if (LocaleCompare("clip",argv[0]+1) == 0)
1877 {
1878 (void) SyncImageSettings(image_info,*image);
1879 if (*argv[0] == '+')
1880 {
1881 (void) SetImageClipMask(*image,(Image *) NULL,exception);
1882 break;
1883 }
1884 (void) ClipImage(*image,exception);
1885 break;
1886 }
1887 if (LocaleCompare("clip-mask",argv[0]+1) == 0)
1888 {
1889 CacheView
1890 *mask_view;
1891
1892 Image
1893 *mask_image;
1894
1895 register Quantum
1896 *restrict q;
1897
1898 register ssize_t
1899 x;
1900
1901 ssize_t
1902 y;
1903
1904 (void) SyncImageSettings(image_info,*image);
1905 if (*argv[0] == '+')
1906 {
anthony74b1cfc2011-10-06 12:44:16 +00001907 /* Remove the write mask */
anthony805a2d42011-09-25 08:25:12 +00001908 (void) SetImageMask(*image,(Image *) NULL,exception);
1909 break;
1910 }
1911 mask_image=GetImageCache(image_info,argv[1],exception);
1912 if (mask_image == (Image *) NULL)
1913 break;
1914 if (SetImageStorageClass(mask_image,DirectClass,exception) == MagickFalse)
1915 return(MagickFalse);
anthony74b1cfc2011-10-06 12:44:16 +00001916 /* create a write mask from clip-mask image */
1917 /* FUTURE: use Alpha operations instead */
anthony805a2d42011-09-25 08:25:12 +00001918 mask_view=AcquireCacheView(mask_image);
1919 for (y=0; y < (ssize_t) mask_image->rows; y++)
1920 {
1921 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1922 exception);
1923 if (q == (Quantum *) NULL)
1924 break;
1925 for (x=0; x < (ssize_t) mask_image->columns; x++)
1926 {
1927 if (mask_image->matte == MagickFalse)
1928 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1929 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1930 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1931 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1932 q+=GetPixelChannels(mask_image);
1933 }
1934 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1935 break;
1936 }
anthony74b1cfc2011-10-06 12:44:16 +00001937 /* set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001938 mask_view=DestroyCacheView(mask_view);
1939 mask_image->matte=MagickTrue;
anthonya89dd172011-10-04 13:29:35 +00001940 (void) SetImageClipMask(*image,mask_image,exception);
anthony805a2d42011-09-25 08:25:12 +00001941 mask_image=DestroyImage(mask_image);
1942 InheritException(exception,&(*image)->exception);
1943 break;
1944 }
1945 if (LocaleCompare("clip-path",argv[0]+1) == 0)
1946 {
1947 (void) SyncImageSettings(image_info,*image);
1948 (void) ClipImagePath(*image,argv[1],*argv[0] == '-' ? MagickTrue :
1949 MagickFalse,exception);
1950 break;
1951 }
1952 if (LocaleCompare("colorize",argv[0]+1) == 0)
1953 {
anthony805a2d42011-09-25 08:25:12 +00001954 (void) SyncImageSettings(image_info,*image);
1955 new_image=ColorizeImage(*image,argv[1],draw_info->fill,
1956 exception);
1957 break;
1958 }
1959 if (LocaleCompare("color-matrix",argv[0]+1) == 0)
1960 {
1961 KernelInfo
1962 *kernel;
1963
1964 (void) SyncImageSettings(image_info,*image);
1965 kernel=AcquireKernelInfo(argv[1]);
1966 if (kernel == (KernelInfo *) NULL)
1967 break;
1968 new_image=ColorMatrixImage(*image,kernel,exception);
1969 kernel=DestroyKernelInfo(kernel);
1970 break;
1971 }
1972 if (LocaleCompare("colors",argv[0]+1) == 0)
1973 {
anthony74b1cfc2011-10-06 12:44:16 +00001974 /* Reduce the number of colors in the image. */
anthony805a2d42011-09-25 08:25:12 +00001975 (void) SyncImageSettings(image_info,*image);
1976 quantize_info->number_colors=StringToUnsignedLong(argv[1]);
1977 if (quantize_info->number_colors == 0)
1978 break;
1979 if (((*image)->storage_class == DirectClass) ||
1980 (*image)->colors > quantize_info->number_colors)
1981 (void) QuantizeImage(quantize_info,*image,exception);
1982 else
1983 (void) CompressImageColormap(*image,exception);
1984 break;
1985 }
1986 if (LocaleCompare("colorspace",argv[0]+1) == 0)
1987 {
anthonyd2cdc862011-10-07 14:07:17 +00001988 /* This is a Image Setting, which should already been set */
1989 /* FUTURE: default colorspace should be sRGB!
1990 Unless some type of 'linear colorspace' mode is set.
1991 Note that +colorspace sets "undefined" or no effect on
1992 new images, but forces images already in memory back to RGB!
1993 */
anthony805a2d42011-09-25 08:25:12 +00001994 (void) SyncImageSettings(image_info,*image);
anthonyd2cdc862011-10-07 14:07:17 +00001995 (void) TransformImageColorspace(*image,
1996 IfSetOption ? image_info->colorspace : RGBColorspace);
anthony805a2d42011-09-25 08:25:12 +00001997 InheritException(exception,&(*image)->exception);
1998 break;
1999 }
2000 if (LocaleCompare("contrast",argv[0]+1) == 0)
2001 {
2002 (void) SyncImageSettings(image_info,*image);
2003 (void) ContrastImage(*image,(*argv[0] == '-') ? MagickTrue :
2004 MagickFalse,exception);
2005 break;
2006 }
2007 if (LocaleCompare("contrast-stretch",argv[0]+1) == 0)
2008 {
2009 double
2010 black_point,
2011 white_point;
2012
2013 MagickStatusType
2014 flags;
2015
2016 /*
2017 Contrast stretch image.
2018 */
2019 (void) SyncImageSettings(image_info,*image);
2020 flags=ParseGeometry(argv[1],&geometry_info);
2021 black_point=geometry_info.rho;
2022 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2023 black_point;
2024 if ((flags & PercentValue) != 0)
2025 {
2026 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2027 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2028 }
2029 white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2030 white_point;
2031 (void) ContrastStretchImage(*image,black_point,white_point,
2032 exception);
2033 InheritException(exception,&(*image)->exception);
2034 break;
2035 }
2036 if (LocaleCompare("convolve",argv[0]+1) == 0)
2037 {
2038 KernelInfo
2039 *kernel_info;
2040
2041 (void) SyncImageSettings(image_info,*image);
2042 kernel_info=AcquireKernelInfo(argv[1]);
2043 if (kernel_info == (KernelInfo *) NULL)
2044 break;
2045 kernel_info->bias=(*image)->bias;
2046 new_image=ConvolveImage(*image,kernel_info,exception);
2047 kernel_info=DestroyKernelInfo(kernel_info);
2048 break;
2049 }
2050 if (LocaleCompare("crop",argv[0]+1) == 0)
2051 {
2052 /*
2053 Crop a image to a smaller size
2054 */
2055 (void) SyncImageSettings(image_info,*image);
2056 new_image=CropImageToTiles(*image,argv[1],exception);
2057 break;
2058 }
2059 if (LocaleCompare("cycle",argv[0]+1) == 0)
2060 {
2061 /*
2062 Cycle an image colormap.
2063 */
2064 (void) SyncImageSettings(image_info,*image);
2065 (void) CycleColormapImage(*image,(ssize_t) StringToLong(argv[1]),
2066 exception);
2067 break;
2068 }
2069 break;
2070 }
2071 case 'd':
2072 {
2073 if (LocaleCompare("decipher",argv[0]+1) == 0)
2074 {
2075 StringInfo
2076 *passkey;
2077
2078 /*
2079 Decipher pixels.
2080 */
2081 (void) SyncImageSettings(image_info,*image);
2082 passkey=FileToStringInfo(argv[1],~0,exception);
2083 if (passkey != (StringInfo *) NULL)
2084 {
2085 (void) PasskeyDecipherImage(*image,passkey,exception);
2086 passkey=DestroyStringInfo(passkey);
2087 }
2088 break;
2089 }
anthony805a2d42011-09-25 08:25:12 +00002090 if (LocaleCompare("depth",argv[0]+1) == 0)
2091 {
anthony5f867ae2011-10-09 10:28:34 +00002092 /* the image_info->depth setting has already bee set
2093 * We just need to apply it to all images in current sequence */
anthony805a2d42011-09-25 08:25:12 +00002094 (void) SyncImageSettings(image_info,*image);
anthony5f867ae2011-10-09 10:28:34 +00002095 (void) SetImageDepth(*image,image_info->depth);
anthony805a2d42011-09-25 08:25:12 +00002096 break;
2097 }
2098 if (LocaleCompare("deskew",argv[0]+1) == 0)
2099 {
2100 double
2101 threshold;
2102
2103 /*
2104 Straighten the image.
2105 */
2106 (void) SyncImageSettings(image_info,*image);
2107 if (*argv[0] == '+')
2108 threshold=40.0*QuantumRange/100.0;
2109 else
2110 threshold=SiPrefixToDouble(argv[1],QuantumRange);
2111 new_image=DeskewImage(*image,threshold,exception);
2112 break;
2113 }
2114 if (LocaleCompare("despeckle",argv[0]+1) == 0)
2115 {
2116 /*
2117 Reduce the speckles within an image.
2118 */
2119 (void) SyncImageSettings(image_info,*image);
2120 new_image=DespeckleImage(*image,exception);
2121 break;
2122 }
2123 if (LocaleCompare("display",argv[0]+1) == 0)
2124 {
2125 (void) CloneString(&draw_info->server_name,argv[1]);
2126 break;
2127 }
2128 if (LocaleCompare("distort",argv[0]+1) == 0)
2129 {
2130 char
2131 *args,
2132 token[MaxTextExtent];
2133
2134 const char
2135 *p;
2136
2137 DistortImageMethod
2138 method;
2139
2140 double
2141 *arguments;
2142
2143 register ssize_t
2144 x;
2145
2146 size_t
2147 number_arguments;
2148
2149 /*
2150 Distort image.
2151 */
2152 (void) SyncImageSettings(image_info,*image);
2153 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
2154 MagickFalse,argv[1]);
2155 if ( method == ResizeDistortion )
2156 {
2157 /* Special Case - Argument is actually a resize geometry!
2158 ** Convert that to an appropriate distortion argument array.
2159 */
2160 double
2161 resize_args[2];
2162 (void) ParseRegionGeometry(*image,argv[2],&geometry,
2163 exception);
2164 resize_args[0]=(double)geometry.width;
2165 resize_args[1]=(double)geometry.height;
2166 new_image=DistortImage(*image,method,(size_t)2,
2167 resize_args,MagickTrue,exception);
2168 break;
2169 }
2170 args=InterpretImageProperties(image_info,*image,argv[2],
2171 exception);
2172 if (args == (char *) NULL)
2173 break;
2174 p=(char *) args;
2175 for (x=0; *p != '\0'; x++)
2176 {
2177 GetMagickToken(p,&p,token);
2178 if (*token == ',')
2179 GetMagickToken(p,&p,token);
2180 }
2181 number_arguments=(size_t) x;
2182 arguments=(double *) AcquireQuantumMemory(number_arguments,
2183 sizeof(*arguments));
2184 if (arguments == (double *) NULL)
2185 ThrowWandFatalException(ResourceLimitFatalError,
2186 "MemoryAllocationFailed",(*image)->filename);
2187 (void) ResetMagickMemory(arguments,0,number_arguments*
2188 sizeof(*arguments));
2189 p=(char *) args;
2190 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2191 {
2192 GetMagickToken(p,&p,token);
2193 if (*token == ',')
2194 GetMagickToken(p,&p,token);
2195 arguments[x]=InterpretLocaleValue(token,(char **) NULL);
2196 }
2197 args=DestroyString(args);
2198 new_image=DistortImage(*image,method,number_arguments,arguments,
2199 (*argv[0] == '+') ? MagickTrue : MagickFalse,exception);
2200 arguments=(double *) RelinquishMagickMemory(arguments);
2201 break;
2202 }
anthony805a2d42011-09-25 08:25:12 +00002203 if (LocaleCompare("draw",argv[0]+1) == 0)
2204 {
anthony805a2d42011-09-25 08:25:12 +00002205 (void) SyncImageSettings(image_info,*image);
2206 (void) CloneString(&draw_info->primitive,argv[1]);
2207 (void) DrawImage(*image,draw_info,exception);
2208 break;
2209 }
2210 break;
2211 }
2212 case 'e':
2213 {
2214 if (LocaleCompare("edge",argv[0]+1) == 0)
2215 {
anthony805a2d42011-09-25 08:25:12 +00002216 (void) SyncImageSettings(image_info,*image);
2217 flags=ParseGeometry(argv[1],&geometry_info);
2218 if ((flags & SigmaValue) == 0)
2219 geometry_info.sigma=1.0;
2220 new_image=EdgeImage(*image,geometry_info.rho,
2221 geometry_info.sigma,exception);
2222 break;
2223 }
2224 if (LocaleCompare("emboss",argv[0]+1) == 0)
2225 {
anthony805a2d42011-09-25 08:25:12 +00002226 (void) SyncImageSettings(image_info,*image);
2227 flags=ParseGeometry(argv[1],&geometry_info);
2228 if ((flags & SigmaValue) == 0)
2229 geometry_info.sigma=1.0;
2230 new_image=EmbossImage(*image,geometry_info.rho,
2231 geometry_info.sigma,exception);
2232 break;
2233 }
2234 if (LocaleCompare("encipher",argv[0]+1) == 0)
2235 {
2236 StringInfo
2237 *passkey;
2238
anthony805a2d42011-09-25 08:25:12 +00002239 (void) SyncImageSettings(image_info,*image);
2240 passkey=FileToStringInfo(argv[1],~0,exception);
2241 if (passkey != (StringInfo *) NULL)
2242 {
2243 (void) PasskeyEncipherImage(*image,passkey,exception);
2244 passkey=DestroyStringInfo(passkey);
2245 }
2246 break;
2247 }
anthony805a2d42011-09-25 08:25:12 +00002248 if (LocaleCompare("enhance",argv[0]+1) == 0)
2249 {
2250 /*
2251 Enhance image.
2252 */
2253 (void) SyncImageSettings(image_info,*image);
2254 new_image=EnhanceImage(*image,exception);
2255 break;
2256 }
2257 if (LocaleCompare("equalize",argv[0]+1) == 0)
2258 {
2259 /*
2260 Equalize image.
2261 */
2262 (void) SyncImageSettings(image_info,*image);
2263 (void) EqualizeImage(*image,exception);
2264 break;
2265 }
2266 if (LocaleCompare("evaluate",argv[0]+1) == 0)
2267 {
2268 double
2269 constant;
2270
2271 MagickEvaluateOperator
2272 op;
2273
2274 (void) SyncImageSettings(image_info,*image);
2275 op=(MagickEvaluateOperator) ParseCommandOption(
2276 MagickEvaluateOptions,MagickFalse,argv[1]);
2277 constant=SiPrefixToDouble(argv[2],QuantumRange);
2278 (void) EvaluateImage(*image,op,constant,exception);
2279 break;
2280 }
2281 if (LocaleCompare("extent",argv[0]+1) == 0)
2282 {
2283 /*
2284 Set the image extent.
2285 */
2286 (void) SyncImageSettings(image_info,*image);
2287 flags=ParseGravityGeometry(*image,argv[1],&geometry,exception);
2288 if (geometry.width == 0)
2289 geometry.width=(*image)->columns;
2290 if (geometry.height == 0)
2291 geometry.height=(*image)->rows;
2292 new_image=ExtentImage(*image,&geometry,exception);
2293 break;
2294 }
2295 break;
2296 }
2297 case 'f':
2298 {
2299 if (LocaleCompare("family",argv[0]+1) == 0)
2300 {
2301 if (*argv[0] == '+')
2302 {
2303 if (draw_info->family != (char *) NULL)
2304 draw_info->family=DestroyString(draw_info->family);
2305 break;
2306 }
2307 (void) CloneString(&draw_info->family,argv[1]);
2308 break;
2309 }
2310 if (LocaleCompare("features",argv[0]+1) == 0)
2311 {
2312 if (*argv[0] == '+')
2313 {
2314 (void) DeleteImageArtifact(*image,"identify:features");
2315 break;
2316 }
2317 (void) SetImageArtifact(*image,"identify:features",argv[1]);
2318 break;
2319 }
2320 if (LocaleCompare("fill",argv[0]+1) == 0)
2321 {
2322 ExceptionInfo
2323 *sans;
2324
2325 GetPixelInfo(*image,&fill);
2326 if (*argv[0] == '+')
2327 {
anthonya89dd172011-10-04 13:29:35 +00002328 (void) QueryMagickColorCompliance("none",AllCompliance,&fill,
anthony74b1cfc2011-10-06 12:44:16 +00002329 exception);
anthony1afdc7a2011-10-05 11:54:28 +00002330 (void) QueryColorCompliance("none",AllCompliance,&draw_info->fill,
anthonya89dd172011-10-04 13:29:35 +00002331 exception);
anthony805a2d42011-09-25 08:25:12 +00002332 if (draw_info->fill_pattern != (Image *) NULL)
2333 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
2334 break;
2335 }
2336 sans=AcquireExceptionInfo();
anthonya89dd172011-10-04 13:29:35 +00002337 (void) QueryMagickColorCompliance(argv[1],AllCompliance,&fill,sans);
anthony1afdc7a2011-10-05 11:54:28 +00002338 status=QueryColorCompliance(argv[1],AllCompliance,&draw_info->fill,sans);
anthony805a2d42011-09-25 08:25:12 +00002339 sans=DestroyExceptionInfo(sans);
2340 if (status == MagickFalse)
2341 draw_info->fill_pattern=GetImageCache(image_info,argv[1],
2342 exception);
2343 break;
2344 }
2345 if (LocaleCompare("flip",argv[0]+1) == 0)
2346 {
2347 /*
2348 Flip image scanlines.
2349 */
2350 (void) SyncImageSettings(image_info,*image);
2351 new_image=FlipImage(*image,exception);
2352 break;
2353 }
2354 if (LocaleCompare("flop",argv[0]+1) == 0)
2355 {
2356 /*
2357 Flop image scanlines.
2358 */
2359 (void) SyncImageSettings(image_info,*image);
2360 new_image=FlopImage(*image,exception);
2361 break;
2362 }
2363 if (LocaleCompare("floodfill",argv[0]+1) == 0)
2364 {
2365 PixelInfo
2366 target;
2367
2368 /*
2369 Floodfill image.
2370 */
2371 (void) SyncImageSettings(image_info,*image);
2372 (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
anthonya89dd172011-10-04 13:29:35 +00002373 (void) QueryMagickColorCompliance(argv[2],AllCompliance,&target,
2374 exception);
anthony805a2d42011-09-25 08:25:12 +00002375 (void) FloodfillPaintImage(*image,draw_info,&target,geometry.x,
2376 geometry.y,*argv[0] == '-' ? MagickFalse : MagickTrue,exception);
2377 break;
2378 }
2379 if (LocaleCompare("font",argv[0]+1) == 0)
2380 {
2381 if (*argv[0] == '+')
2382 {
2383 if (draw_info->font != (char *) NULL)
2384 draw_info->font=DestroyString(draw_info->font);
2385 break;
2386 }
2387 (void) CloneString(&draw_info->font,argv[1]);
2388 break;
2389 }
2390 if (LocaleCompare("format",argv[0]+1) == 0)
2391 {
2392 format=argv[1];
2393 break;
2394 }
2395 if (LocaleCompare("frame",argv[0]+1) == 0)
2396 {
2397 FrameInfo
2398 frame_info;
2399
2400 /*
2401 Surround image with an ornamental border.
2402 */
2403 (void) SyncImageSettings(image_info,*image);
2404 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
2405 frame_info.width=geometry.width;
2406 frame_info.height=geometry.height;
2407 if ((flags & HeightValue) == 0)
2408 frame_info.height=geometry.width;
2409 frame_info.outer_bevel=geometry.x;
2410 frame_info.inner_bevel=geometry.y;
2411 frame_info.x=(ssize_t) frame_info.width;
2412 frame_info.y=(ssize_t) frame_info.height;
2413 frame_info.width=(*image)->columns+2*frame_info.width;
2414 frame_info.height=(*image)->rows+2*frame_info.height;
anthony5f867ae2011-10-09 10:28:34 +00002415 new_image=FrameImage(*image,&frame_info,COMPOSE,exception);
anthony805a2d42011-09-25 08:25:12 +00002416 break;
2417 }
2418 if (LocaleCompare("function",argv[0]+1) == 0)
2419 {
2420 char
2421 *arguments,
2422 token[MaxTextExtent];
2423
2424 const char
2425 *p;
2426
2427 double
2428 *parameters;
2429
2430 MagickFunction
2431 function;
2432
2433 register ssize_t
2434 x;
2435
2436 size_t
2437 number_parameters;
2438
2439 /*
2440 Function Modify Image Values
2441 */
2442 (void) SyncImageSettings(image_info,*image);
2443 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
2444 MagickFalse,argv[1]);
2445 arguments=InterpretImageProperties(image_info,*image,argv[2],
2446 exception);
2447 if (arguments == (char *) NULL)
2448 break;
2449 p=(char *) arguments;
2450 for (x=0; *p != '\0'; x++)
2451 {
2452 GetMagickToken(p,&p,token);
2453 if (*token == ',')
2454 GetMagickToken(p,&p,token);
2455 }
2456 number_parameters=(size_t) x;
2457 parameters=(double *) AcquireQuantumMemory(number_parameters,
2458 sizeof(*parameters));
2459 if (parameters == (double *) NULL)
2460 ThrowWandFatalException(ResourceLimitFatalError,
2461 "MemoryAllocationFailed",(*image)->filename);
2462 (void) ResetMagickMemory(parameters,0,number_parameters*
2463 sizeof(*parameters));
2464 p=(char *) arguments;
2465 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2466 {
2467 GetMagickToken(p,&p,token);
2468 if (*token == ',')
2469 GetMagickToken(p,&p,token);
2470 parameters[x]=InterpretLocaleValue(token,(char **) NULL);
2471 }
2472 arguments=DestroyString(arguments);
2473 (void) FunctionImage(*image,function,number_parameters,parameters,
2474 exception);
2475 parameters=(double *) RelinquishMagickMemory(parameters);
2476 break;
2477 }
2478 break;
2479 }
2480 case 'g':
2481 {
2482 if (LocaleCompare("gamma",argv[0]+1) == 0)
2483 {
2484 /*
2485 Gamma image.
2486 */
2487 (void) SyncImageSettings(image_info,*image);
2488 if (*argv[0] == '+')
2489 (*image)->gamma=InterpretLocaleValue(argv[1],(char **) NULL);
2490 else
2491 (void) GammaImage(*image,InterpretLocaleValue(argv[1],
2492 (char **) NULL),exception);
2493 break;
2494 }
2495 if ((LocaleCompare("gaussian-blur",argv[0]+1) == 0) ||
2496 (LocaleCompare("gaussian",argv[0]+1) == 0))
2497 {
2498 /*
2499 Gaussian blur image.
2500 */
2501 (void) SyncImageSettings(image_info,*image);
2502 flags=ParseGeometry(argv[1],&geometry_info);
2503 if ((flags & SigmaValue) == 0)
2504 geometry_info.sigma=1.0;
2505 if ((flags & XiValue) == 0)
2506 geometry_info.xi=0.0;
2507 new_image=GaussianBlurImage(*image,geometry_info.rho,
2508 geometry_info.sigma,geometry_info.xi,exception);
2509 break;
2510 }
2511 if (LocaleCompare("geometry",argv[0]+1) == 0)
2512 {
2513 /*
2514 Record Image offset, Resize last image.
2515 */
2516 (void) SyncImageSettings(image_info,*image);
2517 if (*argv[0] == '+')
2518 {
2519 if ((*image)->geometry != (char *) NULL)
2520 (*image)->geometry=DestroyString((*image)->geometry);
2521 break;
2522 }
2523 flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2524 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2525 (void) CloneString(&(*image)->geometry,argv[1]);
2526 else
2527 new_image=ResizeImage(*image,geometry.width,geometry.height,
2528 (*image)->filter,(*image)->blur,exception);
2529 break;
2530 }
2531 if (LocaleCompare("gravity",argv[0]+1) == 0)
2532 {
2533 if (*argv[0] == '+')
2534 {
2535 draw_info->gravity=UndefinedGravity;
2536 break;
2537 }
2538 draw_info->gravity=(GravityType) ParseCommandOption(
2539 MagickGravityOptions,MagickFalse,argv[1]);
2540 break;
2541 }
2542 break;
2543 }
2544 case 'h':
2545 {
2546 if (LocaleCompare("highlight-color",argv[0]+1) == 0)
2547 {
2548 (void) SetImageArtifact(*image,argv[0]+1,argv[1]);
2549 break;
2550 }
2551 break;
2552 }
2553 case 'i':
2554 {
2555 if (LocaleCompare("identify",argv[0]+1) == 0)
2556 {
2557 char
2558 *text;
2559
2560 (void) SyncImageSettings(image_info,*image);
2561 if (format == (char *) NULL)
2562 {
2563 (void) IdentifyImage(*image,stdout,image_info->verbose,
2564 exception);
2565 break;
2566 }
2567 text=InterpretImageProperties(image_info,*image,format,
2568 exception);
2569 if (text == (char *) NULL)
2570 break;
2571 (void) fputs(text,stdout);
2572 (void) fputc('\n',stdout);
2573 text=DestroyString(text);
2574 break;
2575 }
2576 if (LocaleCompare("implode",argv[0]+1) == 0)
2577 {
2578 /*
2579 Implode image.
2580 */
2581 (void) SyncImageSettings(image_info,*image);
2582 (void) ParseGeometry(argv[1],&geometry_info);
anthonya89dd172011-10-04 13:29:35 +00002583 new_image=ImplodeImage(*image,geometry_info.rho,
2584 interpolate_method,exception);
anthony805a2d42011-09-25 08:25:12 +00002585 break;
2586 }
2587 if (LocaleCompare("interline-spacing",argv[0]+1) == 0)
2588 {
2589 if (*argv[0] == '+')
2590 (void) ParseGeometry("0",&geometry_info);
2591 else
2592 (void) ParseGeometry(argv[1],&geometry_info);
2593 draw_info->interline_spacing=geometry_info.rho;
2594 break;
2595 }
anthonya89dd172011-10-04 13:29:35 +00002596 if (LocaleCompare("interpolate",argv[0]+1) == 0)
2597 {
2598 interpolate_method=(PixelInterpolateMethod) ParseCommandOption(
2599 MagickInterpolateOptions,MagickFalse,argv[1]);
2600 break;
2601 }
anthony805a2d42011-09-25 08:25:12 +00002602 if (LocaleCompare("interword-spacing",argv[0]+1) == 0)
2603 {
2604 if (*argv[0] == '+')
2605 (void) ParseGeometry("0",&geometry_info);
2606 else
2607 (void) ParseGeometry(argv[1],&geometry_info);
2608 draw_info->interword_spacing=geometry_info.rho;
2609 break;
2610 }
2611 break;
2612 }
2613 case 'k':
2614 {
2615 if (LocaleCompare("kerning",argv[0]+1) == 0)
2616 {
2617 if (*argv[0] == '+')
2618 (void) ParseGeometry("0",&geometry_info);
2619 else
2620 (void) ParseGeometry(argv[1],&geometry_info);
2621 draw_info->kerning=geometry_info.rho;
2622 break;
2623 }
2624 break;
2625 }
2626 case 'l':
2627 {
2628 if (LocaleCompare("lat",argv[0]+1) == 0)
2629 {
2630 /*
2631 Local adaptive threshold image.
2632 */
2633 (void) SyncImageSettings(image_info,*image);
2634 flags=ParseGeometry(argv[1],&geometry_info);
2635 if ((flags & PercentValue) != 0)
2636 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2637 new_image=AdaptiveThresholdImage(*image,(size_t)
2638 geometry_info.rho,(size_t) geometry_info.sigma,(double)
2639 geometry_info.xi,exception);
2640 break;
2641 }
2642 if (LocaleCompare("level",argv[0]+1) == 0)
2643 {
2644 MagickRealType
2645 black_point,
2646 gamma,
2647 white_point;
2648
2649 MagickStatusType
2650 flags;
2651
2652 /*
2653 Parse levels.
2654 */
2655 (void) SyncImageSettings(image_info,*image);
2656 flags=ParseGeometry(argv[1],&geometry_info);
2657 black_point=geometry_info.rho;
2658 white_point=(MagickRealType) QuantumRange;
2659 if ((flags & SigmaValue) != 0)
2660 white_point=geometry_info.sigma;
2661 gamma=1.0;
2662 if ((flags & XiValue) != 0)
2663 gamma=geometry_info.xi;
2664 if ((flags & PercentValue) != 0)
2665 {
2666 black_point*=(MagickRealType) (QuantumRange/100.0);
2667 white_point*=(MagickRealType) (QuantumRange/100.0);
2668 }
2669 if ((flags & SigmaValue) == 0)
2670 white_point=(MagickRealType) QuantumRange-black_point;
2671 if ((*argv[0] == '+') || ((flags & AspectValue) != 0))
2672 (void) LevelizeImage(*image,black_point,white_point,gamma,
2673 exception);
2674 else
2675 (void) LevelImage(*image,black_point,white_point,gamma,
2676 exception);
2677 InheritException(exception,&(*image)->exception);
2678 break;
2679 }
2680 if (LocaleCompare("level-colors",argv[0]+1) == 0)
2681 {
2682 char
2683 token[MaxTextExtent];
2684
2685 const char
2686 *p;
2687
2688 PixelInfo
2689 black_point,
2690 white_point;
2691
2692 p=(const char *) argv[1];
2693 GetMagickToken(p,&p,token); /* get black point color */
2694 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
anthonya89dd172011-10-04 13:29:35 +00002695 (void) QueryMagickColorCompliance(token,AllCompliance,
2696 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002697 else
anthonya89dd172011-10-04 13:29:35 +00002698 (void) QueryMagickColorCompliance("#000000",AllCompliance,
2699 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002700 if (isalpha((int) token[0]) || (token[0] == '#'))
2701 GetMagickToken(p,&p,token);
2702 if (*token == '\0')
2703 white_point=black_point; /* set everything to that color */
2704 else
2705 {
2706 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2707 GetMagickToken(p,&p,token); /* Get white point color. */
2708 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
anthonya89dd172011-10-04 13:29:35 +00002709 (void) QueryMagickColorCompliance(token,AllCompliance,
2710 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002711 else
anthonya89dd172011-10-04 13:29:35 +00002712 (void) QueryMagickColorCompliance("#ffffff",AllCompliance,
2713 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002714 }
2715 (void) LevelImageColors(*image,&black_point,&white_point,
2716 *argv[0] == '+' ? MagickTrue : MagickFalse,exception);
2717 break;
2718 }
2719 if (LocaleCompare("linear-stretch",argv[0]+1) == 0)
2720 {
2721 double
2722 black_point,
2723 white_point;
2724
2725 MagickStatusType
2726 flags;
2727
2728 (void) SyncImageSettings(image_info,*image);
2729 flags=ParseGeometry(argv[1],&geometry_info);
2730 black_point=geometry_info.rho;
2731 white_point=(MagickRealType) (*image)->columns*(*image)->rows;
2732 if ((flags & SigmaValue) != 0)
2733 white_point=geometry_info.sigma;
2734 if ((flags & PercentValue) != 0)
2735 {
2736 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2737 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2738 }
2739 if ((flags & SigmaValue) == 0)
2740 white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2741 black_point;
2742 (void) LinearStretchImage(*image,black_point,white_point,exception);
2743 InheritException(exception,&(*image)->exception);
2744 break;
2745 }
2746 if (LocaleCompare("linewidth",argv[0]+1) == 0)
2747 {
2748 draw_info->stroke_width=InterpretLocaleValue(argv[1],
2749 (char **) NULL);
2750 break;
2751 }
2752 if (LocaleCompare("liquid-rescale",argv[0]+1) == 0)
2753 {
2754 /*
2755 Liquid rescale image.
2756 */
2757 (void) SyncImageSettings(image_info,*image);
2758 flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2759 if ((flags & XValue) == 0)
2760 geometry.x=1;
2761 if ((flags & YValue) == 0)
2762 geometry.y=0;
2763 new_image=LiquidRescaleImage(*image,geometry.width,
2764 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2765 break;
2766 }
2767 if (LocaleCompare("lowlight-color",argv[0]+1) == 0)
2768 {
2769 (void) SetImageArtifact(*image,argv[0]+1,argv[1]);
2770 break;
2771 }
2772 break;
2773 }
2774 case 'm':
2775 {
2776 if (LocaleCompare("map",argv[0]+1) == 0)
2777 {
2778 Image
2779 *remap_image;
2780
2781 /*
2782 Transform image colors to match this set of colors.
2783 */
2784 (void) SyncImageSettings(image_info,*image);
2785 if (*argv[0] == '+')
2786 break;
2787 remap_image=GetImageCache(image_info,argv[1],exception);
2788 if (remap_image == (Image *) NULL)
2789 break;
2790 (void) RemapImage(quantize_info,*image,remap_image,exception);
2791 remap_image=DestroyImage(remap_image);
2792 break;
2793 }
2794 if (LocaleCompare("mask",argv[0]+1) == 0)
2795 {
2796 Image
2797 *mask;
2798
2799 (void) SyncImageSettings(image_info,*image);
2800 if (*argv[0] == '+')
2801 {
2802 /*
2803 Remove a mask.
2804 */
2805 (void) SetImageMask(*image,(Image *) NULL,exception);
2806 break;
2807 }
2808 /*
2809 Set the image mask.
2810 */
2811 mask=GetImageCache(image_info,argv[1],exception);
2812 if (mask == (Image *) NULL)
2813 break;
2814 (void) SetImageMask(*image,mask,exception);
2815 mask=DestroyImage(mask);
2816 break;
2817 }
2818 if (LocaleCompare("matte",argv[0]+1) == 0)
2819 {
2820 (void) SetImageAlphaChannel(*image,(*argv[0] == '-') ?
2821 SetAlphaChannel : DeactivateAlphaChannel,exception);
2822 break;
2823 }
2824 if (LocaleCompare("median",argv[0]+1) == 0)
2825 {
2826 /*
2827 Median filter image.
2828 */
2829 (void) SyncImageSettings(image_info,*image);
2830 flags=ParseGeometry(argv[1],&geometry_info);
2831 if ((flags & SigmaValue) == 0)
2832 geometry_info.sigma=geometry_info.rho;
2833 new_image=StatisticImage(*image,MedianStatistic,(size_t)
2834 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2835 break;
2836 }
2837 if (LocaleCompare("mode",argv[0]+1) == 0)
2838 {
2839 /*
2840 Mode image.
2841 */
2842 (void) SyncImageSettings(image_info,*image);
2843 flags=ParseGeometry(argv[1],&geometry_info);
2844 if ((flags & SigmaValue) == 0)
2845 geometry_info.sigma=geometry_info.rho;
2846 new_image=StatisticImage(*image,ModeStatistic,(size_t)
2847 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2848 break;
2849 }
2850 if (LocaleCompare("modulate",argv[0]+1) == 0)
2851 {
2852 (void) SyncImageSettings(image_info,*image);
2853 (void) ModulateImage(*image,argv[1],exception);
2854 break;
2855 }
2856 if (LocaleCompare("monitor",argv[0]+1) == 0)
2857 {
2858 if (*argv[0] == '+')
2859 {
2860 (void) SetImageProgressMonitor(*image,
2861 (MagickProgressMonitor) NULL,(void *) NULL);
2862 break;
2863 }
2864 (void) SetImageProgressMonitor(*image,MonitorProgress,
2865 (void *) NULL);
2866 break;
2867 }
2868 if (LocaleCompare("monochrome",argv[0]+1) == 0)
2869 {
2870 (void) SyncImageSettings(image_info,*image);
2871 (void) SetImageType(*image,BilevelType,exception);
2872 break;
2873 }
2874 if (LocaleCompare("morphology",argv[0]+1) == 0)
2875 {
2876 char
2877 token[MaxTextExtent];
2878
2879 const char
2880 *p;
2881
2882 KernelInfo
2883 *kernel;
2884
2885 MorphologyMethod
2886 method;
2887
2888 ssize_t
2889 iterations;
2890
2891 /*
2892 Morphological Image Operation
2893 */
2894 (void) SyncImageSettings(image_info,*image);
2895 p=argv[1];
2896 GetMagickToken(p,&p,token);
2897 method=(MorphologyMethod) ParseCommandOption(
2898 MagickMorphologyOptions,MagickFalse,token);
2899 iterations=1L;
2900 GetMagickToken(p,&p,token);
2901 if ((*p == ':') || (*p == ','))
2902 GetMagickToken(p,&p,token);
2903 if ((*p != '\0'))
2904 iterations=(ssize_t) StringToLong(p);
2905 kernel=AcquireKernelInfo(argv[2]);
2906 if (kernel == (KernelInfo *) NULL)
2907 {
2908 (void) ThrowMagickException(exception,GetMagickModule(),
2909 OptionError,"UnabletoParseKernel","morphology");
2910 status=MagickFalse;
2911 break;
2912 }
2913 new_image=MorphologyImage(*image,method,iterations,kernel,
2914 exception);
2915 kernel=DestroyKernelInfo(kernel);
2916 break;
2917 }
2918 if (LocaleCompare("motion-blur",argv[0]+1) == 0)
2919 {
2920 /*
2921 Motion blur image.
2922 */
2923 (void) SyncImageSettings(image_info,*image);
2924 flags=ParseGeometry(argv[1],&geometry_info);
2925 if ((flags & SigmaValue) == 0)
2926 geometry_info.sigma=1.0;
2927 new_image=MotionBlurImage(*image,geometry_info.rho,
2928 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2929 exception);
2930 break;
2931 }
2932 break;
2933 }
2934 case 'n':
2935 {
2936 if (LocaleCompare("negate",argv[0]+1) == 0)
2937 {
2938 (void) SyncImageSettings(image_info,*image);
2939 (void) NegateImage(*image,*argv[0] == '+' ? MagickTrue :
2940 MagickFalse,exception);
2941 break;
2942 }
2943 if (LocaleCompare("noise",argv[0]+1) == 0)
2944 {
2945 (void) SyncImageSettings(image_info,*image);
2946 if (*argv[0] == '-')
2947 {
2948 flags=ParseGeometry(argv[1],&geometry_info);
2949 if ((flags & SigmaValue) == 0)
2950 geometry_info.sigma=geometry_info.rho;
2951 new_image=StatisticImage(*image,NonpeakStatistic,(size_t)
2952 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2953 }
2954 else
2955 {
2956 NoiseType
2957 noise;
2958
2959 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
2960 MagickFalse,argv[1]);
anthony5f867ae2011-10-09 10:28:34 +00002961 new_image=AddNoiseImage(*image,noise,exception);
anthony805a2d42011-09-25 08:25:12 +00002962 }
2963 break;
2964 }
2965 if (LocaleCompare("normalize",argv[0]+1) == 0)
2966 {
2967 (void) SyncImageSettings(image_info,*image);
2968 (void) NormalizeImage(*image,exception);
2969 break;
2970 }
2971 break;
2972 }
2973 case 'o':
2974 {
2975 if (LocaleCompare("opaque",argv[0]+1) == 0)
2976 {
2977 PixelInfo
2978 target;
2979
2980 (void) SyncImageSettings(image_info,*image);
anthonya89dd172011-10-04 13:29:35 +00002981 (void) QueryMagickColorCompliance(argv[1],AllCompliance,&target,
2982 exception);
anthony805a2d42011-09-25 08:25:12 +00002983 (void) OpaquePaintImage(*image,&target,&fill,*argv[0] == '-' ?
2984 MagickFalse : MagickTrue,exception);
2985 break;
2986 }
2987 if (LocaleCompare("ordered-dither",argv[0]+1) == 0)
2988 {
2989 (void) SyncImageSettings(image_info,*image);
2990 (void) OrderedPosterizeImage(*image,argv[1],exception);
2991 break;
2992 }
2993 break;
2994 }
2995 case 'p':
2996 {
2997 if (LocaleCompare("paint",argv[0]+1) == 0)
2998 {
2999 (void) SyncImageSettings(image_info,*image);
3000 (void) ParseGeometry(argv[1],&geometry_info);
3001 new_image=OilPaintImage(*image,geometry_info.rho,
3002 geometry_info.sigma,exception);
3003 break;
3004 }
3005 if (LocaleCompare("pen",argv[0]+1) == 0)
3006 {
3007 if (*argv[0] == '+')
3008 {
anthony1afdc7a2011-10-05 11:54:28 +00003009 (void) QueryColorCompliance("none",AllCompliance,&draw_info->fill,
anthonya89dd172011-10-04 13:29:35 +00003010 exception);
anthony805a2d42011-09-25 08:25:12 +00003011 break;
3012 }
anthony1afdc7a2011-10-05 11:54:28 +00003013 (void) QueryColorCompliance(argv[1],AllCompliance,&draw_info->fill,
anthonya89dd172011-10-04 13:29:35 +00003014 exception);
anthony805a2d42011-09-25 08:25:12 +00003015 break;
3016 }
3017 if (LocaleCompare("pointsize",argv[0]+1) == 0)
3018 {
3019 if (*argv[0] == '+')
3020 (void) ParseGeometry("12",&geometry_info);
3021 else
3022 (void) ParseGeometry(argv[1],&geometry_info);
3023 draw_info->pointsize=geometry_info.rho;
3024 break;
3025 }
3026 if (LocaleCompare("polaroid",argv[0]+1) == 0)
3027 {
3028 double
3029 angle;
3030
3031 RandomInfo
3032 *random_info;
3033
3034 /*
3035 Simulate a Polaroid picture.
3036 */
3037 (void) SyncImageSettings(image_info,*image);
3038 random_info=AcquireRandomInfo();
3039 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3040 random_info=DestroyRandomInfo(random_info);
3041 if (*argv[0] == '-')
3042 {
3043 SetGeometryInfo(&geometry_info);
3044 flags=ParseGeometry(argv[1],&geometry_info);
3045 angle=geometry_info.rho;
3046 }
3047 new_image=PolaroidImage(*image,draw_info,angle,
3048 interpolate_method,exception);
3049 break;
3050 }
3051 if (LocaleCompare("posterize",argv[0]+1) == 0)
3052 {
3053 /*
3054 Posterize image.
3055 */
3056 (void) SyncImageSettings(image_info,*image);
3057 (void) PosterizeImage(*image,StringToUnsignedLong(argv[1]),
3058 quantize_info->dither,exception);
3059 break;
3060 }
3061 if (LocaleCompare("preview",argv[0]+1) == 0)
3062 {
3063 PreviewType
3064 preview_type;
3065
3066 /*
3067 Preview image.
3068 */
3069 (void) SyncImageSettings(image_info,*image);
3070 if (*argv[0] == '+')
3071 preview_type=UndefinedPreview;
3072 else
3073 preview_type=(PreviewType) ParseCommandOption(
3074 MagickPreviewOptions,MagickFalse,argv[1]);
3075 new_image=PreviewImage(*image,preview_type,exception);
3076 break;
3077 }
3078 if (LocaleCompare("profile",argv[0]+1) == 0)
3079 {
3080 const char
3081 *name;
3082
3083 const StringInfo
3084 *profile;
3085
3086 Image
3087 *profile_image;
3088
3089 ImageInfo
3090 *profile_info;
3091
3092 (void) SyncImageSettings(image_info,*image);
3093 if (*argv[0] == '+')
3094 {
3095 /*
3096 Remove a profile from the image.
3097 */
3098 (void) ProfileImage(*image,argv[1],(const unsigned char *)
3099 NULL,0,MagickTrue);
3100 InheritException(exception,&(*image)->exception);
3101 break;
3102 }
3103 /*
3104 Associate a profile with the image.
3105 */
3106 profile_info=CloneImageInfo(image_info);
3107 profile=GetImageProfile(*image,"iptc");
3108 if (profile != (StringInfo *) NULL)
3109 profile_info->profile=(void *) CloneStringInfo(profile);
3110 profile_image=GetImageCache(profile_info,argv[1],exception);
3111 profile_info=DestroyImageInfo(profile_info);
3112 if (profile_image == (Image *) NULL)
3113 {
3114 StringInfo
3115 *profile;
3116
3117 profile_info=CloneImageInfo(image_info);
3118 (void) CopyMagickString(profile_info->filename,argv[1],
3119 MaxTextExtent);
3120 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
3121 if (profile != (StringInfo *) NULL)
3122 {
3123 (void) ProfileImage(*image,profile_info->magick,
3124 GetStringInfoDatum(profile),(size_t)
3125 GetStringInfoLength(profile),MagickFalse);
3126 profile=DestroyStringInfo(profile);
3127 }
3128 profile_info=DestroyImageInfo(profile_info);
3129 break;
3130 }
3131 ResetImageProfileIterator(profile_image);
3132 name=GetNextImageProfile(profile_image);
3133 while (name != (const char *) NULL)
3134 {
3135 profile=GetImageProfile(profile_image,name);
3136 if (profile != (StringInfo *) NULL)
3137 (void) ProfileImage(*image,name,GetStringInfoDatum(profile),
3138 (size_t) GetStringInfoLength(profile),MagickFalse);
3139 name=GetNextImageProfile(profile_image);
3140 }
3141 profile_image=DestroyImage(profile_image);
3142 break;
3143 }
3144 break;
3145 }
3146 case 'q':
3147 {
3148 if (LocaleCompare("quantize",argv[0]+1) == 0)
3149 {
3150 if (*argv[0] == '+')
3151 {
3152 quantize_info->colorspace=UndefinedColorspace;
3153 break;
3154 }
3155 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
3156 MagickColorspaceOptions,MagickFalse,argv[1]);
3157 break;
3158 }
3159 break;
3160 }
3161 case 'r':
3162 {
3163 if (LocaleCompare("radial-blur",argv[0]+1) == 0)
3164 {
3165 /*
3166 Radial blur image.
3167 */
3168 (void) SyncImageSettings(image_info,*image);
3169 flags=ParseGeometry(argv[1],&geometry_info);
3170 new_image=RadialBlurImage(*image,geometry_info.rho,
3171 geometry_info.sigma,exception);
3172 break;
3173 }
3174 if (LocaleCompare("raise",argv[0]+1) == 0)
3175 {
3176 /*
3177 Surround image with a raise of solid color.
3178 */
3179 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3180 if ((flags & SigmaValue) == 0)
3181 geometry.height=geometry.width;
3182 (void) RaiseImage(*image,&geometry,*argv[0] == '-' ? MagickTrue :
3183 MagickFalse,exception);
3184 break;
3185 }
3186 if (LocaleCompare("random-threshold",argv[0]+1) == 0)
3187 {
3188 /*
3189 Threshold image.
3190 */
3191 (void) SyncImageSettings(image_info,*image);
3192 (void) RandomThresholdImage(*image,argv[1],exception);
3193 break;
3194 }
3195 if (LocaleCompare("recolor",argv[0]+1) == 0)
3196 {
3197 KernelInfo
3198 *kernel;
3199
3200 (void) SyncImageSettings(image_info,*image);
3201 kernel=AcquireKernelInfo(argv[1]);
3202 if (kernel == (KernelInfo *) NULL)
3203 break;
3204 new_image=ColorMatrixImage(*image,kernel,exception);
3205 kernel=DestroyKernelInfo(kernel);
3206 break;
3207 }
3208 if (LocaleCompare("render",argv[0]+1) == 0)
3209 {
3210 (void) SyncImageSettings(image_info,*image);
3211 draw_info->render=(*argv[0] == '+') ? MagickTrue : MagickFalse;
3212 break;
3213 }
3214 if (LocaleCompare("remap",argv[0]+1) == 0)
3215 {
3216 Image
3217 *remap_image;
3218
3219 /*
3220 Transform image colors to match this set of colors.
3221 */
3222 (void) SyncImageSettings(image_info,*image);
3223 if (*argv[0] == '+')
3224 break;
3225 remap_image=GetImageCache(image_info,argv[1],exception);
3226 if (remap_image == (Image *) NULL)
3227 break;
3228 (void) RemapImage(quantize_info,*image,remap_image,exception);
3229 remap_image=DestroyImage(remap_image);
3230 break;
3231 }
3232 if (LocaleCompare("repage",argv[0]+1) == 0)
3233 {
3234 if (*argv[0] == '+')
3235 {
3236 (void) ParseAbsoluteGeometry("0x0+0+0",&(*image)->page);
3237 break;
3238 }
3239 (void) ResetImagePage(*image,argv[1]);
3240 InheritException(exception,&(*image)->exception);
3241 break;
3242 }
3243 if (LocaleCompare("resample",argv[0]+1) == 0)
3244 {
3245 /*
3246 Resample image.
3247 */
3248 (void) SyncImageSettings(image_info,*image);
3249 flags=ParseGeometry(argv[1],&geometry_info);
3250 if ((flags & SigmaValue) == 0)
3251 geometry_info.sigma=geometry_info.rho;
3252 new_image=ResampleImage(*image,geometry_info.rho,
3253 geometry_info.sigma,(*image)->filter,(*image)->blur,exception);
3254 break;
3255 }
3256 if (LocaleCompare("resize",argv[0]+1) == 0)
3257 {
3258 /*
3259 Resize image.
3260 */
3261 (void) SyncImageSettings(image_info,*image);
3262 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3263 new_image=ResizeImage(*image,geometry.width,geometry.height,
3264 (*image)->filter,(*image)->blur,exception);
3265 break;
3266 }
3267 if (LocaleCompare("roll",argv[0]+1) == 0)
3268 {
3269 /*
3270 Roll image.
3271 */
3272 (void) SyncImageSettings(image_info,*image);
3273 (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
3274 new_image=RollImage(*image,geometry.x,geometry.y,exception);
3275 break;
3276 }
3277 if (LocaleCompare("rotate",argv[0]+1) == 0)
3278 {
3279 char
3280 *geometry;
3281
3282 /*
3283 Check for conditional image rotation.
3284 */
3285 (void) SyncImageSettings(image_info,*image);
3286 if (strchr(argv[1],'>') != (char *) NULL)
3287 if ((*image)->columns <= (*image)->rows)
3288 break;
3289 if (strchr(argv[1],'<') != (char *) NULL)
3290 if ((*image)->columns >= (*image)->rows)
3291 break;
3292 /*
3293 Rotate image.
3294 */
3295 geometry=ConstantString(argv[1]);
3296 (void) SubstituteString(&geometry,">","");
3297 (void) SubstituteString(&geometry,"<","");
3298 (void) ParseGeometry(geometry,&geometry_info);
3299 geometry=DestroyString(geometry);
3300 new_image=RotateImage(*image,geometry_info.rho,exception);
3301 break;
3302 }
3303 break;
3304 }
3305 case 's':
3306 {
3307 if (LocaleCompare("sample",argv[0]+1) == 0)
3308 {
3309 /*
3310 Sample image with pixel replication.
3311 */
3312 (void) SyncImageSettings(image_info,*image);
3313 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3314 new_image=SampleImage(*image,geometry.width,geometry.height,
3315 exception);
3316 break;
3317 }
3318 if (LocaleCompare("scale",argv[0]+1) == 0)
3319 {
3320 /*
3321 Resize image.
3322 */
3323 (void) SyncImageSettings(image_info,*image);
3324 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3325 new_image=ScaleImage(*image,geometry.width,geometry.height,
3326 exception);
3327 break;
3328 }
3329 if (LocaleCompare("selective-blur",argv[0]+1) == 0)
3330 {
3331 /*
3332 Selectively blur pixels within a contrast threshold.
3333 */
3334 (void) SyncImageSettings(image_info,*image);
3335 flags=ParseGeometry(argv[1],&geometry_info);
3336 if ((flags & PercentValue) != 0)
3337 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3338 new_image=SelectiveBlurImage(*image,geometry_info.rho,
3339 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3340 break;
3341 }
3342 if (LocaleCompare("separate",argv[0]+1) == 0)
3343 {
3344 /*
3345 Break channels into separate images.
3346 WARNING: This can generate multiple images!
3347 */
3348 (void) SyncImageSettings(image_info,*image);
3349 new_image=SeparateImages(*image,exception);
3350 break;
3351 }
3352 if (LocaleCompare("sepia-tone",argv[0]+1) == 0)
3353 {
3354 double
3355 threshold;
3356
3357 /*
3358 Sepia-tone image.
3359 */
3360 (void) SyncImageSettings(image_info,*image);
3361 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3362 new_image=SepiaToneImage(*image,threshold,exception);
3363 break;
3364 }
3365 if (LocaleCompare("segment",argv[0]+1) == 0)
3366 {
3367 /*
3368 Segment image.
3369 */
3370 (void) SyncImageSettings(image_info,*image);
3371 flags=ParseGeometry(argv[1],&geometry_info);
3372 if ((flags & SigmaValue) == 0)
3373 geometry_info.sigma=1.0;
3374 (void) SegmentImage(*image,(*image)->colorspace,
3375 image_info->verbose,geometry_info.rho,geometry_info.sigma,
3376 exception);
3377 break;
3378 }
3379 if (LocaleCompare("set",argv[0]+1) == 0)
3380 {
3381 char
3382 *value;
3383
anthony805a2d42011-09-25 08:25:12 +00003384 if (*argv[0] == '+')
3385 {
3386 if (LocaleNCompare(argv[1],"registry:",9) == 0)
3387 (void) DeleteImageRegistry(argv[1]+9);
3388 else
3389 if (LocaleNCompare(argv[1],"argv[0]:",7) == 0)
3390 {
3391 (void) DeleteImageOption(image_info,argv[1]+7);
3392 (void) DeleteImageArtifact(*image,argv[1]+7);
3393 }
3394 else
3395 (void) DeleteImageProperty(*image,argv[1]);
3396 break;
3397 }
3398 value=InterpretImageProperties(image_info,*image,argv[2],
3399 exception);
3400 if (value == (char *) NULL)
3401 break;
3402 if (LocaleNCompare(argv[1],"registry:",9) == 0)
3403 (void) SetImageRegistry(StringRegistryType,argv[1]+9,value,
3404 exception);
3405 else
anthonya89dd172011-10-04 13:29:35 +00003406 if (LocaleNCompare(argv[1],"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003407 {
3408 (void) SetImageOption(image_info,argv[1]+7,value);
anthony805a2d42011-09-25 08:25:12 +00003409 (void) SetImageArtifact(*image,argv[1]+7,value);
3410 }
3411 else
3412 (void) SetImageProperty(*image,argv[1],value);
3413 value=DestroyString(value);
3414 break;
3415 }
3416 if (LocaleCompare("shade",argv[0]+1) == 0)
3417 {
3418 /*
3419 Shade image.
3420 */
3421 (void) SyncImageSettings(image_info,*image);
3422 flags=ParseGeometry(argv[1],&geometry_info);
3423 if ((flags & SigmaValue) == 0)
3424 geometry_info.sigma=1.0;
3425 new_image=ShadeImage(*image,(*argv[0] == '-') ? MagickTrue :
3426 MagickFalse,geometry_info.rho,geometry_info.sigma,exception);
3427 break;
3428 }
3429 if (LocaleCompare("shadow",argv[0]+1) == 0)
3430 {
3431 /*
3432 Shadow image.
3433 */
3434 (void) SyncImageSettings(image_info,*image);
3435 flags=ParseGeometry(argv[1],&geometry_info);
3436 if ((flags & SigmaValue) == 0)
3437 geometry_info.sigma=1.0;
3438 if ((flags & XiValue) == 0)
3439 geometry_info.xi=4.0;
3440 if ((flags & PsiValue) == 0)
3441 geometry_info.psi=4.0;
3442 new_image=ShadowImage(*image,geometry_info.rho,
3443 geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3444 ceil(geometry_info.psi-0.5),exception);
3445 break;
3446 }
3447 if (LocaleCompare("sharpen",argv[0]+1) == 0)
3448 {
3449 /*
3450 Sharpen image.
3451 */
3452 (void) SyncImageSettings(image_info,*image);
3453 flags=ParseGeometry(argv[1],&geometry_info);
3454 if ((flags & SigmaValue) == 0)
3455 geometry_info.sigma=1.0;
3456 if ((flags & XiValue) == 0)
3457 geometry_info.xi=0.0;
3458 new_image=SharpenImage(*image,geometry_info.rho,
3459 geometry_info.sigma,geometry_info.xi,exception);
3460 break;
3461 }
3462 if (LocaleCompare("shave",argv[0]+1) == 0)
3463 {
3464 /*
3465 Shave the image edges.
3466 */
3467 (void) SyncImageSettings(image_info,*image);
3468 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3469 new_image=ShaveImage(*image,&geometry,exception);
3470 break;
3471 }
3472 if (LocaleCompare("shear",argv[0]+1) == 0)
3473 {
3474 /*
3475 Shear image.
3476 */
3477 (void) SyncImageSettings(image_info,*image);
3478 flags=ParseGeometry(argv[1],&geometry_info);
3479 if ((flags & SigmaValue) == 0)
3480 geometry_info.sigma=geometry_info.rho;
3481 new_image=ShearImage(*image,geometry_info.rho,
3482 geometry_info.sigma,exception);
3483 break;
3484 }
3485 if (LocaleCompare("sigmoidal-contrast",argv[0]+1) == 0)
3486 {
3487 /*
3488 Sigmoidal non-linearity contrast control.
3489 */
3490 (void) SyncImageSettings(image_info,*image);
3491 flags=ParseGeometry(argv[1],&geometry_info);
3492 if ((flags & SigmaValue) == 0)
3493 geometry_info.sigma=(double) QuantumRange/2.0;
3494 if ((flags & PercentValue) != 0)
3495 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3496 100.0;
3497 (void) SigmoidalContrastImage(*image,(*argv[0] == '-') ?
3498 MagickTrue : MagickFalse,geometry_info.rho,geometry_info.sigma,
3499 exception);
3500 break;
3501 }
3502 if (LocaleCompare("sketch",argv[0]+1) == 0)
3503 {
3504 /*
3505 Sketch image.
3506 */
3507 (void) SyncImageSettings(image_info,*image);
3508 flags=ParseGeometry(argv[1],&geometry_info);
3509 if ((flags & SigmaValue) == 0)
3510 geometry_info.sigma=1.0;
3511 new_image=SketchImage(*image,geometry_info.rho,
3512 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3513 break;
3514 }
3515 if (LocaleCompare("solarize",argv[0]+1) == 0)
3516 {
3517 double
3518 threshold;
3519
3520 (void) SyncImageSettings(image_info,*image);
3521 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3522 (void) SolarizeImage(*image,threshold,exception);
3523 break;
3524 }
3525 if (LocaleCompare("sparse-color",argv[0]+1) == 0)
3526 {
3527 SparseColorMethod
3528 method;
3529
3530 char
3531 *arguments;
3532
3533 /*
3534 Sparse Color Interpolated Gradient
3535 */
3536 (void) SyncImageSettings(image_info,*image);
3537 method=(SparseColorMethod) ParseCommandOption(
3538 MagickSparseColorOptions,MagickFalse,argv[1]);
3539 arguments=InterpretImageProperties(image_info,*image,argv[2],
3540 exception);
3541 if (arguments == (char *) NULL)
3542 break;
3543 new_image=SparseColorOption(*image,method,arguments,
3544 argv[0][0] == '+' ? MagickTrue : MagickFalse,exception);
3545 arguments=DestroyString(arguments);
3546 break;
3547 }
3548 if (LocaleCompare("splice",argv[0]+1) == 0)
3549 {
3550 /*
3551 Splice a solid color into the image.
3552 */
3553 (void) SyncImageSettings(image_info,*image);
3554 (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
3555 new_image=SpliceImage(*image,&geometry,exception);
3556 break;
3557 }
3558 if (LocaleCompare("spread",argv[0]+1) == 0)
3559 {
3560 /*
3561 Spread an image.
3562 */
3563 (void) SyncImageSettings(image_info,*image);
3564 (void) ParseGeometry(argv[1],&geometry_info);
3565 new_image=SpreadImage(*image,geometry_info.rho,
3566 interpolate_method,exception);
3567 break;
3568 }
3569 if (LocaleCompare("statistic",argv[0]+1) == 0)
3570 {
3571 StatisticType
3572 type;
3573
3574 (void) SyncImageSettings(image_info,*image);
3575 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
3576 MagickFalse,argv[1]);
3577 (void) ParseGeometry(argv[2],&geometry_info);
3578 new_image=StatisticImage(*image,type,(size_t) geometry_info.rho,
3579 (size_t) geometry_info.sigma,exception);
3580 break;
3581 }
3582 if (LocaleCompare("stretch",argv[0]+1) == 0)
3583 {
3584 if (*argv[0] == '+')
3585 {
3586 draw_info->stretch=UndefinedStretch;
3587 break;
3588 }
3589 draw_info->stretch=(StretchType) ParseCommandOption(
3590 MagickStretchOptions,MagickFalse,argv[1]);
3591 break;
3592 }
3593 if (LocaleCompare("strip",argv[0]+1) == 0)
3594 {
3595 /*
3596 Strip image of profiles and comments.
3597 */
3598 (void) SyncImageSettings(image_info,*image);
3599 (void) StripImage(*image);
3600 InheritException(exception,&(*image)->exception);
3601 break;
3602 }
3603 if (LocaleCompare("stroke",argv[0]+1) == 0)
3604 {
3605 ExceptionInfo
3606 *sans;
3607
3608 if (*argv[0] == '+')
3609 {
anthony1afdc7a2011-10-05 11:54:28 +00003610 (void) QueryColorCompliance("none",AllCompliance,&draw_info->stroke,
anthonya89dd172011-10-04 13:29:35 +00003611 exception);
anthony805a2d42011-09-25 08:25:12 +00003612 if (draw_info->stroke_pattern != (Image *) NULL)
3613 draw_info->stroke_pattern=DestroyImage(
3614 draw_info->stroke_pattern);
3615 break;
3616 }
3617 sans=AcquireExceptionInfo();
anthony1afdc7a2011-10-05 11:54:28 +00003618 status=QueryColorCompliance(argv[1],AllCompliance,&draw_info->stroke,sans);
anthony805a2d42011-09-25 08:25:12 +00003619 sans=DestroyExceptionInfo(sans);
3620 if (status == MagickFalse)
3621 draw_info->stroke_pattern=GetImageCache(image_info,argv[1],
3622 exception);
3623 break;
3624 }
3625 if (LocaleCompare("strokewidth",argv[0]+1) == 0)
3626 {
3627 draw_info->stroke_width=InterpretLocaleValue(argv[1],
3628 (char **) NULL);
3629 break;
3630 }
3631 if (LocaleCompare("style",argv[0]+1) == 0)
3632 {
3633 if (*argv[0] == '+')
3634 {
3635 draw_info->style=UndefinedStyle;
3636 break;
3637 }
3638 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
3639 MagickFalse,argv[1]);
3640 break;
3641 }
3642 if (LocaleCompare("swirl",argv[0]+1) == 0)
3643 {
3644 /*
3645 Swirl image.
3646 */
3647 (void) SyncImageSettings(image_info,*image);
3648 (void) ParseGeometry(argv[1],&geometry_info);
3649 new_image=SwirlImage(*image,geometry_info.rho,
3650 interpolate_method,exception);
3651 break;
3652 }
3653 break;
3654 }
3655 case 't':
3656 {
3657 if (LocaleCompare("threshold",argv[0]+1) == 0)
3658 {
3659 double
3660 threshold;
3661
3662 /*
3663 Threshold image.
3664 */
3665 (void) SyncImageSettings(image_info,*image);
3666 if (*argv[0] == '+')
3667 threshold=(double) QuantumRange/2;
3668 else
3669 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3670 (void) BilevelImage(*image,threshold);
3671 InheritException(exception,&(*image)->exception);
3672 break;
3673 }
3674 if (LocaleCompare("thumbnail",argv[0]+1) == 0)
3675 {
3676 /*
3677 Thumbnail image.
3678 */
3679 (void) SyncImageSettings(image_info,*image);
3680 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3681 new_image=ThumbnailImage(*image,geometry.width,geometry.height,
3682 exception);
3683 break;
3684 }
3685 if (LocaleCompare("tile",argv[0]+1) == 0)
3686 {
3687 if (*argv[0] == '+')
3688 {
3689 if (draw_info->fill_pattern != (Image *) NULL)
3690 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
3691 break;
3692 }
3693 draw_info->fill_pattern=GetImageCache(image_info,argv[1],
3694 exception);
3695 break;
3696 }
3697 if (LocaleCompare("tint",argv[0]+1) == 0)
3698 {
3699 /*
3700 Tint the image.
3701 */
3702 (void) SyncImageSettings(image_info,*image);
3703 new_image=TintImage(*image,argv[1],&fill,exception);
3704 break;
3705 }
3706 if (LocaleCompare("transform",argv[0]+1) == 0)
3707 {
3708 /*
3709 Affine transform image.
3710 */
3711 (void) SyncImageSettings(image_info,*image);
3712 new_image=AffineTransformImage(*image,&draw_info->affine,
3713 exception);
3714 break;
3715 }
3716 if (LocaleCompare("transparent",argv[0]+1) == 0)
3717 {
3718 PixelInfo
3719 target;
3720
3721 (void) SyncImageSettings(image_info,*image);
anthonya89dd172011-10-04 13:29:35 +00003722 (void) QueryMagickColorCompliance(argv[1],AllCompliance,&target,
3723 exception);
anthony805a2d42011-09-25 08:25:12 +00003724 (void) TransparentPaintImage(*image,&target,(Quantum)
3725 TransparentAlpha,*argv[0] == '-' ? MagickFalse : MagickTrue,
3726 &(*image)->exception);
3727 break;
3728 }
3729 if (LocaleCompare("transpose",argv[0]+1) == 0)
3730 {
3731 /*
3732 Transpose image scanlines.
3733 */
3734 (void) SyncImageSettings(image_info,*image);
3735 new_image=TransposeImage(*image,exception);
3736 break;
3737 }
3738 if (LocaleCompare("transverse",argv[0]+1) == 0)
3739 {
3740 /*
3741 Transverse image scanlines.
3742 */
3743 (void) SyncImageSettings(image_info,*image);
3744 new_image=TransverseImage(*image,exception);
3745 break;
3746 }
3747 if (LocaleCompare("treedepth",argv[0]+1) == 0)
3748 {
3749 quantize_info->tree_depth=StringToUnsignedLong(argv[1]);
3750 break;
3751 }
3752 if (LocaleCompare("trim",argv[0]+1) == 0)
3753 {
3754 /*
3755 Trim image.
3756 */
3757 (void) SyncImageSettings(image_info,*image);
3758 new_image=TrimImage(*image,exception);
3759 break;
3760 }
3761 if (LocaleCompare("type",argv[0]+1) == 0)
3762 {
3763 ImageType
3764 type;
3765
3766 (void) SyncImageSettings(image_info,*image);
3767 if (*argv[0] == '+')
3768 type=UndefinedType;
3769 else
3770 type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
3771 argv[1]);
3772 (*image)->type=UndefinedType;
3773 (void) SetImageType(*image,type,exception);
3774 break;
3775 }
3776 break;
3777 }
3778 case 'u':
3779 {
3780 if (LocaleCompare("undercolor",argv[0]+1) == 0)
3781 {
anthony1afdc7a2011-10-05 11:54:28 +00003782 (void) QueryColorCompliance(argv[1],AllCompliance,&draw_info->undercolor,
anthony805a2d42011-09-25 08:25:12 +00003783 exception);
3784 break;
3785 }
3786 if (LocaleCompare("unique",argv[0]+1) == 0)
3787 {
3788 if (*argv[0] == '+')
3789 {
3790 (void) DeleteImageArtifact(*image,"identify:unique-colors");
3791 break;
3792 }
3793 (void) SetImageArtifact(*image,"identify:unique-colors","true");
3794 (void) SetImageArtifact(*image,"verbose","true");
3795 break;
3796 }
3797 if (LocaleCompare("unique-colors",argv[0]+1) == 0)
3798 {
3799 /*
3800 Unique image colors.
3801 */
3802 (void) SyncImageSettings(image_info,*image);
3803 new_image=UniqueImageColors(*image,exception);
3804 break;
3805 }
3806 if (LocaleCompare("unsharp",argv[0]+1) == 0)
3807 {
3808 /*
3809 Unsharp mask image.
3810 */
3811 (void) SyncImageSettings(image_info,*image);
3812 flags=ParseGeometry(argv[1],&geometry_info);
3813 if ((flags & SigmaValue) == 0)
3814 geometry_info.sigma=1.0;
3815 if ((flags & XiValue) == 0)
3816 geometry_info.xi=1.0;
3817 if ((flags & PsiValue) == 0)
3818 geometry_info.psi=0.05;
3819 new_image=UnsharpMaskImage(*image,geometry_info.rho,
3820 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3821 break;
3822 }
3823 break;
3824 }
3825 case 'v':
3826 {
3827 if (LocaleCompare("verbose",argv[0]+1) == 0)
3828 {
3829 (void) SetImageArtifact(*image,argv[0]+1,
3830 *argv[0] == '+' ? "false" : "true");
3831 break;
3832 }
3833 if (LocaleCompare("vignette",argv[0]+1) == 0)
3834 {
3835 /*
3836 Vignette image.
3837 */
3838 (void) SyncImageSettings(image_info,*image);
3839 flags=ParseGeometry(argv[1],&geometry_info);
3840 if ((flags & SigmaValue) == 0)
3841 geometry_info.sigma=1.0;
3842 if ((flags & XiValue) == 0)
3843 geometry_info.xi=0.1*(*image)->columns;
3844 if ((flags & PsiValue) == 0)
3845 geometry_info.psi=0.1*(*image)->rows;
3846 new_image=VignetteImage(*image,geometry_info.rho,
3847 geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3848 ceil(geometry_info.psi-0.5),exception);
3849 break;
3850 }
3851 if (LocaleCompare("virtual-pixel",argv[0]+1) == 0)
3852 {
3853 if (*argv[0] == '+')
3854 {
3855 (void) SetImageVirtualPixelMethod(*image,
3856 UndefinedVirtualPixelMethod);
3857 break;
3858 }
3859 (void) SetImageVirtualPixelMethod(*image,(VirtualPixelMethod)
3860 ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
3861 argv[1]));
3862 break;
3863 }
3864 break;
3865 }
3866 case 'w':
3867 {
3868 if (LocaleCompare("wave",argv[0]+1) == 0)
3869 {
3870 /*
3871 Wave image.
3872 */
3873 (void) SyncImageSettings(image_info,*image);
3874 flags=ParseGeometry(argv[1],&geometry_info);
3875 if ((flags & SigmaValue) == 0)
3876 geometry_info.sigma=1.0;
3877 new_image=WaveImage(*image,geometry_info.rho,
anthonya89dd172011-10-04 13:29:35 +00003878 geometry_info.sigma,interpolate_method,exception);
anthony805a2d42011-09-25 08:25:12 +00003879 break;
3880 }
3881 if (LocaleCompare("weight",argv[0]+1) == 0)
3882 {
3883 draw_info->weight=StringToUnsignedLong(argv[1]);
3884 if (LocaleCompare(argv[1],"all") == 0)
3885 draw_info->weight=0;
3886 if (LocaleCompare(argv[1],"bold") == 0)
3887 draw_info->weight=700;
3888 if (LocaleCompare(argv[1],"bolder") == 0)
3889 if (draw_info->weight <= 800)
3890 draw_info->weight+=100;
3891 if (LocaleCompare(argv[1],"lighter") == 0)
3892 if (draw_info->weight >= 100)
3893 draw_info->weight-=100;
3894 if (LocaleCompare(argv[1],"normal") == 0)
3895 draw_info->weight=400;
3896 break;
3897 }
3898 if (LocaleCompare("white-threshold",argv[0]+1) == 0)
3899 {
3900 /*
3901 White threshold image.
3902 */
3903 (void) SyncImageSettings(image_info,*image);
3904 (void) WhiteThresholdImage(*image,argv[1],exception);
3905 InheritException(exception,&(*image)->exception);
3906 break;
3907 }
3908 break;
3909 }
3910 default:
3911 break;
3912 }
3913 /*
3914 Replace current image with any image that was generated
3915 */
3916 if (new_image != (Image *) NULL)
3917 ReplaceImageInListReturnLast(image,new_image);
3918
3919 /*
3920 Free resources.
3921 */
3922 quantize_info=DestroyQuantizeInfo(quantize_info);
3923 draw_info=DestroyDrawInfo(draw_info);
anthonya89dd172011-10-04 13:29:35 +00003924 status=(MagickStatusType) ((*image)->exception.severity ==
3925 UndefinedException ? 1 : 0);
3926 return(status == 0 ? MagickFalse : MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003927}
3928
3929/*
3930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3931% %
3932% %
3933% %
3934+ S e q u e n c e O p e r a t i o n I m a g e s %
3935% %
3936% %
3937% %
3938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3939%
3940% SequenceOperationImages() applies a single operation that apply to the
3941% entire image list (e.g. -append, -layers, -coalesce, etc.).
3942%
3943% The format of the MogrifyImage method is:
3944%
3945% MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
3946% const int argc, const char **argv,Image **images,
3947% ExceptionInfo *exception)
3948%
3949% A description of each parameter follows:
3950%
3951% o image_info: the image info..
3952%
3953% o argc: Specifies a pointer to an integer describing the number of
3954% elements in the argument vector.
3955%
3956% o argv: Specifies a pointer to a text array containing the command line
3957% arguments.
3958%
3959% o images: pointer to pointer of the first image in image list.
3960%
3961% o exception: return any errors or warnings in this structure.
3962%
3963*/
3964WandExport MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
3965 const int argc,const char **argv,Image **images,ExceptionInfo *exception)
3966{
3967
3968 MagickStatusType
3969 status;
3970
3971 QuantizeInfo
3972 *quantize_info;
3973
3974 assert(image_info != (ImageInfo *) NULL);
3975 assert(image_info->signature == MagickSignature);
3976 assert(images != (Image **) NULL);
3977 assert((*images)->previous == (Image *) NULL);
3978 assert((*images)->signature == MagickSignature);
3979 if ((*images)->debug != MagickFalse)
3980 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3981 (*images)->filename);
anthonya89dd172011-10-04 13:29:35 +00003982 if ((argc <= 0) || (*argv == (char *) NULL))
3983 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003984 status=MagickTrue;
3985
3986 switch (*(argv[0]+1))
3987 {
3988 case 'a':
3989 {
3990 if (LocaleCompare("affinity",argv[0]+1) == 0)
3991 {
3992 (void) SyncImagesSettings(image_info,*images);
3993 if (*argv[0] == '+')
3994 {
3995 (void) RemapImages(quantize_info,*images,(Image *) NULL,
3996 exception);
3997 break;
3998 }
3999 break;
4000 }
4001 if (LocaleCompare("append",argv[0]+1) == 0)
4002 {
4003 Image
4004 *append_image;
4005
4006 (void) SyncImagesSettings(image_info,*images);
4007 append_image=AppendImages(*images,*argv[0] == '-' ? MagickTrue :
4008 MagickFalse,exception);
4009 if (append_image == (Image *) NULL)
4010 {
4011 status=MagickFalse;
4012 break;
4013 }
4014 *images=DestroyImageList(*images);
4015 *images=append_image;
4016 break;
4017 }
4018 if (LocaleCompare("average",argv[0]+1) == 0)
4019 {
4020 Image
4021 *average_image;
4022
4023 /*
4024 Average an image sequence (deprecated).
4025 */
4026 (void) SyncImagesSettings(image_info,*images);
4027 average_image=EvaluateImages(*images,MeanEvaluateOperator,
4028 exception);
4029 if (average_image == (Image *) NULL)
4030 {
4031 status=MagickFalse;
4032 break;
4033 }
4034 *images=DestroyImageList(*images);
4035 *images=average_image;
4036 break;
4037 }
4038 break;
4039 }
4040 case 'c':
4041 {
4042 if (LocaleCompare("channel",argv[0]+1) == 0)
4043 {
4044 ChannelType
4045 channel;
4046
4047 if (*argv[0] == '+')
4048 {
4049 channel=DefaultChannels;
4050 break;
4051 }
4052 channel=(ChannelType) ParseChannelOption(argv[1]);
4053 SetPixelChannelMap(*images,channel);
4054 break;
4055 }
4056 if (LocaleCompare("clut",argv[0]+1) == 0)
4057 {
4058 Image
4059 *clut_image,
4060 *image;
4061
4062 (void) SyncImagesSettings(image_info,*images);
4063 image=RemoveFirstImageFromList(images);
4064 clut_image=RemoveFirstImageFromList(images);
4065 if (clut_image == (Image *) NULL)
4066 {
4067 status=MagickFalse;
4068 break;
4069 }
anthonya89dd172011-10-04 13:29:35 +00004070 (void) ClutImage(image,clut_image,interpolate_method,exception);
anthony805a2d42011-09-25 08:25:12 +00004071 clut_image=DestroyImage(clut_image);
4072 *images=DestroyImageList(*images);
4073 *images=image;
4074 break;
4075 }
4076 if (LocaleCompare("coalesce",argv[0]+1) == 0)
4077 {
4078 Image
4079 *coalesce_image;
4080
4081 (void) SyncImagesSettings(image_info,*images);
4082 coalesce_image=CoalesceImages(*images,exception);
4083 if (coalesce_image == (Image *) NULL)
4084 {
4085 status=MagickFalse;
4086 break;
4087 }
4088 *images=DestroyImageList(*images);
4089 *images=coalesce_image;
4090 break;
4091 }
4092 if (LocaleCompare("combine",argv[0]+1) == 0)
4093 {
4094 Image
4095 *combine_image;
4096
4097 (void) SyncImagesSettings(image_info,*images);
4098 combine_image=CombineImages(*images,exception);
4099 if (combine_image == (Image *) NULL)
4100 {
4101 status=MagickFalse;
4102 break;
4103 }
4104 *images=DestroyImageList(*images);
4105 *images=combine_image;
4106 break;
4107 }
4108 if (LocaleCompare("composite",argv[0]+1) == 0)
4109 {
4110 Image
4111 *mask_image,
4112 *composite_image,
4113 *image;
4114
4115 RectangleInfo
4116 geometry;
4117
anthony5f867ae2011-10-09 10:28:34 +00004118 ComposeOperator
4119 compose;
4120
4121 const char*
4122 value;
4123
4124 value=GetImageOption(image_info,"compose");
4125 if (value != (const char *) NULL)
4126 compose=(CompositeOperator) ParseCommandOption(
4127 MagickComposeOptions,MagickFalse,value);
4128 else
4129 compose=OverCompositeOp; /* use Over not image->compose */
4130
4131 const char*
4132 value=GetImageOption(image_info,"compose");
4133
4134 if (value != (const char *) NULL)
4135 compose=(CompositeOperator) ParseCommandOption(
4136 MagickComposeOptions,MagickFalse,value);
4137 else
4138 compose=OverCompositeOp; /* use Over not image->compose */
4139
4140
anthony805a2d42011-09-25 08:25:12 +00004141 (void) SyncImagesSettings(image_info,*images);
4142 image=RemoveFirstImageFromList(images);
4143 composite_image=RemoveFirstImageFromList(images);
4144 if (composite_image == (Image *) NULL)
4145 {
4146 status=MagickFalse;
4147 break;
4148 }
4149 (void) TransformImage(&composite_image,(char *) NULL,
4150 composite_image->geometry);
4151 SetGeometry(composite_image,&geometry);
4152 (void) ParseAbsoluteGeometry(composite_image->geometry,&geometry);
4153 GravityAdjustGeometry(image->columns,image->rows,image->gravity,
4154 &geometry);
4155 mask_image=RemoveFirstImageFromList(images);
4156 if (mask_image != (Image *) NULL)
4157 {
anthony5f867ae2011-10-09 10:28:34 +00004158 if ((compose == DisplaceCompositeOp) ||
4159 (compose == DistortCompositeOp))
anthony805a2d42011-09-25 08:25:12 +00004160 {
4161 /*
4162 Merge Y displacement into X displacement image.
4163 */
4164 (void) CompositeImage(composite_image,CopyGreenCompositeOp,
4165 mask_image,0,0);
4166 mask_image=DestroyImage(mask_image);
4167 }
4168 else
4169 {
4170 /*
4171 Set a blending mask for the composition.
4172 Posible error, what if image->mask already set.
4173 */
4174 image->mask=mask_image;
4175 (void) NegateImage(image->mask,MagickFalse,exception);
4176 }
4177 }
anthony5f867ae2011-10-09 10:28:34 +00004178 (void) CompositeImage(image,compose,composite_image,
anthony805a2d42011-09-25 08:25:12 +00004179 geometry.x,geometry.y);
4180 if (mask_image != (Image *) NULL)
4181 mask_image=image->mask=DestroyImage(image->mask);
4182 composite_image=DestroyImage(composite_image);
4183 InheritException(exception,&image->exception);
4184 *images=DestroyImageList(*images);
4185 *images=image;
4186 break;
4187 }
4188 break;
4189 }
4190 case 'd':
4191 {
4192 if (LocaleCompare("deconstruct",argv[0]+1) == 0)
4193 {
4194 Image
4195 *deconstruct_image;
4196
4197 (void) SyncImagesSettings(image_info,*images);
4198 deconstruct_image=CompareImagesLayers(*images,CompareAnyLayer,
4199 exception);
4200 if (deconstruct_image == (Image *) NULL)
4201 {
4202 status=MagickFalse;
4203 break;
4204 }
4205 *images=DestroyImageList(*images);
4206 *images=deconstruct_image;
4207 break;
4208 }
4209 if (LocaleCompare("delete",argv[0]+1) == 0)
4210 {
4211 if (*argv[0] == '+')
4212 DeleteImages(images,"-1",exception);
4213 else
4214 DeleteImages(images,argv[1],exception);
4215 break;
4216 }
4217 if (LocaleCompare("dither",argv[0]+1) == 0)
4218 {
4219 if (*argv[0] == '+')
4220 {
4221 quantize_info->dither=MagickFalse;
4222 break;
4223 }
4224 quantize_info->dither=MagickTrue;
4225 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
4226 MagickDitherOptions,MagickFalse,argv[1]);
4227 break;
4228 }
4229 if (LocaleCompare("duplicate",argv[0]+1) == 0)
4230 {
4231 Image
4232 *duplicate_images;
4233
4234 if (*argv[0] == '+')
4235 duplicate_images=DuplicateImages(*images,1,"-1",exception);
4236 else
4237 {
4238 const char
4239 *p;
4240
4241 size_t
4242 number_duplicates;
4243
4244 number_duplicates=(size_t) StringToLong(argv[1]);
4245 p=strchr(argv[1],',');
4246 if (p == (const char *) NULL)
4247 duplicate_images=DuplicateImages(*images,number_duplicates,
4248 "-1",exception);
4249 else
4250 duplicate_images=DuplicateImages(*images,number_duplicates,p,
4251 exception);
4252 }
4253 AppendImageToList(images, duplicate_images);
4254 (void) SyncImagesSettings(image_info,*images);
4255 break;
4256 }
4257 break;
4258 }
4259 case 'e':
4260 {
4261 if (LocaleCompare("evaluate-sequence",argv[0]+1) == 0)
4262 {
4263 Image
4264 *evaluate_image;
4265
4266 MagickEvaluateOperator
4267 op;
4268
4269 (void) SyncImageSettings(image_info,*images);
4270 op=(MagickEvaluateOperator) ParseCommandOption(
4271 MagickEvaluateOptions,MagickFalse,argv[1]);
4272 evaluate_image=EvaluateImages(*images,op,exception);
4273 if (evaluate_image == (Image *) NULL)
4274 {
4275 status=MagickFalse;
4276 break;
4277 }
4278 *images=DestroyImageList(*images);
4279 *images=evaluate_image;
4280 break;
4281 }
4282 break;
4283 }
4284 case 'f':
4285 {
4286 if (LocaleCompare("fft",argv[0]+1) == 0)
4287 {
4288 Image
4289 *fourier_image;
4290
4291 /*
4292 Implements the discrete Fourier transform (DFT).
4293 */
4294 (void) SyncImageSettings(image_info,*images);
4295 fourier_image=ForwardFourierTransformImage(*images,*argv[0] == '-' ?
4296 MagickTrue : MagickFalse,exception);
4297 if (fourier_image == (Image *) NULL)
4298 break;
4299 *images=DestroyImage(*images);
4300 *images=fourier_image;
4301 break;
4302 }
4303 if (LocaleCompare("flatten",argv[0]+1) == 0)
4304 {
4305 Image
4306 *flatten_image;
4307
4308 (void) SyncImagesSettings(image_info,*images);
4309 flatten_image=MergeImageLayers(*images,FlattenLayer,exception);
4310 if (flatten_image == (Image *) NULL)
4311 break;
4312 *images=DestroyImageList(*images);
4313 *images=flatten_image;
4314 break;
4315 }
4316 if (LocaleCompare("fx",argv[0]+1) == 0)
4317 {
4318 Image
4319 *fx_image;
4320
4321 (void) SyncImagesSettings(image_info,*images);
4322 fx_image=FxImage(*images,argv[1],exception);
4323 if (fx_image == (Image *) NULL)
4324 {
4325 status=MagickFalse;
4326 break;
4327 }
4328 *images=DestroyImageList(*images);
4329 *images=fx_image;
4330 break;
4331 }
4332 break;
4333 }
4334 case 'h':
4335 {
4336 if (LocaleCompare("hald-clut",argv[0]+1) == 0)
4337 {
4338 Image
4339 *hald_image,
4340 *image;
4341
4342 (void) SyncImagesSettings(image_info,*images);
4343 image=RemoveFirstImageFromList(images);
4344 hald_image=RemoveFirstImageFromList(images);
4345 if (hald_image == (Image *) NULL)
4346 {
4347 status=MagickFalse;
4348 break;
4349 }
4350 (void) HaldClutImage(image,hald_image,exception);
4351 hald_image=DestroyImage(hald_image);
4352 if (*images != (Image *) NULL)
4353 *images=DestroyImageList(*images);
4354 *images=image;
4355 break;
4356 }
4357 break;
4358 }
4359 case 'i':
4360 {
4361 if (LocaleCompare("ift",argv[0]+1) == 0)
4362 {
4363 Image
4364 *fourier_image,
4365 *magnitude_image,
4366 *phase_image;
4367
4368 /*
4369 Implements the inverse fourier discrete Fourier transform (DFT).
4370 */
4371 (void) SyncImagesSettings(image_info,*images);
4372 magnitude_image=RemoveFirstImageFromList(images);
4373 phase_image=RemoveFirstImageFromList(images);
4374 if (phase_image == (Image *) NULL)
4375 {
4376 status=MagickFalse;
4377 break;
4378 }
4379 fourier_image=InverseFourierTransformImage(magnitude_image,
4380 phase_image,*argv[0] == '-' ? MagickTrue : MagickFalse,exception);
4381 if (fourier_image == (Image *) NULL)
4382 break;
4383 if (*images != (Image *) NULL)
4384 *images=DestroyImage(*images);
4385 *images=fourier_image;
4386 break;
4387 }
4388 if (LocaleCompare("insert",argv[0]+1) == 0)
4389 {
4390 Image
4391 *p,
4392 *q;
4393
4394 index=0;
4395 if (*argv[0] != '+')
4396 index=(ssize_t) StringToLong(argv[1]);
4397 p=RemoveLastImageFromList(images);
4398 if (p == (Image *) NULL)
4399 {
4400 (void) ThrowMagickException(exception,GetMagickModule(),
4401 OptionError,"NoSuchImage","`%s'",argv[1]);
4402 status=MagickFalse;
4403 break;
4404 }
4405 q=p;
4406 if (index == 0)
4407 PrependImageToList(images,q);
4408 else
4409 if (index == (ssize_t) GetImageListLength(*images))
4410 AppendImageToList(images,q);
4411 else
4412 {
4413 q=GetImageFromList(*images,index-1);
4414 if (q == (Image *) NULL)
4415 {
4416 (void) ThrowMagickException(exception,GetMagickModule(),
4417 OptionError,"NoSuchImage","`%s'",argv[1]);
4418 status=MagickFalse;
4419 break;
4420 }
4421 InsertImageInList(&q,p);
4422 }
4423 *images=GetFirstImageInList(q);
4424 break;
4425 }
4426 if (LocaleCompare("interpolate",argv[0]+1) == 0)
4427 {
4428 interpolate_method=(PixelInterpolateMethod) ParseCommandOption(
4429 MagickInterpolateOptions,MagickFalse,argv[1]);
4430 break;
4431 }
4432 break;
4433 }
4434 case 'l':
4435 {
4436 if (LocaleCompare("layers",argv[0]+1) == 0)
4437 {
4438 Image
4439 *layers;
4440
4441 ImageLayerMethod
4442 method;
4443
4444 (void) SyncImagesSettings(image_info,*images);
4445 layers=(Image *) NULL;
4446 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
4447 MagickFalse,argv[1]);
4448 switch (method)
4449 {
4450 case CoalesceLayer:
4451 {
4452 layers=CoalesceImages(*images,exception);
4453 break;
4454 }
4455 case CompareAnyLayer:
4456 case CompareClearLayer:
4457 case CompareOverlayLayer:
4458 default:
4459 {
4460 layers=CompareImagesLayers(*images,method,exception);
4461 break;
4462 }
4463 case MergeLayer:
4464 case FlattenLayer:
4465 case MosaicLayer:
4466 case TrimBoundsLayer:
4467 {
4468 layers=MergeImageLayers(*images,method,exception);
4469 break;
4470 }
4471 case DisposeLayer:
4472 {
4473 layers=DisposeImages(*images,exception);
4474 break;
4475 }
4476 case OptimizeImageLayer:
4477 {
4478 layers=OptimizeImageLayers(*images,exception);
4479 break;
4480 }
4481 case OptimizePlusLayer:
4482 {
4483 layers=OptimizePlusImageLayers(*images,exception);
4484 break;
4485 }
4486 case OptimizeTransLayer:
4487 {
4488 OptimizeImageTransparency(*images,exception);
4489 break;
4490 }
4491 case RemoveDupsLayer:
4492 {
4493 RemoveDuplicateLayers(images,exception);
4494 break;
4495 }
4496 case RemoveZeroLayer:
4497 {
4498 RemoveZeroDelayLayers(images,exception);
4499 break;
4500 }
4501 case OptimizeLayer:
4502 {
4503 /*
4504 General Purpose, GIF Animation Optimizer.
4505 */
4506 layers=CoalesceImages(*images,exception);
4507 if (layers == (Image *) NULL)
4508 {
4509 status=MagickFalse;
4510 break;
4511 }
4512 *images=DestroyImageList(*images);
4513 *images=layers;
4514 layers=OptimizeImageLayers(*images,exception);
4515 if (layers == (Image *) NULL)
4516 {
4517 status=MagickFalse;
4518 break;
4519 }
4520 *images=DestroyImageList(*images);
4521 *images=layers;
4522 layers=(Image *) NULL;
4523 OptimizeImageTransparency(*images,exception);
4524 (void) RemapImages(quantize_info,*images,(Image *) NULL,
4525 exception);
4526 break;
4527 }
4528 case CompositeLayer:
4529 {
anthony805a2d42011-09-25 08:25:12 +00004530 Image
4531 *source;
4532
4533 RectangleInfo
4534 geometry;
4535
anthony5f867ae2011-10-09 10:28:34 +00004536 ComposeOperator
4537 compose;
4538
4539 const char*
4540 value;
4541
4542 value=GetImageOption(image_info,"compose");
4543 if (value != (const char *) NULL)
4544 compose=(CompositeOperator) ParseCommandOption(
4545 MagickComposeOptions,MagickFalse,value);
4546 else
4547 compose=OverCompositeOp; /* use Over not image->compose */
4548
anthony805a2d42011-09-25 08:25:12 +00004549 /*
4550 Split image sequence at the first 'NULL:' image.
4551 */
4552 source=(*images);
4553 while (source != (Image *) NULL)
4554 {
4555 source=GetNextImageInList(source);
4556 if ((source != (Image *) NULL) &&
4557 (LocaleCompare(source->magick,"NULL") == 0))
4558 break;
4559 }
4560 if (source != (Image *) NULL)
4561 {
4562 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4563 (GetNextImageInList(source) == (Image *) NULL))
4564 source=(Image *) NULL;
4565 else
4566 {
4567 /*
4568 Separate the two lists, junk the null: image.
4569 */
4570 source=SplitImageList(source->previous);
4571 DeleteImageFromList(&source);
4572 }
4573 }
4574 if (source == (Image *) NULL)
4575 {
4576 (void) ThrowMagickException(exception,GetMagickModule(),
4577 OptionError,"MissingNullSeparator","layers Composite");
4578 status=MagickFalse;
4579 break;
4580 }
4581 /*
4582 Adjust offset with gravity and virtual canvas.
4583 */
4584 SetGeometry(*images,&geometry);
4585 (void) ParseAbsoluteGeometry((*images)->geometry,&geometry);
4586 geometry.width=source->page.width != 0 ?
4587 source->page.width : source->columns;
4588 geometry.height=source->page.height != 0 ?
4589 source->page.height : source->rows;
4590 GravityAdjustGeometry((*images)->page.width != 0 ?
4591 (*images)->page.width : (*images)->columns,
4592 (*images)->page.height != 0 ? (*images)->page.height :
4593 (*images)->rows,(*images)->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004594
4595 /*
4596 Compose the two image sequences together
4597 */
anthony805a2d42011-09-25 08:25:12 +00004598 CompositeLayers(*images,compose,source,geometry.x,geometry.y,
4599 exception);
4600 source=DestroyImageList(source);
4601 break;
4602 }
4603 }
4604 if (layers == (Image *) NULL)
4605 break;
4606 InheritException(exception,&layers->exception);
4607 *images=DestroyImageList(*images);
4608 *images=layers;
4609 break;
4610 }
4611 break;
4612 }
4613 case 'm':
4614 {
4615 if (LocaleCompare("map",argv[0]+1) == 0)
4616 {
4617 (void) SyncImagesSettings(image_info,*images);
4618 if (*argv[0] == '+')
4619 {
4620 (void) RemapImages(quantize_info,*images,(Image *) NULL,
4621 exception);
4622 break;
4623 }
4624 break;
4625 }
4626 if (LocaleCompare("maximum",argv[0]+1) == 0)
4627 {
4628 Image
4629 *maximum_image;
4630
4631 /*
4632 Maximum image sequence (deprecated).
4633 */
4634 (void) SyncImagesSettings(image_info,*images);
4635 maximum_image=EvaluateImages(*images,MaxEvaluateOperator,exception);
4636 if (maximum_image == (Image *) NULL)
4637 {
4638 status=MagickFalse;
4639 break;
4640 }
4641 *images=DestroyImageList(*images);
4642 *images=maximum_image;
4643 break;
4644 }
4645 if (LocaleCompare("minimum",argv[0]+1) == 0)
4646 {
4647 Image
4648 *minimum_image;
4649
4650 /*
4651 Minimum image sequence (deprecated).
4652 */
4653 (void) SyncImagesSettings(image_info,*images);
4654 minimum_image=EvaluateImages(*images,MinEvaluateOperator,exception);
4655 if (minimum_image == (Image *) NULL)
4656 {
4657 status=MagickFalse;
4658 break;
4659 }
4660 *images=DestroyImageList(*images);
4661 *images=minimum_image;
4662 break;
4663 }
4664 if (LocaleCompare("morph",argv[0]+1) == 0)
4665 {
4666 Image
4667 *morph_image;
4668
4669 (void) SyncImagesSettings(image_info,*images);
4670 morph_image=MorphImages(*images,StringToUnsignedLong(argv[1]),
4671 exception);
4672 if (morph_image == (Image *) NULL)
4673 {
4674 status=MagickFalse;
4675 break;
4676 }
4677 *images=DestroyImageList(*images);
4678 *images=morph_image;
4679 break;
4680 }
4681 if (LocaleCompare("mosaic",argv[0]+1) == 0)
4682 {
4683 Image
4684 *mosaic_image;
4685
4686 (void) SyncImagesSettings(image_info,*images);
4687 mosaic_image=MergeImageLayers(*images,MosaicLayer,exception);
4688 if (mosaic_image == (Image *) NULL)
4689 {
4690 status=MagickFalse;
4691 break;
4692 }
4693 *images=DestroyImageList(*images);
4694 *images=mosaic_image;
4695 break;
4696 }
4697 break;
4698 }
4699 case 'p':
4700 {
4701 if (LocaleCompare("print",argv[0]+1) == 0)
4702 {
4703 char
4704 *string;
4705
4706 (void) SyncImagesSettings(image_info,*images);
4707 string=InterpretImageProperties(image_info,*images,argv[1],
4708 exception);
4709 if (string == (char *) NULL)
4710 break;
4711 (void) FormatLocaleFile(stdout,"%s",string);
4712 string=DestroyString(string);
4713 }
4714 if (LocaleCompare("process",argv[0]+1) == 0)
4715 {
4716 char
4717 **arguments;
4718
4719 int
4720 j,
4721 number_arguments;
4722
4723 (void) SyncImagesSettings(image_info,*images);
4724 arguments=StringToArgv(argv[1],&number_arguments);
4725 if (arguments == (char **) NULL)
4726 break;
4727 if ((argc > 1) && (strchr(arguments[1],'=') != (char *) NULL))
4728 {
4729 char
4730 breaker,
4731 quote,
4732 *token;
4733
4734 const char
4735 *arguments;
4736
4737 int
4738 next,
4739 status;
4740
4741 size_t
4742 length;
4743
4744 TokenInfo
4745 *token_info;
4746
4747 /*
4748 Support old style syntax, filter="-option arg".
4749 */
4750 length=strlen(argv[1]);
4751 token=(char *) NULL;
4752 if (~length >= (MaxTextExtent-1))
4753 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4754 sizeof(*token));
4755 if (token == (char *) NULL)
4756 break;
4757 next=0;
4758 arguments=argv[1];
4759 token_info=AcquireTokenInfo();
4760 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4761 "\"",'\0',&breaker,&next,&quote);
4762 token_info=DestroyTokenInfo(token_info);
4763 if (status == 0)
4764 {
4765 const char
4766 *argv;
4767
4768 argv=(&(arguments[next]));
4769 (void) InvokeDynamicImageFilter(token,&(*images),1,&argv,
4770 exception);
4771 }
4772 token=DestroyString(token);
4773 break;
4774 }
4775 (void) SubstituteString(&arguments[1],"-","");
4776 (void) InvokeDynamicImageFilter(arguments[1],&(*images),
4777 number_arguments-2,(const char **) arguments+2,exception);
4778 for (j=0; j < number_arguments; j++)
4779 arguments[j]=DestroyString(arguments[j]);
4780 arguments=(char **) RelinquishMagickMemory(arguments);
4781 break;
4782 }
4783 break;
4784 }
4785 case 'r':
4786 {
4787 if (LocaleCompare("reverse",argv[0]+1) == 0)
4788 {
4789 ReverseImageList(images);
4790 InheritException(exception,&(*images)->exception);
4791 break;
4792 }
4793 break;
4794 }
4795 case 's':
4796 {
4797 if (LocaleCompare("smush",argv[0]+1) == 0)
4798 {
4799 Image
4800 *smush_image;
4801
4802 ssize_t
4803 offset;
4804
4805 (void) SyncImagesSettings(image_info,*images);
4806 offset=(ssize_t) StringToLong(argv[1]);
4807 smush_image=SmushImages(*images,*argv[0] == '-' ? MagickTrue :
4808 MagickFalse,offset,exception);
4809 if (smush_image == (Image *) NULL)
4810 {
4811 status=MagickFalse;
4812 break;
4813 }
4814 *images=DestroyImageList(*images);
4815 *images=smush_image;
4816 break;
4817 }
4818 if (LocaleCompare("swap",argv[0]+1) == 0)
4819 {
4820 Image
4821 *p,
4822 *q,
4823 *swap;
4824
4825 ssize_t
4826 swap_index;
4827
4828 index=(-1);
4829 swap_index=(-2);
4830 if (*argv[0] != '+')
4831 {
4832 GeometryInfo
4833 geometry_info;
4834
4835 MagickStatusType
4836 flags;
4837
4838 swap_index=(-1);
4839 flags=ParseGeometry(argv[1],&geometry_info);
4840 index=(ssize_t) geometry_info.rho;
4841 if ((flags & SigmaValue) != 0)
4842 swap_index=(ssize_t) geometry_info.sigma;
4843 }
4844 p=GetImageFromList(*images,index);
4845 q=GetImageFromList(*images,swap_index);
4846 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4847 {
4848 (void) ThrowMagickException(exception,GetMagickModule(),
4849 OptionError,"NoSuchImage","`%s'",(*images)->filename);
4850 status=MagickFalse;
4851 break;
4852 }
4853 if (p == q)
4854 break;
4855 swap=CloneImage(p,0,0,MagickTrue,exception);
4856 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4857 ReplaceImageInList(&q,swap);
4858 *images=GetFirstImageInList(q);
4859 break;
4860 }
4861 break;
4862 }
4863 case 'w':
4864 {
4865 if (LocaleCompare("write",argv[0]+1) == 0)
4866 {
4867 char
4868 key[MaxTextExtent];
4869
4870 Image
4871 *write_images;
4872
4873 ImageInfo
4874 *write_info;
4875
4876 (void) SyncImagesSettings(image_info,*images);
4877 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",argv[1]);
4878 (void) DeleteImageRegistry(key);
4879 write_images=(*images);
4880 if (*argv[0] == '+')
4881 write_images=CloneImageList(*images,exception);
4882 write_info=CloneImageInfo(image_info);
4883 status&=WriteImages(write_info,write_images,argv[1],exception);
4884 write_info=DestroyImageInfo(write_info);
4885 if (*argv[0] == '+')
4886 write_images=DestroyImageList(write_images);
4887 break;
4888 }
4889 break;
4890 }
4891 default:
4892 break;
4893 }
4894 quantize_info=DestroyQuantizeInfo(quantize_info);
4895
anthonya89dd172011-10-04 13:29:35 +00004896 status=(MagickStatusType) ((*image)->exception.severity ==
4897 UndefinedException ? 1 : 0);
anthony805a2d42011-09-25 08:25:12 +00004898 return(status != 0 ? MagickTrue : MagickFalse);
4899}
cristy0a0ca4f2011-09-28 01:15:28 +00004900#endif