blob: 5cfeedc6b499f98c6efdf4d409e9069bcf0a2560 [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 IfSetOption ((*argv[0])=='-')
437
438 switch (*option)
anthony805a2d42011-09-25 08:25:12 +0000439 {
440 case 'a':
441 {
anthony74b1cfc2011-10-06 12:44:16 +0000442 if (LocaleCompare("adjoin",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000443 {
anthony74b1cfc2011-10-06 12:44:16 +0000444 image_info->adjoin = IfSetOption ? MagickTrue : MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000445 break;
446 }
anthony74b1cfc2011-10-06 12:44:16 +0000447 if (LocaleCompare("affine",option) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000448 {
anthony74b1cfc2011-10-06 12:44:16 +0000449 if (IfSetOption)
anthony1afdc7a2011-10-05 11:54:28 +0000450 (void) ParseAffineGeometry(argv[1],draw_info->affine,
451 exception);
anthony74b1cfc2011-10-06 12:44:16 +0000452 else
453 GetAffineMatrix(draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000454 break;
455 }
anthony74b1cfc2011-10-06 12:44:16 +0000456 if (LocaleCompare("antialias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000457 {
anthony1afdc7a2011-10-05 11:54:28 +0000458 image_info->antialias =
459 draw_info->stroke_antialias =
460 draw_info->text_antialias =
anthony74b1cfc2011-10-06 12:44:16 +0000461 IfSetOption ? MagickTrue : MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000462 break;
463 }
anthony74b1cfc2011-10-06 12:44:16 +0000464 if (LocaleCompare("authenticate",option) == 0)
anthony5f867ae2011-10-09 10:28:34 +0000465 {
anthony74b1cfc2011-10-06 12:44:16 +0000466 (void) SetImageOption(image_info,option,
anthony6dc09cd2011-10-12 08:56:49 +0000467 IfSetOption ? argv[1] : (const char*)NULL);
anthony805a2d42011-09-25 08:25:12 +0000468 break;
469 }
470 break;
471 }
472 case 'b':
473 {
anthony74b1cfc2011-10-06 12:44:16 +0000474 if (LocaleCompare("background",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000475 {
anthony74b1cfc2011-10-06 12:44:16 +0000476 /* FUTURE: both image_info attribute & ImageOption in use!
477 Note that +background, means fall-back to image attribute
478 so ImageOption is deleted, not set to a default.
479 */
480 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000481 {
anthony74b1cfc2011-10-06 12:44:16 +0000482 (void) DeleteImageOption(image_info,option);
anthony1afdc7a2011-10-05 11:54:28 +0000483 (void) QueryColorCompliance(BackgroundColor,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000484 image_info->background_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000485 break;
486 }
anthony74b1cfc2011-10-06 12:44:16 +0000487 (void) SetImageOption(image_info,option,argv[1]);
anthony1afdc7a2011-10-05 11:54:28 +0000488 (void) QueryColorCompliance(argv[1],AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000489 image_info->background_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000490 break;
491 }
anthony74b1cfc2011-10-06 12:44:16 +0000492 if (LocaleCompare("bias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000493 {
anthony74b1cfc2011-10-06 12:44:16 +0000494 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
495 as it is actually rarely used except in direct convolve
496 Usage outside direct convolve is actally non-sensible!
497 */
498 (void) SetImageOption(image_info,option,
499 IfSetOption ? argv[1] : "0");
anthony805a2d42011-09-25 08:25:12 +0000500 break;
501 }
anthony74b1cfc2011-10-06 12:44:16 +0000502 if (LocaleCompare("black-point-compensation",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000503 {
anthony74b1cfc2011-10-06 12:44:16 +0000504 (void) SetImageOption(image_info,option,
505 IfSetOption ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +0000506 break;
507 }
anthony74b1cfc2011-10-06 12:44:16 +0000508 if (LocaleCompare("blue-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000509 {
anthony74b1cfc2011-10-06 12:44:16 +0000510 (void) SetImageOption(image_info,option,
511 IfSetOption ? argv[1] : "0" );
anthony805a2d42011-09-25 08:25:12 +0000512 break;
513 }
anthony74b1cfc2011-10-06 12:44:16 +0000514 if (LocaleCompare("bordercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000515 {
anthony74b1cfc2011-10-06 12:44:16 +0000516 /* FUTURE: both image_info attribute & ImageOption in use! */
517 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000518 {
anthony74b1cfc2011-10-06 12:44:16 +0000519 (void) SetImageOption(image_info,option,argv[1]);
520 (void) QueryColorCompliance(argv[1],AllCompliece,
521 &image_info->border_color,exception);
522 (void) QueryColorCompliance(argv[1],AllCompliance,
523 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000524 break;
525 }
anthony74b1cfc2011-10-06 12:44:16 +0000526 (void) DeleteImageOption(image_info,option);
527 (void) QueryColorCompliance(BorderColor,AllCompliance,
528 &image_info->border_color,exception);
529 (void) QueryColorCompliance(BorderColor,AllCompliance,
530 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000531 break;
532 }
anthony74b1cfc2011-10-06 12:44:16 +0000533 if (LocaleCompare("box",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000534 {
anthony74b1cfc2011-10-06 12:44:16 +0000535 const char
536 *value = IfSetOption ? argv[1] : "none";
537 (void) SetImageOption(image_info,option,value);
538 (void) QueryColorCompliance(value,AllCompliance,
539 &draw_info->undercolor,exception);
anthony805a2d42011-09-25 08:25:12 +0000540 break;
541 }
542 break;
543 }
544 case 'c':
545 {
anthony74b1cfc2011-10-06 12:44:16 +0000546 if (LocaleCompare("cache",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000547 {
548 MagickSizeType
549 limit;
550
551 limit=MagickResourceInfinity;
552 if (LocaleCompare("unlimited",argv[1]) != 0)
553 limit=(MagickSizeType) SiPrefixToDouble(argv[1],100.0);
554 (void) SetMagickResourceLimit(MemoryResource,limit);
555 (void) SetMagickResourceLimit(MapResource,2*limit);
556 break;
557 }
anthony74b1cfc2011-10-06 12:44:16 +0000558 if (LocaleCompare("caption",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000559 {
anthony74b1cfc2011-10-06 12:44:16 +0000560 (void) SetImageOption(image_info,option,
anthony6dc09cd2011-10-12 08:56:49 +0000561 IfSetOption ? argv[1] : (const char*)NULL);
anthony805a2d42011-09-25 08:25:12 +0000562 break;
563 }
anthony74b1cfc2011-10-06 12:44:16 +0000564 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000565 {
anthony74b1cfc2011-10-06 12:44:16 +0000566 image_info->channel=(ChannelType) (
567 IfSetOption ? ParseChannelOption(argv[1]) : DefaultChannels );
anthony965524b2011-10-07 12:34:14 +0000568 /* This is also a SimpleImageOperator */
anthony805a2d42011-09-25 08:25:12 +0000569 break;
570 }
anthony74b1cfc2011-10-06 12:44:16 +0000571 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000572 {
anthony965524b2011-10-07 12:34:14 +0000573 /* This is also a SimpleImageOperator */
anthonyd2cdc862011-10-07 14:07:17 +0000574 /* Undefined colorspace means don't modify images */
anthony965524b2011-10-07 12:34:14 +0000575 image_info->colorspace=UndefinedColorspace;
anthonyd2cdc862011-10-07 14:07:17 +0000576 if (IfSetOption)
577 image_info->colorspace=(ColorspaceType) ParseCommandOption(
578 MagickColorspaceOptions,MagickFalse,argv[1])
anthony805a2d42011-09-25 08:25:12 +0000579 break;
580 }
anthony74b1cfc2011-10-06 12:44:16 +0000581 if (LocaleCompare("comment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000582 {
anthony965524b2011-10-07 12:34:14 +0000583 (void) SetImageOption(image_info,option,
anthony6dc09cd2011-10-12 08:56:49 +0000584 IfSetOption ? argv[1] : (const char*)NULL);
anthony805a2d42011-09-25 08:25:12 +0000585 break;
586 }
anthony74b1cfc2011-10-06 12:44:16 +0000587 if (LocaleCompare("compose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000588 {
anthony965524b2011-10-07 12:34:14 +0000589 /* FUTURE: What should be used? image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000590 The former is more efficent, but Crisy prefers the latter!
anthony965524b2011-10-07 12:34:14 +0000591 */
anthony5f867ae2011-10-09 10:28:34 +0000592 (void) SetImageOption(image_info,option,
anthony6dc09cd2011-10-12 08:56:49 +0000593 IfSetOption ? argv[1] : (const char*)NULL);
anthony965524b2011-10-07 12:34:14 +0000594 image_info->compose=(CompositeOperator) ParseCommandOption(
anthony5f867ae2011-10-09 10:28:34 +0000595 MagickComposeOptions,MagickFalse,
596 IfSetOption ? argv[1] : "undefined");
anthony805a2d42011-09-25 08:25:12 +0000597 break;
598 }
anthony74b1cfc2011-10-06 12:44:16 +0000599 if (LocaleCompare("compress",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000600 {
anthony5f867ae2011-10-09 10:28:34 +0000601 /* FUTURE: What should be used? image_info or ImageOption ???
602 The former is more efficent, but Crisy prefers the latter!
603
604 The coders appears to use image_info, not Image_Option
605 however the image attribute (for save) is set from the
606 ImageOption!
607 */
608 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000609 {
anthony5f867ae2011-10-09 10:28:34 +0000610 image_info->compression=(CompressionType) ParseCommandOption(
611 MagickCompressOptions,MagickFalse,argv[1]);
612 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000613 break;
614 }
anthony5f867ae2011-10-09 10:28:34 +0000615 image_info->compression=UndefinedCompression;
616 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000617 break;
618 }
619 break;
620 }
621 case 'd':
622 {
anthony74b1cfc2011-10-06 12:44:16 +0000623 if (LocaleCompare("debug",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000624 {
anthony5f867ae2011-10-09 10:28:34 +0000625 if (IfSetOption)
626 (void) SetLogEventMask(IfSetOption?argv[1]:"none");
627 image_info->debug=IsEventLogging(); /* extract logging*/
628 wand->debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000629 break;
630 }
anthony74b1cfc2011-10-06 12:44:16 +0000631 if (LocaleCompare("define",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000632 {
anthony5f867ae2011-10-09 10:28:34 +0000633 /* FUTURE both -set and -define sets ImageOption
634 But differs in that -set tried to set image properity (attribute)
635 */
anthony805a2d42011-09-25 08:25:12 +0000636 if (LocaleNCompare(argv[1],"registry:",9) == 0)
637 {
anthony5f867ae2011-10-09 10:28:34 +0000638 if (IfSetOption)
639 (void) DefineImageRegistry(StringRegistryType,argv[1]+9,
640 exception);
641 else
642 (void) DefineImageOption(image_info,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000643 break;
644 }
anthony5f867ae2011-10-09 10:28:34 +0000645 if (IfSetOption)
646 (void) DefineImageOption(image_info,argv[1]);
647 else
648 (void) DeleteImageOption(image_info,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000649 break;
650 }
anthony74b1cfc2011-10-06 12:44:16 +0000651 if (LocaleCompare("delay",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000652 {
anthony5f867ae2011-10-09 10:28:34 +0000653 /* transfered to new images only via AcquireImage()
654 -set delay must be used to set attributes directly.
655 */
656 (void) SetImageOption(image_info,option,
657 IfSetOption ? argv[1] : "0");
anthony805a2d42011-09-25 08:25:12 +0000658 break;
659 }
anthony74b1cfc2011-10-06 12:44:16 +0000660 if (LocaleCompare("density",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000661 {
anthony5f867ae2011-10-09 10:28:34 +0000662 /* FUTURE: At this time everyone is using image_info string
663 The Image Option is not being used.
anthony805a2d42011-09-25 08:25:12 +0000664 */
anthony5f867ae2011-10-09 10:28:34 +0000665 if (IsSetOption)
anthony805a2d42011-09-25 08:25:12 +0000666 {
anthony5f867ae2011-10-09 10:28:34 +0000667 (void) CloneString(&image_info->density,argv[1]);
668 (void) CloneString(&draw_info->density,argv[1]);
669 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000670 break;
671 }
anthony5f867ae2011-10-09 10:28:34 +0000672 if (image_info->density != (char *) NULL)
673 image_info->density=DestroyString(image_info->density);
674 if (draw_info->density != (char *) NULL)
675 draw_info->density=DestroyString(draw_info->density);
676 (void) SetImageOption(image_info,option,"72");
anthony805a2d42011-09-25 08:25:12 +0000677 break;
678 }
anthony74b1cfc2011-10-06 12:44:16 +0000679 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000680 {
anthony5f867ae2011-10-09 10:28:34 +0000681 /* This is also a SimpleImageOperator! */
682 image_info->depth=IsSetOption?StringToUnsignedLong(argv[1])
683 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000684 break;
685 }
anthony74b1cfc2011-10-06 12:44:16 +0000686 if (LocaleCompare("direction",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000687 {
anthony6dc09cd2011-10-12 08:56:49 +0000688 /* Image Option is only used to set draw_info */
anthony5f867ae2011-10-09 10:28:34 +0000689 (void) SetImageOption(image_info,option,
690 IfSetOption ? argv[1] : "undefined");
691 draw_info->direction=(DirectionType) ParseCommandOption(
692 MagickDirectionOptions,MagickFalse,
693 IfSetOption ? argv[1] : "undefined");
anthony805a2d42011-09-25 08:25:12 +0000694 break;
695 }
anthony74b1cfc2011-10-06 12:44:16 +0000696 if (LocaleCompare("display",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000697 {
anthony5f867ae2011-10-09 10:28:34 +0000698 if (IfSetOption)
699 (void) CloneString(&image_info->server_name,argv[1]);
700 else
701 if (image_info->server_name != (char *) NULL)
702 image_info->server_name=DestroyString(image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000703 break;
704 }
anthony74b1cfc2011-10-06 12:44:16 +0000705 if (LocaleCompare("dispose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000706 {
anthony5f867ae2011-10-09 10:28:34 +0000707 (void) SetImageOption(image_info,option,
708 IfSetOption ? argv[1] : "undefined");
anthony805a2d42011-09-25 08:25:12 +0000709 break;
710 }
anthony74b1cfc2011-10-06 12:44:16 +0000711 if (LocaleCompare("dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000712 {
anthony5f867ae2011-10-09 10:28:34 +0000713 /* FUTURE: Merge boolean image_info->dither with Dither type */
714 (void) SetImageOption(image_info,option,
715 IfSetOption ? argv[1] : "none");
716 image_info->dither = quantize_info->dither =
anthony6dc09cd2011-10-12 08:56:49 +0000717 IfSetOption ? MagickTrue : MagickFalse;
anthony5f867ae2011-10-09 10:28:34 +0000718 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony6dc09cd2011-10-12 08:56:49 +0000719 MagickDitherOptions,MagickFalse,
720 IfSetOption ? argv[1] : "none");
anthony5f867ae2011-10-09 10:28:34 +0000721 if (quantize_info->dither_method == NoDitherMethod)
anthony6dc09cd2011-10-12 08:56:49 +0000722 image_info->dither = quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000723 break;
724 }
725 break;
726 }
727 case 'e':
728 {
anthony74b1cfc2011-10-06 12:44:16 +0000729 if (LocaleCompare("encoding",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000730 {
anthony6dc09cd2011-10-12 08:56:49 +0000731 (void) CloneString(&draw_info->encoding,
732 IfSetOption ? argv[1] : "undefined");
733 (void) SetImageOption(image_info,option,&draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000734 break;
735 }
anthony74b1cfc2011-10-06 12:44:16 +0000736 if (LocaleCompare("endian",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000737 {
anthony6dc09cd2011-10-12 08:56:49 +0000738 const char
739 value;
740
741 value=IfSetOption?argv[1]:"undefined";
742 (void) SetImageOption(image_info,option,value);
anthony805a2d42011-09-25 08:25:12 +0000743 image_info->endian=(EndianType) ParseCommandOption(
anthony6dc09cd2011-10-12 08:56:49 +0000744 MagickEndianOptions,MagickFalse,value);
anthony805a2d42011-09-25 08:25:12 +0000745 break;
746 }
anthony74b1cfc2011-10-06 12:44:16 +0000747 if (LocaleCompare("extract",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000748 {
anthony6dc09cd2011-10-12 08:56:49 +0000749 (void) CloneString(&image_info->extract,
750 IfSetOption?argv[1]:(const char *) NULL);
anthony805a2d42011-09-25 08:25:12 +0000751 break;
752 }
753 break;
754 }
755 case 'f':
756 {
anthony6dc09cd2011-10-12 08:56:49 +0000757 if (LocaleCompare("family",argv[0]+1) == 0)
758 {
759 (void) CloneString(&draw_info->family,
760 IfSetOption ? argv[1] : (const char *) NULL);
761 break;
762 }
anthony74b1cfc2011-10-06 12:44:16 +0000763 if (LocaleCompare("fill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000764 {
anthony6dc09cd2011-10-12 08:56:49 +0000765 const char
766 value;
767
768 ExceptionInfo
769 *sans;
770
771 value = IfSetOption ? argv[1] : "none";
772 (void) SetImageOption(image_info,option,value);
773
774 sans=AcquireExceptionInfo();
775 /*(void) QueryMagickColorCompliance(value,AllCompliance,&fill,sans);*/
776 status=QueryColorCompliance(value,AllCompliance,&draw_info->fill,sans);
777 sans=DestroyExceptionInfo(sans);
778
779 if (draw_info->fill_pattern != (Image *) NULL)
780 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
781 if (status == MagickFalse)
782 draw_info->fill_pattern=GetImageCache(image_info,value,
783 exception);
anthony805a2d42011-09-25 08:25:12 +0000784 break;
785 }
anthony74b1cfc2011-10-06 12:44:16 +0000786 if (LocaleCompare("filter",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000787 {
anthony6dc09cd2011-10-12 08:56:49 +0000788 (void) SetImageOption(image_info,option,
789 IfSetOption ? argv[1] : "undefined");
anthony805a2d42011-09-25 08:25:12 +0000790 break;
791 }
anthony6dc09cd2011-10-12 08:56:49 +0000792 if (LocaleCompare("font",argv[0]+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000793 {
anthony6dc09cd2011-10-12 08:56:49 +0000794 (void) CloneString(&draw_info->font,
795 IfSetOption ? argv[1] : (const char *) NULL);
796 (void) CloneString(&image_info->font,draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000797 break;
798 }
anthony74b1cfc2011-10-06 12:44:16 +0000799 if (LocaleCompare("format",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000800 {
anthony6dc09cd2011-10-12 08:56:49 +0000801 /* FUTURE: why the ping test, the user could set ping after this! */
anthony805a2d42011-09-25 08:25:12 +0000802 register const char
803 *q;
804
805 for (q=strchr(argv[1],'%'); q != (char *) NULL; q=strchr(q+1,'%'))
806 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
807 image_info->ping=MagickFalse;
anthony74b1cfc2011-10-06 12:44:16 +0000808 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000809 break;
810 }
anthony74b1cfc2011-10-06 12:44:16 +0000811 if (LocaleCompare("fuzz",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000812 {
anthony6dc09cd2011-10-12 08:56:49 +0000813 /* FUTURE: image_info and ImageOption! */
anthony805a2d42011-09-25 08:25:12 +0000814 if (*argv[0] == '+')
815 {
816 image_info->fuzz=0.0;
anthony74b1cfc2011-10-06 12:44:16 +0000817 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +0000818 break;
819 }
820 image_info->fuzz=SiPrefixToDouble(argv[1],(double) QuantumRange+
821 1.0);
anthony74b1cfc2011-10-06 12:44:16 +0000822 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000823 break;
824 }
825 break;
826 }
827 case 'g':
828 {
anthony74b1cfc2011-10-06 12:44:16 +0000829 if (LocaleCompare("gravity",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000830 {
831 if (*argv[0] == '+')
832 {
anthony74b1cfc2011-10-06 12:44:16 +0000833 (void) SetImageOption(image_info,option,"undefined");
anthony6dc09cd2011-10-12 08:56:49 +0000834 draw_info->gravity=UndefinedGravity;
anthony805a2d42011-09-25 08:25:12 +0000835 break;
836 }
anthony74b1cfc2011-10-06 12:44:16 +0000837 (void) SetImageOption(image_info,option,argv[1]);
anthony6dc09cd2011-10-12 08:56:49 +0000838 draw_info->gravity=(GravityType) ParseCommandOption(
839 MagickGravityOptions,MagickFalse,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000840 break;
841 }
anthony74b1cfc2011-10-06 12:44:16 +0000842 if (LocaleCompare("green-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000843 {
844 if (*argv[0] == '+')
845 {
anthony74b1cfc2011-10-06 12:44:16 +0000846 (void) SetImageOption(image_info,option,"0.0");
anthony805a2d42011-09-25 08:25:12 +0000847 break;
848 }
anthony74b1cfc2011-10-06 12:44:16 +0000849 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000850 break;
851 }
852 break;
853 }
854 case 'i':
855 {
anthony74b1cfc2011-10-06 12:44:16 +0000856 if (LocaleCompare("intent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000857 {
858 if (*argv[0] == '+')
859 {
anthony74b1cfc2011-10-06 12:44:16 +0000860 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000861 break;
862 }
anthony74b1cfc2011-10-06 12:44:16 +0000863 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000864 break;
865 }
anthony74b1cfc2011-10-06 12:44:16 +0000866 if (LocaleCompare("interlace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000867 {
868 if (*argv[0] == '+')
869 {
870 image_info->interlace=UndefinedInterlace;
anthony74b1cfc2011-10-06 12:44:16 +0000871 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000872 break;
873 }
874 image_info->interlace=(InterlaceType) ParseCommandOption(
875 MagickInterlaceOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +0000876 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000877 break;
878 }
anthony74b1cfc2011-10-06 12:44:16 +0000879 if (LocaleCompare("interline-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000880 {
881 if (*argv[0] == '+')
882 {
anthony74b1cfc2011-10-06 12:44:16 +0000883 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000884 break;
885 }
anthony74b1cfc2011-10-06 12:44:16 +0000886 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000887 break;
888 }
anthony74b1cfc2011-10-06 12:44:16 +0000889 if (LocaleCompare("interpolate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000890 {
891 if (*argv[0] == '+')
892 {
anthony74b1cfc2011-10-06 12:44:16 +0000893 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000894 break;
895 }
anthony74b1cfc2011-10-06 12:44:16 +0000896 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000897 break;
898 }
anthony74b1cfc2011-10-06 12:44:16 +0000899 if (LocaleCompare("interword-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000900 {
901 if (*argv[0] == '+')
902 {
anthony74b1cfc2011-10-06 12:44:16 +0000903 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000904 break;
905 }
anthony74b1cfc2011-10-06 12:44:16 +0000906 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000907 break;
908 }
909 break;
910 }
911 case 'k':
912 {
anthony74b1cfc2011-10-06 12:44:16 +0000913 if (LocaleCompare("kerning",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000914 {
915 if (*argv[0] == '+')
916 {
anthony74b1cfc2011-10-06 12:44:16 +0000917 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +0000918 break;
919 }
anthony74b1cfc2011-10-06 12:44:16 +0000920 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000921 break;
922 }
923 break;
924 }
925 case 'l':
926 {
anthony74b1cfc2011-10-06 12:44:16 +0000927 if (LocaleCompare("label",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000928 {
929 if (*argv[0] == '+')
930 {
anthony74b1cfc2011-10-06 12:44:16 +0000931 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +0000932 break;
933 }
anthony74b1cfc2011-10-06 12:44:16 +0000934 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +0000935 break;
936 }
anthony74b1cfc2011-10-06 12:44:16 +0000937 if (LocaleCompare("limit",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000938 {
939 MagickSizeType
940 limit;
941
942 ResourceType
943 type;
944
945 if (*argv[0] == '+')
946 break;
947 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
948 MagickFalse,argv[1]);
949 limit=MagickResourceInfinity;
950 if (LocaleCompare("unlimited",argv[2]) != 0)
951 limit=(MagickSizeType) SiPrefixToDouble(argv[2],100.0);
952 (void) SetMagickResourceLimit(type,limit);
953 break;
954 }
anthony74b1cfc2011-10-06 12:44:16 +0000955 if (LocaleCompare("list",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000956 {
957 ssize_t
958 list;
959
960 /*
961 Display configuration list.
962 */
963 list=ParseCommandOption(MagickListOptions,MagickFalse,argv[1]);
964 switch (list)
965 {
966 case MagickCoderOptions:
967 {
968 (void) ListCoderInfo((FILE *) NULL,exception);
969 break;
970 }
971 case MagickColorOptions:
972 {
973 (void) ListColorInfo((FILE *) NULL,exception);
974 break;
975 }
976 case MagickConfigureOptions:
977 {
978 (void) ListConfigureInfo((FILE *) NULL,exception);
979 break;
980 }
981 case MagickDelegateOptions:
982 {
983 (void) ListDelegateInfo((FILE *) NULL,exception);
984 break;
985 }
986 case MagickFontOptions:
987 {
988 (void) ListTypeInfo((FILE *) NULL,exception);
989 break;
990 }
991 case MagickFormatOptions:
992 {
993 (void) ListMagickInfo((FILE *) NULL,exception);
994 break;
995 }
996 case MagickLocaleOptions:
997 {
998 (void) ListLocaleInfo((FILE *) NULL,exception);
999 break;
1000 }
1001 case MagickLogOptions:
1002 {
1003 (void) ListLogInfo((FILE *) NULL,exception);
1004 break;
1005 }
1006 case MagickMagicOptions:
1007 {
1008 (void) ListMagicInfo((FILE *) NULL,exception);
1009 break;
1010 }
1011 case MagickMimeOptions:
1012 {
1013 (void) ListMimeInfo((FILE *) NULL,exception);
1014 break;
1015 }
1016 case MagickModuleOptions:
1017 {
1018 (void) ListModuleInfo((FILE *) NULL,exception);
1019 break;
1020 }
1021 case MagickPolicyOptions:
1022 {
1023 (void) ListPolicyInfo((FILE *) NULL,exception);
1024 break;
1025 }
1026 case MagickResourceOptions:
1027 {
1028 (void) ListMagickResourceInfo((FILE *) NULL,exception);
1029 break;
1030 }
1031 case MagickThresholdOptions:
1032 {
1033 (void) ListThresholdMaps((FILE *) NULL,exception);
1034 break;
1035 }
1036 default:
1037 {
1038 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
1039 exception);
1040 break;
1041 }
1042 }
1043 break;
1044 }
anthony74b1cfc2011-10-06 12:44:16 +00001045 if (LocaleCompare("log",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001046 {
1047 if (*argv[0] == '+')
1048 break;
1049 (void) SetLogFormat(argv[1]);
1050 break;
1051 }
anthony74b1cfc2011-10-06 12:44:16 +00001052 if (LocaleCompare("loop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001053 {
1054 if (*argv[0] == '+')
1055 {
anthony74b1cfc2011-10-06 12:44:16 +00001056 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001057 break;
1058 }
anthony74b1cfc2011-10-06 12:44:16 +00001059 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001060 break;
1061 }
1062 break;
1063 }
1064 case 'm':
1065 {
anthony74b1cfc2011-10-06 12:44:16 +00001066 if (LocaleCompare("matte",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001067 {
1068 if (*argv[0] == '+')
1069 {
anthony74b1cfc2011-10-06 12:44:16 +00001070 (void) SetImageOption(image_info,option,"false");
anthony805a2d42011-09-25 08:25:12 +00001071 break;
1072 }
anthony74b1cfc2011-10-06 12:44:16 +00001073 (void) SetImageOption(image_info,option,"true");
anthony805a2d42011-09-25 08:25:12 +00001074 break;
1075 }
anthony74b1cfc2011-10-06 12:44:16 +00001076 if (LocaleCompare("mattecolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001077 {
1078 if (*argv[0] == '+')
1079 {
anthony74b1cfc2011-10-06 12:44:16 +00001080 (void) SetImageOption(image_info,option,argv[1]);
anthony1afdc7a2011-10-05 11:54:28 +00001081 (void) QueryColorCompliance(MatteColor,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00001082 &image_info->matte_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001083 break;
1084 }
anthony74b1cfc2011-10-06 12:44:16 +00001085 (void) SetImageOption(image_info,option,argv[1]);
anthony1afdc7a2011-10-05 11:54:28 +00001086 (void) QueryColorCompliance(argv[1],AllCompliance,&image_info->matte_color,
anthony805a2d42011-09-25 08:25:12 +00001087 exception);
1088 break;
1089 }
anthony74b1cfc2011-10-06 12:44:16 +00001090 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001091 {
1092 (void) SetImageInfoProgressMonitor(image_info,MonitorProgress,
1093 (void *) NULL);
1094 break;
1095 }
anthony74b1cfc2011-10-06 12:44:16 +00001096 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001097 {
1098 image_info->monochrome=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1099 break;
1100 }
1101 break;
1102 }
1103 case 'o':
1104 {
anthony74b1cfc2011-10-06 12:44:16 +00001105 if (LocaleCompare("orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001106 {
1107 if (*argv[0] == '+')
1108 {
1109 image_info->orientation=UndefinedOrientation;
anthony74b1cfc2011-10-06 12:44:16 +00001110 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +00001111 break;
1112 }
1113 image_info->orientation=(OrientationType) ParseCommandOption(
1114 MagickOrientationOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001115 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001116 break;
1117 }
1118 }
1119 case 'p':
1120 {
anthony74b1cfc2011-10-06 12:44:16 +00001121 if (LocaleCompare("page",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001122 {
1123 char
1124 *canonical_page,
1125 page[MaxTextExtent];
1126
1127 const char
1128 *image_option;
1129
1130 MagickStatusType
1131 flags;
1132
1133 RectangleInfo
1134 geometry;
1135
1136 if (*argv[0] == '+')
1137 {
anthony74b1cfc2011-10-06 12:44:16 +00001138 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +00001139 (void) CloneString(&image_info->page,(char *) NULL);
1140 break;
1141 }
1142 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1143 image_option=GetImageOption(image_info,"page");
1144 if (image_option != (const char *) NULL)
1145 flags=ParseAbsoluteGeometry(image_option,&geometry);
1146 canonical_page=GetPageGeometry(argv[1]);
1147 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1148 canonical_page=DestroyString(canonical_page);
1149 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1150 (unsigned long) geometry.width,(unsigned long) geometry.height);
1151 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1152 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1153 (unsigned long) geometry.width,(unsigned long) geometry.height,
1154 (long) geometry.x,(long) geometry.y);
anthony74b1cfc2011-10-06 12:44:16 +00001155 (void) SetImageOption(image_info,option,page);
anthony805a2d42011-09-25 08:25:12 +00001156 (void) CloneString(&image_info->page,page);
1157 break;
1158 }
anthony74b1cfc2011-10-06 12:44:16 +00001159 if (LocaleCompare("pen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001160 {
1161 if (*argv[0] == '+')
1162 {
anthony74b1cfc2011-10-06 12:44:16 +00001163 (void) SetImageOption(image_info,option,"none");
anthony805a2d42011-09-25 08:25:12 +00001164 break;
1165 }
anthony74b1cfc2011-10-06 12:44:16 +00001166 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001167 break;
1168 }
anthony74b1cfc2011-10-06 12:44:16 +00001169 if (LocaleCompare("ping",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001170 {
1171 image_info->ping=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1172 break;
1173 }
anthony74b1cfc2011-10-06 12:44:16 +00001174 if (LocaleCompare("pointsize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001175 {
1176 if (*argv[0] == '+')
1177 geometry_info.rho=0.0;
1178 else
1179 (void) ParseGeometry(argv[1],&geometry_info);
1180 image_info->pointsize=geometry_info.rho;
1181 break;
1182 }
anthony74b1cfc2011-10-06 12:44:16 +00001183 if (LocaleCompare("precision",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001184 {
1185 (void) SetMagickPrecision(StringToInteger(argv[1]));
1186 break;
1187 }
anthony74b1cfc2011-10-06 12:44:16 +00001188 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001189 {
1190 /*
1191 Preview image.
1192 */
1193 if (*argv[0] == '+')
1194 {
1195 image_info->preview_type=UndefinedPreview;
1196 break;
1197 }
1198 image_info->preview_type=(PreviewType) ParseCommandOption(
1199 MagickPreviewOptions,MagickFalse,argv[1]);
1200 break;
1201 }
1202 break;
1203 }
1204 case 'q':
1205 {
anthony74b1cfc2011-10-06 12:44:16 +00001206 if (LocaleCompare("quality",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001207 {
1208 /*
1209 Set image compression quality.
1210 */
1211 if (*argv[0] == '+')
1212 {
1213 image_info->quality=UndefinedCompressionQuality;
anthony74b1cfc2011-10-06 12:44:16 +00001214 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001215 break;
1216 }
1217 image_info->quality=StringToUnsignedLong(argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001218 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001219 break;
1220 }
anthony74b1cfc2011-10-06 12:44:16 +00001221 if (LocaleCompare("quiet",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001222 {
1223 static WarningHandler
1224 warning_handler = (WarningHandler) NULL;
1225
1226 if (*argv[0] == '+')
1227 {
1228 /*
1229 Restore error or warning messages.
1230 */
1231 warning_handler=SetWarningHandler(warning_handler);
1232 break;
1233 }
1234 /*
1235 Suppress error or warning messages.
1236 */
1237 warning_handler=SetWarningHandler((WarningHandler) NULL);
1238 break;
1239 }
1240 break;
1241 }
1242 case 'r':
1243 {
anthony74b1cfc2011-10-06 12:44:16 +00001244 if (LocaleCompare("red-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001245 {
1246 if (*argv[0] == '+')
1247 {
anthony74b1cfc2011-10-06 12:44:16 +00001248 (void) SetImageOption(image_info,option,"0.0");
anthony805a2d42011-09-25 08:25:12 +00001249 break;
1250 }
anthony74b1cfc2011-10-06 12:44:16 +00001251 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001252 break;
1253 }
1254 break;
1255 }
1256 case 's':
1257 {
anthony74b1cfc2011-10-06 12:44:16 +00001258 if (LocaleCompare("sampling-factor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001259 {
1260 /*
1261 Set image sampling factor.
1262 */
1263 if (*argv[0] == '+')
1264 {
1265 if (image_info->sampling_factor != (char *) NULL)
1266 image_info->sampling_factor=DestroyString(
1267 image_info->sampling_factor);
1268 break;
1269 }
1270 (void) CloneString(&image_info->sampling_factor,argv[1]);
1271 break;
1272 }
anthony74b1cfc2011-10-06 12:44:16 +00001273 if (LocaleCompare("scene",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001274 {
1275 /*
1276 Set image scene.
1277 */
1278 if (*argv[0] == '+')
1279 {
1280 image_info->scene=0;
anthony74b1cfc2011-10-06 12:44:16 +00001281 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001282 break;
1283 }
1284 image_info->scene=StringToUnsignedLong(argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001285 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001286 break;
1287 }
anthony74b1cfc2011-10-06 12:44:16 +00001288 if (LocaleCompare("seed",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001289 {
1290 size_t
1291 seed;
1292
1293 if (*argv[0] == '+')
1294 {
1295 seed=(size_t) time((time_t *) NULL);
1296 SeedPseudoRandomGenerator(seed);
1297 break;
1298 }
1299 seed=StringToUnsignedLong(argv[1]);
1300 SeedPseudoRandomGenerator(seed);
1301 break;
1302 }
anthony74b1cfc2011-10-06 12:44:16 +00001303 if (LocaleCompare("size",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001304 {
anthony74b1cfc2011-10-06 12:44:16 +00001305 /* FUTURE: convert to ImageOption
1306 Look at special handling for "size" in SetImageOption()
1307 */
anthony805a2d42011-09-25 08:25:12 +00001308 if (*argv[0] == '+')
1309 {
1310 if (image_info->size != (char *) NULL)
1311 image_info->size=DestroyString(image_info->size);
1312 break;
1313 }
1314 (void) CloneString(&image_info->size,argv[1]);
1315 break;
1316 }
anthony74b1cfc2011-10-06 12:44:16 +00001317 if (LocaleCompare("stroke",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001318 {
1319 if (*argv[0] == '+')
1320 {
anthony74b1cfc2011-10-06 12:44:16 +00001321 (void) SetImageOption(image_info,option,"none");
anthony805a2d42011-09-25 08:25:12 +00001322 break;
1323 }
anthony74b1cfc2011-10-06 12:44:16 +00001324 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001325 break;
1326 }
anthony74b1cfc2011-10-06 12:44:16 +00001327 if (LocaleCompare("strokewidth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001328 {
1329 if (*argv[0] == '+')
1330 {
anthony74b1cfc2011-10-06 12:44:16 +00001331 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001332 break;
1333 }
anthony74b1cfc2011-10-06 12:44:16 +00001334 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001335 break;
1336 }
anthony74b1cfc2011-10-06 12:44:16 +00001337 if (LocaleCompare("synchronize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001338 {
1339 if (*argv[0] == '+')
1340 {
1341 image_info->synchronize=MagickFalse;
1342 break;
1343 }
1344 image_info->synchronize=MagickTrue;
1345 break;
1346 }
1347 break;
1348 }
1349 case 't':
1350 {
anthony74b1cfc2011-10-06 12:44:16 +00001351 if (LocaleCompare("taint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001352 {
1353 if (*argv[0] == '+')
1354 {
anthony74b1cfc2011-10-06 12:44:16 +00001355 (void) SetImageOption(image_info,option,"false");
anthony805a2d42011-09-25 08:25:12 +00001356 break;
1357 }
anthony74b1cfc2011-10-06 12:44:16 +00001358 (void) SetImageOption(image_info,option,"true");
anthony805a2d42011-09-25 08:25:12 +00001359 break;
1360 }
anthony74b1cfc2011-10-06 12:44:16 +00001361 if (LocaleCompare("texture",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001362 {
1363 if (*argv[0] == '+')
1364 {
1365 if (image_info->texture != (char *) NULL)
1366 image_info->texture=DestroyString(image_info->texture);
1367 break;
1368 }
1369 (void) CloneString(&image_info->texture,argv[1]);
1370 break;
1371 }
anthony74b1cfc2011-10-06 12:44:16 +00001372 if (LocaleCompare("tile-offset",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001373 {
1374 if (*argv[0] == '+')
1375 {
anthony74b1cfc2011-10-06 12:44:16 +00001376 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +00001377 break;
1378 }
anthony74b1cfc2011-10-06 12:44:16 +00001379 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001380 break;
1381 }
anthony74b1cfc2011-10-06 12:44:16 +00001382 if (LocaleCompare("transparent-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001383 {
1384 if (*argv[0] == '+')
1385 {
anthony1afdc7a2011-10-05 11:54:28 +00001386 (void) QueryColorCompliance("none",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00001387 &image_info->transparent_color,exception);
anthony74b1cfc2011-10-06 12:44:16 +00001388 (void) SetImageOption(image_info,option,"none");
anthony805a2d42011-09-25 08:25:12 +00001389 break;
1390 }
anthony1afdc7a2011-10-05 11:54:28 +00001391 (void) QueryColorCompliance("none",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00001392 &image_info->transparent_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001393 exception);
anthony74b1cfc2011-10-06 12:44:16 +00001394 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001395 break;
1396 }
anthony74b1cfc2011-10-06 12:44:16 +00001397 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001398 {
1399 if (*argv[0] == '+')
1400 {
1401 image_info->type=UndefinedType;
anthony74b1cfc2011-10-06 12:44:16 +00001402 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +00001403 break;
1404 }
1405 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1406 MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001407 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001408 break;
1409 }
1410 break;
1411 }
1412 case 'u':
1413 {
anthony74b1cfc2011-10-06 12:44:16 +00001414 if (LocaleCompare("undercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001415 {
1416 if (*argv[0] == '+')
1417 {
anthony74b1cfc2011-10-06 12:44:16 +00001418 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +00001419 break;
1420 }
anthony74b1cfc2011-10-06 12:44:16 +00001421 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001422 break;
1423 }
anthony74b1cfc2011-10-06 12:44:16 +00001424 if (LocaleCompare("units",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001425 {
1426 if (*argv[0] == '+')
1427 {
1428 image_info->units=UndefinedResolution;
anthony74b1cfc2011-10-06 12:44:16 +00001429 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +00001430 break;
1431 }
1432 image_info->units=(ResolutionType) ParseCommandOption(
1433 MagickResolutionOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001434 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001435 break;
1436 }
1437 break;
1438 }
1439 case 'v':
1440 {
anthony74b1cfc2011-10-06 12:44:16 +00001441 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001442 {
1443 if (*argv[0] == '+')
1444 {
1445 image_info->verbose=MagickFalse;
1446 break;
1447 }
1448 image_info->verbose=MagickTrue;
1449 image_info->ping=MagickFalse;
1450 break;
1451 }
anthony74b1cfc2011-10-06 12:44:16 +00001452 if (LocaleCompare("view",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001453 {
1454 if (*argv[0] == '+')
1455 {
1456 if (image_info->view != (char *) NULL)
1457 image_info->view=DestroyString(image_info->view);
1458 break;
1459 }
1460 (void) CloneString(&image_info->view,argv[1]);
1461 break;
1462 }
anthony74b1cfc2011-10-06 12:44:16 +00001463 if (LocaleCompare("virtual-pixel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001464 {
1465 if (*argv[0] == '+')
1466 {
1467 image_info->virtual_pixel_method=UndefinedVirtualPixelMethod;
anthony74b1cfc2011-10-06 12:44:16 +00001468 (void) SetImageOption(image_info,option,"undefined");
anthony805a2d42011-09-25 08:25:12 +00001469 break;
1470 }
1471 image_info->virtual_pixel_method=(VirtualPixelMethod)
1472 ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,argv[1]);
anthony74b1cfc2011-10-06 12:44:16 +00001473 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001474 break;
1475 }
1476 break;
1477 }
1478 case 'w':
1479 {
anthony74b1cfc2011-10-06 12:44:16 +00001480 if (LocaleCompare("white-point",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001481 {
1482 if (*argv[0] == '+')
1483 {
anthony74b1cfc2011-10-06 12:44:16 +00001484 (void) SetImageOption(image_info,option,"0.0");
anthony805a2d42011-09-25 08:25:12 +00001485 break;
1486 }
anthony74b1cfc2011-10-06 12:44:16 +00001487 (void) SetImageOption(image_info,option,argv[1]);
anthony805a2d42011-09-25 08:25:12 +00001488 break;
1489 }
1490 break;
1491 }
1492 default:
1493 break;
1494 }
1495 return(MagickTrue);
1496}
1497
1498/*
1499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1500% %
1501% %
1502% %
anthony74b1cfc2011-10-06 12:44:16 +00001503+ A p p l y I m a g e O p e r a t o r %
anthony805a2d42011-09-25 08:25:12 +00001504% %
1505% %
1506% %
1507%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1508%
anthony74b1cfc2011-10-06 12:44:16 +00001509% ApplyImageOperator() apply one simple image operation to just the current
1510% image.
anthony805a2d42011-09-25 08:25:12 +00001511%
1512% The image in the list may be modified in three different ways...
1513%
1514% * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1515% * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1516% * replace by a list of images (-separate and -crop only!)
1517%
1518% In each case the result is returned into the list, and the pointer to the
1519% modified image (last image added if replaced by a list of images) is
1520% returned. As the image pointed to may be replaced, the first image in the
1521% list may also change. GetFirstImageInList() should be used by caller if
1522% they wish return the Image pointer to the first image in list.
1523%
anthony74b1cfc2011-10-06 12:44:16 +00001524% The format of the ApplyImageOperator method is:
anthony805a2d42011-09-25 08:25:12 +00001525%
anthony74b1cfc2011-10-06 12:44:16 +00001526% MagickBooleanType ApplyImageOperator(MagickWand *wand,
1527% const int argc,const char **argv)
anthony805a2d42011-09-25 08:25:12 +00001528%
1529% A description of each parameter follows:
1530%
anthony74b1cfc2011-10-06 12:44:16 +00001531% o wand: The CLI wand holding all the settings and pointer to image
anthony805a2d42011-09-25 08:25:12 +00001532%
1533% o argc: Specifies a pointer to an integer describing the number of
1534% elements in the argument vector.
1535%
1536% o argv: Specifies a pointer to a text array containing the command line
1537% arguments.
1538%
anthony805a2d42011-09-25 08:25:12 +00001539% o exception: return any errors or warnings in this structure.
1540%
1541*/
anthony74b1cfc2011-10-06 12:44:16 +00001542MagickExport MagickBooleanType ApplyImageOperator(MagickWand *wand,
1543 const int wand_unused(argc), const char **argv, ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +00001544{
1545 Image *
1546 new_image;
1547
1548 ChannelType
1549 channel;
1550
anthony5f867ae2011-10-09 10:28:34 +00001551 ComposeOperation
1552 compose;
1553
anthony805a2d42011-09-25 08:25:12 +00001554 const char
1555 *format;
1556
1557 DrawInfo
1558 *draw_info;
1559
1560 GeometryInfo
1561 geometry_info;
1562
1563 RectangleInfo
1564 geometry;
1565
1566 MagickStatusType
1567 status;
1568
1569 PixelInfo
1570 fill;
1571
1572 MagickStatusType
1573 flags;
1574
1575 QuantizeInfo
1576 *quantize_info;
1577
1578 assert(image_info != (const ImageInfo *) NULL);
1579 assert(image_info->signature == MagickSignature);
1580 assert(image != (Image **) NULL);
1581 assert((*image)->signature == MagickSignature);
1582 if ((*image)->debug != MagickFalse)
1583 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
anthonya89dd172011-10-04 13:29:35 +00001584 if (argc < 0)
1585 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00001586 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
1587 quantize_info=AcquireQuantizeInfo(image_info);
1588 SetGeometryInfo(&geometry_info);
1589 GetPixelInfo(*image,&fill);
1590 SetPixelInfoPacket(*image,&(*image)->background_color,&fill);
1591 channel=image_info->channel;
1592 format=GetImageOption(image_info,"format");
1593
1594 new_image = (Image *)NULL;
1595
1596 switch (*(argv[0]+1))
1597 {
1598 case 'a':
1599 {
1600 if (LocaleCompare("adaptive-blur",argv[0]+1) == 0)
1601 {
anthony805a2d42011-09-25 08:25:12 +00001602 (void) SyncImageSettings(image_info,*image);
1603 flags=ParseGeometry(argv[1],&geometry_info);
1604 if ((flags & SigmaValue) == 0)
1605 geometry_info.sigma=1.0;
1606 if ((flags & XiValue) == 0)
1607 geometry_info.xi=0.0;
1608 new_image=AdaptiveBlurImage(*image,geometry_info.rho,
1609 geometry_info.sigma,geometry_info.xi,exception);
1610 break;
1611 }
1612 if (LocaleCompare("adaptive-resize",argv[0]+1) == 0)
1613 {
anthony1afdc7a2011-10-05 11:54:28 +00001614 /* FUTURE: this is really a "interpolate-resize" operator
1615 "adaptive-resize" uses a fixed "Mesh" interpolation
anthony805a2d42011-09-25 08:25:12 +00001616 */
1617 (void) SyncImageSettings(image_info,*image);
1618 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
1619 new_image=AdaptiveResizeImage(*image,geometry.width,
anthonya89dd172011-10-04 13:29:35 +00001620 geometry.height,interpolate_method,exception);
anthony805a2d42011-09-25 08:25:12 +00001621 break;
1622 }
1623 if (LocaleCompare("adaptive-sharpen",argv[0]+1) == 0)
1624 {
1625 /*
1626 Adaptive sharpen image.
1627 */
1628 (void) SyncImageSettings(image_info,*image);
1629 flags=ParseGeometry(argv[1],&geometry_info);
1630 if ((flags & SigmaValue) == 0)
1631 geometry_info.sigma=1.0;
1632 if ((flags & XiValue) == 0)
1633 geometry_info.xi=0.0;
1634 new_image=AdaptiveSharpenImage(*image,geometry_info.rho,
1635 geometry_info.sigma,geometry_info.xi,exception);
1636 break;
1637 }
anthony805a2d42011-09-25 08:25:12 +00001638 if (LocaleCompare("alpha",argv[0]+1) == 0)
1639 {
1640 AlphaChannelType
1641 alpha_type;
1642
1643 (void) SyncImageSettings(image_info,*image);
1644 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
1645 MagickFalse,argv[1]);
1646 (void) SetImageAlphaChannel(*image,alpha_type,exception);
1647 break;
1648 }
1649 if (LocaleCompare("annotate",argv[0]+1) == 0)
1650 {
1651 char
1652 *text,
1653 geometry[MaxTextExtent];
1654
anthony805a2d42011-09-25 08:25:12 +00001655 (void) SyncImageSettings(image_info,*image);
1656 SetGeometryInfo(&geometry_info);
1657 flags=ParseGeometry(argv[1],&geometry_info);
1658 if ((flags & SigmaValue) == 0)
1659 geometry_info.sigma=geometry_info.rho;
1660 text=InterpretImageProperties(image_info,*image,argv[2],
1661 exception);
1662 if (text == (char *) NULL)
1663 break;
1664 (void) CloneString(&draw_info->text,text);
1665 text=DestroyString(text);
1666 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1667 geometry_info.xi,geometry_info.psi);
1668 (void) CloneString(&draw_info->geometry,geometry);
1669 draw_info->affine.sx=cos(DegreesToRadians(
1670 fmod(geometry_info.rho,360.0)));
1671 draw_info->affine.rx=sin(DegreesToRadians(
1672 fmod(geometry_info.rho,360.0)));
1673 draw_info->affine.ry=(-sin(DegreesToRadians(
1674 fmod(geometry_info.sigma,360.0))));
1675 draw_info->affine.sy=cos(DegreesToRadians(
1676 fmod(geometry_info.sigma,360.0)));
1677 (void) AnnotateImage(*image,draw_info,exception);
1678 break;
1679 }
anthony805a2d42011-09-25 08:25:12 +00001680 if (LocaleCompare("auto-gamma",argv[0]+1) == 0)
1681 {
1682 /*
1683 Auto Adjust Gamma of image based on its mean
1684 */
1685 (void) SyncImageSettings(image_info,*image);
1686 (void) AutoGammaImage(*image,exception);
1687 break;
1688 }
1689 if (LocaleCompare("auto-level",argv[0]+1) == 0)
1690 {
1691 /*
1692 Perfectly Normalize (max/min stretch) the image
1693 */
1694 (void) SyncImageSettings(image_info,*image);
1695 (void) AutoLevelImage(*image,exception);
1696 break;
1697 }
1698 if (LocaleCompare("auto-orient",argv[0]+1) == 0)
1699 {
1700 (void) SyncImageSettings(image_info,*image);
1701 switch ((*image)->orientation)
1702 {
1703 case TopRightOrientation:
1704 {
1705 new_image=FlopImage(*image,exception);
1706 break;
1707 }
1708 case BottomRightOrientation:
1709 {
1710 new_image=RotateImage(*image,180.0,exception);
1711 break;
1712 }
1713 case BottomLeftOrientation:
1714 {
1715 new_image=FlipImage(*image,exception);
1716 break;
1717 }
1718 case LeftTopOrientation:
1719 {
1720 new_image=TransposeImage(*image,exception);
1721 break;
1722 }
1723 case RightTopOrientation:
1724 {
1725 new_image=RotateImage(*image,90.0,exception);
1726 break;
1727 }
1728 case RightBottomOrientation:
1729 {
1730 new_image=TransverseImage(*image,exception);
1731 break;
1732 }
1733 case LeftBottomOrientation:
1734 {
1735 new_image=RotateImage(*image,270.0,exception);
1736 break;
1737 }
1738 default:
1739 break;
1740 }
1741 if (new_image != (Image *) NULL)
1742 new_image->orientation=TopLeftOrientation;
1743 break;
1744 }
1745 break;
1746 }
1747 case 'b':
1748 {
1749 if (LocaleCompare("black-threshold",argv[0]+1) == 0)
1750 {
anthony805a2d42011-09-25 08:25:12 +00001751 (void) SyncImageSettings(image_info,*image);
1752 (void) BlackThresholdImage(*image,argv[1],exception);
1753 InheritException(exception,&(*image)->exception);
1754 break;
1755 }
1756 if (LocaleCompare("blue-shift",argv[0]+1) == 0)
1757 {
anthony805a2d42011-09-25 08:25:12 +00001758 (void) SyncImageSettings(image_info,*image);
1759 geometry_info.rho=1.5;
1760 if (*argv[0] == '-')
1761 flags=ParseGeometry(argv[1],&geometry_info);
1762 new_image=BlueShiftImage(*image,geometry_info.rho,exception);
1763 break;
1764 }
1765 if (LocaleCompare("blur",argv[0]+1) == 0)
1766 {
anthony74b1cfc2011-10-06 12:44:16 +00001767 /* FUTURE: use of "bias" in a blur is non-sensible */
anthony805a2d42011-09-25 08:25:12 +00001768 (void) SyncImageSettings(image_info,*image);
1769 flags=ParseGeometry(argv[1],&geometry_info);
1770 if ((flags & SigmaValue) == 0)
1771 geometry_info.sigma=1.0;
1772 if ((flags & XiValue) == 0)
1773 geometry_info.xi=0.0;
1774 new_image=BlurImage(*image,geometry_info.rho,
1775 geometry_info.sigma,geometry_info.xi,exception);
1776 break;
1777 }
1778 if (LocaleCompare("border",argv[0]+1) == 0)
1779 {
anthony5f867ae2011-10-09 10:28:34 +00001780 ComposeOperator
1781 compose;
1782
1783 const char*
1784 const char*
1785 value;
1786
1787 value=GetImageOption(image_info,"compose");
1788 if (value != (const char *) NULL)
1789 compose=(CompositeOperator) ParseCommandOption(
1790 MagickComposeOptions,MagickFalse,value);
1791 else
1792 compose=OverCompositeOp; /* use Over not image->compose */
1793
anthony805a2d42011-09-25 08:25:12 +00001794 (void) SyncImageSettings(image_info,*image);
1795 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
1796 if ((flags & SigmaValue) == 0)
1797 geometry.height=geometry.width;
anthonya89dd172011-10-04 13:29:35 +00001798 new_image=BorderImage(*image,&geometry,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00001799 break;
1800 }
anthony805a2d42011-09-25 08:25:12 +00001801 if (LocaleCompare("brightness-contrast",argv[0]+1) == 0)
1802 {
1803 double
1804 brightness,
1805 contrast;
1806
1807 GeometryInfo
1808 geometry_info;
1809
1810 MagickStatusType
1811 flags;
1812
anthony805a2d42011-09-25 08:25:12 +00001813 (void) SyncImageSettings(image_info,*image);
1814 flags=ParseGeometry(argv[1],&geometry_info);
1815 brightness=geometry_info.rho;
1816 contrast=0.0;
1817 if ((flags & SigmaValue) != 0)
1818 contrast=geometry_info.sigma;
1819 (void) BrightnessContrastImage(*image,brightness,contrast,
1820 exception);
1821 InheritException(exception,&(*image)->exception);
1822 break;
1823 }
1824 break;
1825 }
1826 case 'c':
1827 {
1828 if (LocaleCompare("cdl",argv[0]+1) == 0)
1829 {
1830 char
1831 *color_correction_collection;
1832
1833 /*
1834 Color correct with a color decision list.
1835 */
1836 (void) SyncImageSettings(image_info,*image);
1837 color_correction_collection=FileToString(argv[1],~0,exception);
1838 if (color_correction_collection == (char *) NULL)
1839 break;
1840 (void) ColorDecisionListImage(*image,color_correction_collection,
1841 exception);
1842 InheritException(exception,&(*image)->exception);
1843 break;
1844 }
1845 if (LocaleCompare("channel",argv[0]+1) == 0)
1846 {
anthony74b1cfc2011-10-06 12:44:16 +00001847 /* The "channel" setting has already been set */
1848 SetPixelChannelMap(*image,image_info->channel);
anthony805a2d42011-09-25 08:25:12 +00001849 break;
1850 }
1851 if (LocaleCompare("charcoal",argv[0]+1) == 0)
1852 {
anthony805a2d42011-09-25 08:25:12 +00001853 (void) SyncImageSettings(image_info,*image);
1854 flags=ParseGeometry(argv[1],&geometry_info);
1855 if ((flags & SigmaValue) == 0)
1856 geometry_info.sigma=1.0;
1857 if ((flags & XiValue) == 0)
1858 geometry_info.xi=1.0;
1859 new_image=CharcoalImage(*image,geometry_info.rho,
1860 geometry_info.sigma,geometry_info.xi,exception);
1861 break;
1862 }
1863 if (LocaleCompare("chop",argv[0]+1) == 0)
1864 {
anthony805a2d42011-09-25 08:25:12 +00001865 (void) SyncImageSettings(image_info,*image);
1866 (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
1867 new_image=ChopImage(*image,&geometry,exception);
1868 break;
1869 }
1870 if (LocaleCompare("clamp",argv[0]+1) == 0)
1871 {
anthony805a2d42011-09-25 08:25:12 +00001872 (void) SyncImageSettings(image_info,*image);
1873 (void) ClampImage(*image);
1874 InheritException(exception,&(*image)->exception);
1875 break;
1876 }
1877 if (LocaleCompare("clip",argv[0]+1) == 0)
1878 {
1879 (void) SyncImageSettings(image_info,*image);
1880 if (*argv[0] == '+')
1881 {
1882 (void) SetImageClipMask(*image,(Image *) NULL,exception);
1883 break;
1884 }
1885 (void) ClipImage(*image,exception);
1886 break;
1887 }
1888 if (LocaleCompare("clip-mask",argv[0]+1) == 0)
1889 {
1890 CacheView
1891 *mask_view;
1892
1893 Image
1894 *mask_image;
1895
1896 register Quantum
1897 *restrict q;
1898
1899 register ssize_t
1900 x;
1901
1902 ssize_t
1903 y;
1904
1905 (void) SyncImageSettings(image_info,*image);
1906 if (*argv[0] == '+')
1907 {
anthony74b1cfc2011-10-06 12:44:16 +00001908 /* Remove the write mask */
anthony805a2d42011-09-25 08:25:12 +00001909 (void) SetImageMask(*image,(Image *) NULL,exception);
1910 break;
1911 }
1912 mask_image=GetImageCache(image_info,argv[1],exception);
1913 if (mask_image == (Image *) NULL)
1914 break;
1915 if (SetImageStorageClass(mask_image,DirectClass,exception) == MagickFalse)
1916 return(MagickFalse);
anthony74b1cfc2011-10-06 12:44:16 +00001917 /* create a write mask from clip-mask image */
1918 /* FUTURE: use Alpha operations instead */
anthony805a2d42011-09-25 08:25:12 +00001919 mask_view=AcquireCacheView(mask_image);
1920 for (y=0; y < (ssize_t) mask_image->rows; y++)
1921 {
1922 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1923 exception);
1924 if (q == (Quantum *) NULL)
1925 break;
1926 for (x=0; x < (ssize_t) mask_image->columns; x++)
1927 {
1928 if (mask_image->matte == MagickFalse)
1929 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1930 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1931 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1932 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1933 q+=GetPixelChannels(mask_image);
1934 }
1935 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1936 break;
1937 }
anthony74b1cfc2011-10-06 12:44:16 +00001938 /* set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001939 mask_view=DestroyCacheView(mask_view);
1940 mask_image->matte=MagickTrue;
anthonya89dd172011-10-04 13:29:35 +00001941 (void) SetImageClipMask(*image,mask_image,exception);
anthony805a2d42011-09-25 08:25:12 +00001942 mask_image=DestroyImage(mask_image);
1943 InheritException(exception,&(*image)->exception);
1944 break;
1945 }
1946 if (LocaleCompare("clip-path",argv[0]+1) == 0)
1947 {
1948 (void) SyncImageSettings(image_info,*image);
1949 (void) ClipImagePath(*image,argv[1],*argv[0] == '-' ? MagickTrue :
1950 MagickFalse,exception);
1951 break;
1952 }
1953 if (LocaleCompare("colorize",argv[0]+1) == 0)
1954 {
anthony805a2d42011-09-25 08:25:12 +00001955 (void) SyncImageSettings(image_info,*image);
1956 new_image=ColorizeImage(*image,argv[1],draw_info->fill,
1957 exception);
1958 break;
1959 }
1960 if (LocaleCompare("color-matrix",argv[0]+1) == 0)
1961 {
1962 KernelInfo
1963 *kernel;
1964
1965 (void) SyncImageSettings(image_info,*image);
1966 kernel=AcquireKernelInfo(argv[1]);
1967 if (kernel == (KernelInfo *) NULL)
1968 break;
1969 new_image=ColorMatrixImage(*image,kernel,exception);
1970 kernel=DestroyKernelInfo(kernel);
1971 break;
1972 }
1973 if (LocaleCompare("colors",argv[0]+1) == 0)
1974 {
anthony74b1cfc2011-10-06 12:44:16 +00001975 /* Reduce the number of colors in the image. */
anthony805a2d42011-09-25 08:25:12 +00001976 (void) SyncImageSettings(image_info,*image);
1977 quantize_info->number_colors=StringToUnsignedLong(argv[1]);
1978 if (quantize_info->number_colors == 0)
1979 break;
1980 if (((*image)->storage_class == DirectClass) ||
1981 (*image)->colors > quantize_info->number_colors)
1982 (void) QuantizeImage(quantize_info,*image,exception);
1983 else
1984 (void) CompressImageColormap(*image,exception);
1985 break;
1986 }
1987 if (LocaleCompare("colorspace",argv[0]+1) == 0)
1988 {
anthonyd2cdc862011-10-07 14:07:17 +00001989 /* This is a Image Setting, which should already been set */
1990 /* FUTURE: default colorspace should be sRGB!
1991 Unless some type of 'linear colorspace' mode is set.
1992 Note that +colorspace sets "undefined" or no effect on
1993 new images, but forces images already in memory back to RGB!
1994 */
anthony805a2d42011-09-25 08:25:12 +00001995 (void) SyncImageSettings(image_info,*image);
anthonyd2cdc862011-10-07 14:07:17 +00001996 (void) TransformImageColorspace(*image,
1997 IfSetOption ? image_info->colorspace : RGBColorspace);
anthony805a2d42011-09-25 08:25:12 +00001998 InheritException(exception,&(*image)->exception);
1999 break;
2000 }
2001 if (LocaleCompare("contrast",argv[0]+1) == 0)
2002 {
2003 (void) SyncImageSettings(image_info,*image);
2004 (void) ContrastImage(*image,(*argv[0] == '-') ? MagickTrue :
2005 MagickFalse,exception);
2006 break;
2007 }
2008 if (LocaleCompare("contrast-stretch",argv[0]+1) == 0)
2009 {
2010 double
2011 black_point,
2012 white_point;
2013
2014 MagickStatusType
2015 flags;
2016
2017 /*
2018 Contrast stretch image.
2019 */
2020 (void) SyncImageSettings(image_info,*image);
2021 flags=ParseGeometry(argv[1],&geometry_info);
2022 black_point=geometry_info.rho;
2023 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2024 black_point;
2025 if ((flags & PercentValue) != 0)
2026 {
2027 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2028 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2029 }
2030 white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2031 white_point;
2032 (void) ContrastStretchImage(*image,black_point,white_point,
2033 exception);
2034 InheritException(exception,&(*image)->exception);
2035 break;
2036 }
2037 if (LocaleCompare("convolve",argv[0]+1) == 0)
2038 {
2039 KernelInfo
2040 *kernel_info;
2041
2042 (void) SyncImageSettings(image_info,*image);
2043 kernel_info=AcquireKernelInfo(argv[1]);
2044 if (kernel_info == (KernelInfo *) NULL)
2045 break;
2046 kernel_info->bias=(*image)->bias;
2047 new_image=ConvolveImage(*image,kernel_info,exception);
2048 kernel_info=DestroyKernelInfo(kernel_info);
2049 break;
2050 }
2051 if (LocaleCompare("crop",argv[0]+1) == 0)
2052 {
2053 /*
2054 Crop a image to a smaller size
2055 */
2056 (void) SyncImageSettings(image_info,*image);
2057 new_image=CropImageToTiles(*image,argv[1],exception);
2058 break;
2059 }
2060 if (LocaleCompare("cycle",argv[0]+1) == 0)
2061 {
2062 /*
2063 Cycle an image colormap.
2064 */
2065 (void) SyncImageSettings(image_info,*image);
2066 (void) CycleColormapImage(*image,(ssize_t) StringToLong(argv[1]),
2067 exception);
2068 break;
2069 }
2070 break;
2071 }
2072 case 'd':
2073 {
2074 if (LocaleCompare("decipher",argv[0]+1) == 0)
2075 {
2076 StringInfo
2077 *passkey;
2078
2079 /*
2080 Decipher pixels.
2081 */
2082 (void) SyncImageSettings(image_info,*image);
2083 passkey=FileToStringInfo(argv[1],~0,exception);
2084 if (passkey != (StringInfo *) NULL)
2085 {
2086 (void) PasskeyDecipherImage(*image,passkey,exception);
2087 passkey=DestroyStringInfo(passkey);
2088 }
2089 break;
2090 }
anthony805a2d42011-09-25 08:25:12 +00002091 if (LocaleCompare("depth",argv[0]+1) == 0)
2092 {
anthony5f867ae2011-10-09 10:28:34 +00002093 /* the image_info->depth setting has already bee set
2094 * We just need to apply it to all images in current sequence */
anthony805a2d42011-09-25 08:25:12 +00002095 (void) SyncImageSettings(image_info,*image);
anthony5f867ae2011-10-09 10:28:34 +00002096 (void) SetImageDepth(*image,image_info->depth);
anthony805a2d42011-09-25 08:25:12 +00002097 break;
2098 }
2099 if (LocaleCompare("deskew",argv[0]+1) == 0)
2100 {
2101 double
2102 threshold;
2103
2104 /*
2105 Straighten the image.
2106 */
2107 (void) SyncImageSettings(image_info,*image);
2108 if (*argv[0] == '+')
2109 threshold=40.0*QuantumRange/100.0;
2110 else
2111 threshold=SiPrefixToDouble(argv[1],QuantumRange);
2112 new_image=DeskewImage(*image,threshold,exception);
2113 break;
2114 }
2115 if (LocaleCompare("despeckle",argv[0]+1) == 0)
2116 {
2117 /*
2118 Reduce the speckles within an image.
2119 */
2120 (void) SyncImageSettings(image_info,*image);
2121 new_image=DespeckleImage(*image,exception);
2122 break;
2123 }
2124 if (LocaleCompare("display",argv[0]+1) == 0)
2125 {
2126 (void) CloneString(&draw_info->server_name,argv[1]);
2127 break;
2128 }
2129 if (LocaleCompare("distort",argv[0]+1) == 0)
2130 {
2131 char
2132 *args,
2133 token[MaxTextExtent];
2134
2135 const char
2136 *p;
2137
2138 DistortImageMethod
2139 method;
2140
2141 double
2142 *arguments;
2143
2144 register ssize_t
2145 x;
2146
2147 size_t
2148 number_arguments;
2149
2150 /*
2151 Distort image.
2152 */
2153 (void) SyncImageSettings(image_info,*image);
2154 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
2155 MagickFalse,argv[1]);
2156 if ( method == ResizeDistortion )
2157 {
2158 /* Special Case - Argument is actually a resize geometry!
2159 ** Convert that to an appropriate distortion argument array.
2160 */
2161 double
2162 resize_args[2];
2163 (void) ParseRegionGeometry(*image,argv[2],&geometry,
2164 exception);
2165 resize_args[0]=(double)geometry.width;
2166 resize_args[1]=(double)geometry.height;
2167 new_image=DistortImage(*image,method,(size_t)2,
2168 resize_args,MagickTrue,exception);
2169 break;
2170 }
2171 args=InterpretImageProperties(image_info,*image,argv[2],
2172 exception);
2173 if (args == (char *) NULL)
2174 break;
2175 p=(char *) args;
2176 for (x=0; *p != '\0'; x++)
2177 {
2178 GetMagickToken(p,&p,token);
2179 if (*token == ',')
2180 GetMagickToken(p,&p,token);
2181 }
2182 number_arguments=(size_t) x;
2183 arguments=(double *) AcquireQuantumMemory(number_arguments,
2184 sizeof(*arguments));
2185 if (arguments == (double *) NULL)
2186 ThrowWandFatalException(ResourceLimitFatalError,
2187 "MemoryAllocationFailed",(*image)->filename);
2188 (void) ResetMagickMemory(arguments,0,number_arguments*
2189 sizeof(*arguments));
2190 p=(char *) args;
2191 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2192 {
2193 GetMagickToken(p,&p,token);
2194 if (*token == ',')
2195 GetMagickToken(p,&p,token);
2196 arguments[x]=InterpretLocaleValue(token,(char **) NULL);
2197 }
2198 args=DestroyString(args);
2199 new_image=DistortImage(*image,method,number_arguments,arguments,
2200 (*argv[0] == '+') ? MagickTrue : MagickFalse,exception);
2201 arguments=(double *) RelinquishMagickMemory(arguments);
2202 break;
2203 }
anthony805a2d42011-09-25 08:25:12 +00002204 if (LocaleCompare("draw",argv[0]+1) == 0)
2205 {
anthony805a2d42011-09-25 08:25:12 +00002206 (void) SyncImageSettings(image_info,*image);
2207 (void) CloneString(&draw_info->primitive,argv[1]);
2208 (void) DrawImage(*image,draw_info,exception);
2209 break;
2210 }
2211 break;
2212 }
2213 case 'e':
2214 {
2215 if (LocaleCompare("edge",argv[0]+1) == 0)
2216 {
anthony805a2d42011-09-25 08:25:12 +00002217 (void) SyncImageSettings(image_info,*image);
2218 flags=ParseGeometry(argv[1],&geometry_info);
2219 if ((flags & SigmaValue) == 0)
2220 geometry_info.sigma=1.0;
2221 new_image=EdgeImage(*image,geometry_info.rho,
2222 geometry_info.sigma,exception);
2223 break;
2224 }
2225 if (LocaleCompare("emboss",argv[0]+1) == 0)
2226 {
anthony805a2d42011-09-25 08:25:12 +00002227 (void) SyncImageSettings(image_info,*image);
2228 flags=ParseGeometry(argv[1],&geometry_info);
2229 if ((flags & SigmaValue) == 0)
2230 geometry_info.sigma=1.0;
2231 new_image=EmbossImage(*image,geometry_info.rho,
2232 geometry_info.sigma,exception);
2233 break;
2234 }
2235 if (LocaleCompare("encipher",argv[0]+1) == 0)
2236 {
2237 StringInfo
2238 *passkey;
2239
anthony805a2d42011-09-25 08:25:12 +00002240 (void) SyncImageSettings(image_info,*image);
2241 passkey=FileToStringInfo(argv[1],~0,exception);
2242 if (passkey != (StringInfo *) NULL)
2243 {
2244 (void) PasskeyEncipherImage(*image,passkey,exception);
2245 passkey=DestroyStringInfo(passkey);
2246 }
2247 break;
2248 }
anthony805a2d42011-09-25 08:25:12 +00002249 if (LocaleCompare("enhance",argv[0]+1) == 0)
2250 {
anthony805a2d42011-09-25 08:25:12 +00002251 (void) SyncImageSettings(image_info,*image);
2252 new_image=EnhanceImage(*image,exception);
2253 break;
2254 }
2255 if (LocaleCompare("equalize",argv[0]+1) == 0)
2256 {
anthony805a2d42011-09-25 08:25:12 +00002257 (void) SyncImageSettings(image_info,*image);
2258 (void) EqualizeImage(*image,exception);
2259 break;
2260 }
2261 if (LocaleCompare("evaluate",argv[0]+1) == 0)
2262 {
2263 double
2264 constant;
2265
2266 MagickEvaluateOperator
2267 op;
2268
2269 (void) SyncImageSettings(image_info,*image);
2270 op=(MagickEvaluateOperator) ParseCommandOption(
2271 MagickEvaluateOptions,MagickFalse,argv[1]);
2272 constant=SiPrefixToDouble(argv[2],QuantumRange);
2273 (void) EvaluateImage(*image,op,constant,exception);
2274 break;
2275 }
2276 if (LocaleCompare("extent",argv[0]+1) == 0)
2277 {
anthony805a2d42011-09-25 08:25:12 +00002278 (void) SyncImageSettings(image_info,*image);
2279 flags=ParseGravityGeometry(*image,argv[1],&geometry,exception);
2280 if (geometry.width == 0)
2281 geometry.width=(*image)->columns;
2282 if (geometry.height == 0)
2283 geometry.height=(*image)->rows;
2284 new_image=ExtentImage(*image,&geometry,exception);
2285 break;
2286 }
2287 break;
2288 }
2289 case 'f':
2290 {
anthony805a2d42011-09-25 08:25:12 +00002291 if (LocaleCompare("features",argv[0]+1) == 0)
2292 {
anthony6dc09cd2011-10-12 08:56:49 +00002293 /* FUTURE: Assign Artifact all images */
2294 (void) SetImageArtifact(*image,"identify:features",
2295 IfSetOption ? argv[1] : (const char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002296 break;
2297 }
2298 if (LocaleCompare("flip",argv[0]+1) == 0)
2299 {
2300 /*
2301 Flip image scanlines.
2302 */
2303 (void) SyncImageSettings(image_info,*image);
2304 new_image=FlipImage(*image,exception);
2305 break;
2306 }
2307 if (LocaleCompare("flop",argv[0]+1) == 0)
2308 {
2309 /*
2310 Flop image scanlines.
2311 */
2312 (void) SyncImageSettings(image_info,*image);
2313 new_image=FlopImage(*image,exception);
2314 break;
2315 }
2316 if (LocaleCompare("floodfill",argv[0]+1) == 0)
2317 {
2318 PixelInfo
2319 target;
2320
2321 /*
2322 Floodfill image.
2323 */
2324 (void) SyncImageSettings(image_info,*image);
2325 (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
anthonya89dd172011-10-04 13:29:35 +00002326 (void) QueryMagickColorCompliance(argv[2],AllCompliance,&target,
2327 exception);
anthony805a2d42011-09-25 08:25:12 +00002328 (void) FloodfillPaintImage(*image,draw_info,&target,geometry.x,
2329 geometry.y,*argv[0] == '-' ? MagickFalse : MagickTrue,exception);
2330 break;
2331 }
anthony6dc09cd2011-10-12 08:56:49 +00002332 /* FUTURE: should be from ImageOption "format"
anthony805a2d42011-09-25 08:25:12 +00002333 if (LocaleCompare("format",argv[0]+1) == 0)
2334 {
2335 format=argv[1];
2336 break;
2337 }
anthony6dc09cd2011-10-12 08:56:49 +00002338 */
anthony805a2d42011-09-25 08:25:12 +00002339 if (LocaleCompare("frame",argv[0]+1) == 0)
2340 {
2341 FrameInfo
2342 frame_info;
2343
2344 /*
2345 Surround image with an ornamental border.
2346 */
2347 (void) SyncImageSettings(image_info,*image);
2348 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
2349 frame_info.width=geometry.width;
2350 frame_info.height=geometry.height;
2351 if ((flags & HeightValue) == 0)
2352 frame_info.height=geometry.width;
2353 frame_info.outer_bevel=geometry.x;
2354 frame_info.inner_bevel=geometry.y;
2355 frame_info.x=(ssize_t) frame_info.width;
2356 frame_info.y=(ssize_t) frame_info.height;
2357 frame_info.width=(*image)->columns+2*frame_info.width;
2358 frame_info.height=(*image)->rows+2*frame_info.height;
anthony5f867ae2011-10-09 10:28:34 +00002359 new_image=FrameImage(*image,&frame_info,COMPOSE,exception);
anthony805a2d42011-09-25 08:25:12 +00002360 break;
2361 }
2362 if (LocaleCompare("function",argv[0]+1) == 0)
2363 {
2364 char
2365 *arguments,
2366 token[MaxTextExtent];
2367
2368 const char
2369 *p;
2370
2371 double
2372 *parameters;
2373
2374 MagickFunction
2375 function;
2376
2377 register ssize_t
2378 x;
2379
2380 size_t
2381 number_parameters;
2382
2383 /*
2384 Function Modify Image Values
2385 */
2386 (void) SyncImageSettings(image_info,*image);
2387 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
2388 MagickFalse,argv[1]);
2389 arguments=InterpretImageProperties(image_info,*image,argv[2],
2390 exception);
2391 if (arguments == (char *) NULL)
2392 break;
2393 p=(char *) arguments;
2394 for (x=0; *p != '\0'; x++)
2395 {
2396 GetMagickToken(p,&p,token);
2397 if (*token == ',')
2398 GetMagickToken(p,&p,token);
2399 }
2400 number_parameters=(size_t) x;
2401 parameters=(double *) AcquireQuantumMemory(number_parameters,
2402 sizeof(*parameters));
2403 if (parameters == (double *) NULL)
2404 ThrowWandFatalException(ResourceLimitFatalError,
2405 "MemoryAllocationFailed",(*image)->filename);
2406 (void) ResetMagickMemory(parameters,0,number_parameters*
2407 sizeof(*parameters));
2408 p=(char *) arguments;
2409 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2410 {
2411 GetMagickToken(p,&p,token);
2412 if (*token == ',')
2413 GetMagickToken(p,&p,token);
2414 parameters[x]=InterpretLocaleValue(token,(char **) NULL);
2415 }
2416 arguments=DestroyString(arguments);
2417 (void) FunctionImage(*image,function,number_parameters,parameters,
2418 exception);
2419 parameters=(double *) RelinquishMagickMemory(parameters);
2420 break;
2421 }
2422 break;
2423 }
2424 case 'g':
2425 {
2426 if (LocaleCompare("gamma",argv[0]+1) == 0)
2427 {
2428 /*
2429 Gamma image.
2430 */
2431 (void) SyncImageSettings(image_info,*image);
2432 if (*argv[0] == '+')
2433 (*image)->gamma=InterpretLocaleValue(argv[1],(char **) NULL);
2434 else
2435 (void) GammaImage(*image,InterpretLocaleValue(argv[1],
2436 (char **) NULL),exception);
2437 break;
2438 }
2439 if ((LocaleCompare("gaussian-blur",argv[0]+1) == 0) ||
2440 (LocaleCompare("gaussian",argv[0]+1) == 0))
2441 {
2442 /*
2443 Gaussian blur image.
2444 */
2445 (void) SyncImageSettings(image_info,*image);
2446 flags=ParseGeometry(argv[1],&geometry_info);
2447 if ((flags & SigmaValue) == 0)
2448 geometry_info.sigma=1.0;
2449 if ((flags & XiValue) == 0)
2450 geometry_info.xi=0.0;
2451 new_image=GaussianBlurImage(*image,geometry_info.rho,
2452 geometry_info.sigma,geometry_info.xi,exception);
2453 break;
2454 }
2455 if (LocaleCompare("geometry",argv[0]+1) == 0)
2456 {
2457 /*
2458 Record Image offset, Resize last image.
2459 */
2460 (void) SyncImageSettings(image_info,*image);
2461 if (*argv[0] == '+')
2462 {
2463 if ((*image)->geometry != (char *) NULL)
2464 (*image)->geometry=DestroyString((*image)->geometry);
2465 break;
2466 }
2467 flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2468 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2469 (void) CloneString(&(*image)->geometry,argv[1]);
2470 else
2471 new_image=ResizeImage(*image,geometry.width,geometry.height,
2472 (*image)->filter,(*image)->blur,exception);
2473 break;
2474 }
anthony805a2d42011-09-25 08:25:12 +00002475 break;
2476 }
2477 case 'h':
2478 {
2479 if (LocaleCompare("highlight-color",argv[0]+1) == 0)
2480 {
2481 (void) SetImageArtifact(*image,argv[0]+1,argv[1]);
2482 break;
2483 }
2484 break;
2485 }
2486 case 'i':
2487 {
2488 if (LocaleCompare("identify",argv[0]+1) == 0)
2489 {
2490 char
2491 *text;
2492
2493 (void) SyncImageSettings(image_info,*image);
2494 if (format == (char *) NULL)
2495 {
2496 (void) IdentifyImage(*image,stdout,image_info->verbose,
2497 exception);
2498 break;
2499 }
2500 text=InterpretImageProperties(image_info,*image,format,
2501 exception);
2502 if (text == (char *) NULL)
2503 break;
2504 (void) fputs(text,stdout);
2505 (void) fputc('\n',stdout);
2506 text=DestroyString(text);
2507 break;
2508 }
2509 if (LocaleCompare("implode",argv[0]+1) == 0)
2510 {
2511 /*
2512 Implode image.
2513 */
2514 (void) SyncImageSettings(image_info,*image);
2515 (void) ParseGeometry(argv[1],&geometry_info);
anthonya89dd172011-10-04 13:29:35 +00002516 new_image=ImplodeImage(*image,geometry_info.rho,
2517 interpolate_method,exception);
anthony805a2d42011-09-25 08:25:12 +00002518 break;
2519 }
2520 if (LocaleCompare("interline-spacing",argv[0]+1) == 0)
2521 {
2522 if (*argv[0] == '+')
2523 (void) ParseGeometry("0",&geometry_info);
2524 else
2525 (void) ParseGeometry(argv[1],&geometry_info);
2526 draw_info->interline_spacing=geometry_info.rho;
2527 break;
2528 }
anthonya89dd172011-10-04 13:29:35 +00002529 if (LocaleCompare("interpolate",argv[0]+1) == 0)
2530 {
2531 interpolate_method=(PixelInterpolateMethod) ParseCommandOption(
2532 MagickInterpolateOptions,MagickFalse,argv[1]);
2533 break;
2534 }
anthony805a2d42011-09-25 08:25:12 +00002535 if (LocaleCompare("interword-spacing",argv[0]+1) == 0)
2536 {
2537 if (*argv[0] == '+')
2538 (void) ParseGeometry("0",&geometry_info);
2539 else
2540 (void) ParseGeometry(argv[1],&geometry_info);
2541 draw_info->interword_spacing=geometry_info.rho;
2542 break;
2543 }
2544 break;
2545 }
2546 case 'k':
2547 {
2548 if (LocaleCompare("kerning",argv[0]+1) == 0)
2549 {
2550 if (*argv[0] == '+')
2551 (void) ParseGeometry("0",&geometry_info);
2552 else
2553 (void) ParseGeometry(argv[1],&geometry_info);
2554 draw_info->kerning=geometry_info.rho;
2555 break;
2556 }
2557 break;
2558 }
2559 case 'l':
2560 {
2561 if (LocaleCompare("lat",argv[0]+1) == 0)
2562 {
2563 /*
2564 Local adaptive threshold image.
2565 */
2566 (void) SyncImageSettings(image_info,*image);
2567 flags=ParseGeometry(argv[1],&geometry_info);
2568 if ((flags & PercentValue) != 0)
2569 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2570 new_image=AdaptiveThresholdImage(*image,(size_t)
2571 geometry_info.rho,(size_t) geometry_info.sigma,(double)
2572 geometry_info.xi,exception);
2573 break;
2574 }
2575 if (LocaleCompare("level",argv[0]+1) == 0)
2576 {
2577 MagickRealType
2578 black_point,
2579 gamma,
2580 white_point;
2581
2582 MagickStatusType
2583 flags;
2584
2585 /*
2586 Parse levels.
2587 */
2588 (void) SyncImageSettings(image_info,*image);
2589 flags=ParseGeometry(argv[1],&geometry_info);
2590 black_point=geometry_info.rho;
2591 white_point=(MagickRealType) QuantumRange;
2592 if ((flags & SigmaValue) != 0)
2593 white_point=geometry_info.sigma;
2594 gamma=1.0;
2595 if ((flags & XiValue) != 0)
2596 gamma=geometry_info.xi;
2597 if ((flags & PercentValue) != 0)
2598 {
2599 black_point*=(MagickRealType) (QuantumRange/100.0);
2600 white_point*=(MagickRealType) (QuantumRange/100.0);
2601 }
2602 if ((flags & SigmaValue) == 0)
2603 white_point=(MagickRealType) QuantumRange-black_point;
2604 if ((*argv[0] == '+') || ((flags & AspectValue) != 0))
2605 (void) LevelizeImage(*image,black_point,white_point,gamma,
2606 exception);
2607 else
2608 (void) LevelImage(*image,black_point,white_point,gamma,
2609 exception);
2610 InheritException(exception,&(*image)->exception);
2611 break;
2612 }
2613 if (LocaleCompare("level-colors",argv[0]+1) == 0)
2614 {
2615 char
2616 token[MaxTextExtent];
2617
2618 const char
2619 *p;
2620
2621 PixelInfo
2622 black_point,
2623 white_point;
2624
2625 p=(const char *) argv[1];
2626 GetMagickToken(p,&p,token); /* get black point color */
2627 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
anthonya89dd172011-10-04 13:29:35 +00002628 (void) QueryMagickColorCompliance(token,AllCompliance,
2629 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002630 else
anthonya89dd172011-10-04 13:29:35 +00002631 (void) QueryMagickColorCompliance("#000000",AllCompliance,
2632 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002633 if (isalpha((int) token[0]) || (token[0] == '#'))
2634 GetMagickToken(p,&p,token);
2635 if (*token == '\0')
2636 white_point=black_point; /* set everything to that color */
2637 else
2638 {
2639 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2640 GetMagickToken(p,&p,token); /* Get white point color. */
2641 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
anthonya89dd172011-10-04 13:29:35 +00002642 (void) QueryMagickColorCompliance(token,AllCompliance,
2643 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002644 else
anthonya89dd172011-10-04 13:29:35 +00002645 (void) QueryMagickColorCompliance("#ffffff",AllCompliance,
2646 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002647 }
2648 (void) LevelImageColors(*image,&black_point,&white_point,
2649 *argv[0] == '+' ? MagickTrue : MagickFalse,exception);
2650 break;
2651 }
2652 if (LocaleCompare("linear-stretch",argv[0]+1) == 0)
2653 {
2654 double
2655 black_point,
2656 white_point;
2657
2658 MagickStatusType
2659 flags;
2660
2661 (void) SyncImageSettings(image_info,*image);
2662 flags=ParseGeometry(argv[1],&geometry_info);
2663 black_point=geometry_info.rho;
2664 white_point=(MagickRealType) (*image)->columns*(*image)->rows;
2665 if ((flags & SigmaValue) != 0)
2666 white_point=geometry_info.sigma;
2667 if ((flags & PercentValue) != 0)
2668 {
2669 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2670 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2671 }
2672 if ((flags & SigmaValue) == 0)
2673 white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2674 black_point;
2675 (void) LinearStretchImage(*image,black_point,white_point,exception);
2676 InheritException(exception,&(*image)->exception);
2677 break;
2678 }
2679 if (LocaleCompare("linewidth",argv[0]+1) == 0)
2680 {
2681 draw_info->stroke_width=InterpretLocaleValue(argv[1],
2682 (char **) NULL);
2683 break;
2684 }
2685 if (LocaleCompare("liquid-rescale",argv[0]+1) == 0)
2686 {
2687 /*
2688 Liquid rescale image.
2689 */
2690 (void) SyncImageSettings(image_info,*image);
2691 flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2692 if ((flags & XValue) == 0)
2693 geometry.x=1;
2694 if ((flags & YValue) == 0)
2695 geometry.y=0;
2696 new_image=LiquidRescaleImage(*image,geometry.width,
2697 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2698 break;
2699 }
2700 if (LocaleCompare("lowlight-color",argv[0]+1) == 0)
2701 {
2702 (void) SetImageArtifact(*image,argv[0]+1,argv[1]);
2703 break;
2704 }
2705 break;
2706 }
2707 case 'm':
2708 {
2709 if (LocaleCompare("map",argv[0]+1) == 0)
2710 {
2711 Image
2712 *remap_image;
2713
2714 /*
2715 Transform image colors to match this set of colors.
2716 */
2717 (void) SyncImageSettings(image_info,*image);
2718 if (*argv[0] == '+')
2719 break;
2720 remap_image=GetImageCache(image_info,argv[1],exception);
2721 if (remap_image == (Image *) NULL)
2722 break;
2723 (void) RemapImage(quantize_info,*image,remap_image,exception);
2724 remap_image=DestroyImage(remap_image);
2725 break;
2726 }
2727 if (LocaleCompare("mask",argv[0]+1) == 0)
2728 {
2729 Image
2730 *mask;
2731
2732 (void) SyncImageSettings(image_info,*image);
2733 if (*argv[0] == '+')
2734 {
2735 /*
2736 Remove a mask.
2737 */
2738 (void) SetImageMask(*image,(Image *) NULL,exception);
2739 break;
2740 }
2741 /*
2742 Set the image mask.
2743 */
2744 mask=GetImageCache(image_info,argv[1],exception);
2745 if (mask == (Image *) NULL)
2746 break;
2747 (void) SetImageMask(*image,mask,exception);
2748 mask=DestroyImage(mask);
2749 break;
2750 }
2751 if (LocaleCompare("matte",argv[0]+1) == 0)
2752 {
2753 (void) SetImageAlphaChannel(*image,(*argv[0] == '-') ?
2754 SetAlphaChannel : DeactivateAlphaChannel,exception);
2755 break;
2756 }
2757 if (LocaleCompare("median",argv[0]+1) == 0)
2758 {
2759 /*
2760 Median filter image.
2761 */
2762 (void) SyncImageSettings(image_info,*image);
2763 flags=ParseGeometry(argv[1],&geometry_info);
2764 if ((flags & SigmaValue) == 0)
2765 geometry_info.sigma=geometry_info.rho;
2766 new_image=StatisticImage(*image,MedianStatistic,(size_t)
2767 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2768 break;
2769 }
2770 if (LocaleCompare("mode",argv[0]+1) == 0)
2771 {
2772 /*
2773 Mode image.
2774 */
2775 (void) SyncImageSettings(image_info,*image);
2776 flags=ParseGeometry(argv[1],&geometry_info);
2777 if ((flags & SigmaValue) == 0)
2778 geometry_info.sigma=geometry_info.rho;
2779 new_image=StatisticImage(*image,ModeStatistic,(size_t)
2780 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2781 break;
2782 }
2783 if (LocaleCompare("modulate",argv[0]+1) == 0)
2784 {
2785 (void) SyncImageSettings(image_info,*image);
2786 (void) ModulateImage(*image,argv[1],exception);
2787 break;
2788 }
2789 if (LocaleCompare("monitor",argv[0]+1) == 0)
2790 {
2791 if (*argv[0] == '+')
2792 {
2793 (void) SetImageProgressMonitor(*image,
2794 (MagickProgressMonitor) NULL,(void *) NULL);
2795 break;
2796 }
2797 (void) SetImageProgressMonitor(*image,MonitorProgress,
2798 (void *) NULL);
2799 break;
2800 }
2801 if (LocaleCompare("monochrome",argv[0]+1) == 0)
2802 {
2803 (void) SyncImageSettings(image_info,*image);
2804 (void) SetImageType(*image,BilevelType,exception);
2805 break;
2806 }
2807 if (LocaleCompare("morphology",argv[0]+1) == 0)
2808 {
2809 char
2810 token[MaxTextExtent];
2811
2812 const char
2813 *p;
2814
2815 KernelInfo
2816 *kernel;
2817
2818 MorphologyMethod
2819 method;
2820
2821 ssize_t
2822 iterations;
2823
2824 /*
2825 Morphological Image Operation
2826 */
2827 (void) SyncImageSettings(image_info,*image);
2828 p=argv[1];
2829 GetMagickToken(p,&p,token);
2830 method=(MorphologyMethod) ParseCommandOption(
2831 MagickMorphologyOptions,MagickFalse,token);
2832 iterations=1L;
2833 GetMagickToken(p,&p,token);
2834 if ((*p == ':') || (*p == ','))
2835 GetMagickToken(p,&p,token);
2836 if ((*p != '\0'))
2837 iterations=(ssize_t) StringToLong(p);
2838 kernel=AcquireKernelInfo(argv[2]);
2839 if (kernel == (KernelInfo *) NULL)
2840 {
2841 (void) ThrowMagickException(exception,GetMagickModule(),
2842 OptionError,"UnabletoParseKernel","morphology");
2843 status=MagickFalse;
2844 break;
2845 }
2846 new_image=MorphologyImage(*image,method,iterations,kernel,
2847 exception);
2848 kernel=DestroyKernelInfo(kernel);
2849 break;
2850 }
2851 if (LocaleCompare("motion-blur",argv[0]+1) == 0)
2852 {
2853 /*
2854 Motion blur image.
2855 */
2856 (void) SyncImageSettings(image_info,*image);
2857 flags=ParseGeometry(argv[1],&geometry_info);
2858 if ((flags & SigmaValue) == 0)
2859 geometry_info.sigma=1.0;
2860 new_image=MotionBlurImage(*image,geometry_info.rho,
2861 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2862 exception);
2863 break;
2864 }
2865 break;
2866 }
2867 case 'n':
2868 {
2869 if (LocaleCompare("negate",argv[0]+1) == 0)
2870 {
2871 (void) SyncImageSettings(image_info,*image);
2872 (void) NegateImage(*image,*argv[0] == '+' ? MagickTrue :
2873 MagickFalse,exception);
2874 break;
2875 }
2876 if (LocaleCompare("noise",argv[0]+1) == 0)
2877 {
2878 (void) SyncImageSettings(image_info,*image);
2879 if (*argv[0] == '-')
2880 {
2881 flags=ParseGeometry(argv[1],&geometry_info);
2882 if ((flags & SigmaValue) == 0)
2883 geometry_info.sigma=geometry_info.rho;
2884 new_image=StatisticImage(*image,NonpeakStatistic,(size_t)
2885 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2886 }
2887 else
2888 {
2889 NoiseType
2890 noise;
2891
2892 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
2893 MagickFalse,argv[1]);
anthony5f867ae2011-10-09 10:28:34 +00002894 new_image=AddNoiseImage(*image,noise,exception);
anthony805a2d42011-09-25 08:25:12 +00002895 }
2896 break;
2897 }
2898 if (LocaleCompare("normalize",argv[0]+1) == 0)
2899 {
2900 (void) SyncImageSettings(image_info,*image);
2901 (void) NormalizeImage(*image,exception);
2902 break;
2903 }
2904 break;
2905 }
2906 case 'o':
2907 {
2908 if (LocaleCompare("opaque",argv[0]+1) == 0)
2909 {
2910 PixelInfo
2911 target;
2912
2913 (void) SyncImageSettings(image_info,*image);
anthonya89dd172011-10-04 13:29:35 +00002914 (void) QueryMagickColorCompliance(argv[1],AllCompliance,&target,
2915 exception);
anthony805a2d42011-09-25 08:25:12 +00002916 (void) OpaquePaintImage(*image,&target,&fill,*argv[0] == '-' ?
2917 MagickFalse : MagickTrue,exception);
2918 break;
2919 }
2920 if (LocaleCompare("ordered-dither",argv[0]+1) == 0)
2921 {
2922 (void) SyncImageSettings(image_info,*image);
2923 (void) OrderedPosterizeImage(*image,argv[1],exception);
2924 break;
2925 }
2926 break;
2927 }
2928 case 'p':
2929 {
2930 if (LocaleCompare("paint",argv[0]+1) == 0)
2931 {
2932 (void) SyncImageSettings(image_info,*image);
2933 (void) ParseGeometry(argv[1],&geometry_info);
2934 new_image=OilPaintImage(*image,geometry_info.rho,
2935 geometry_info.sigma,exception);
2936 break;
2937 }
2938 if (LocaleCompare("pen",argv[0]+1) == 0)
2939 {
2940 if (*argv[0] == '+')
2941 {
anthony1afdc7a2011-10-05 11:54:28 +00002942 (void) QueryColorCompliance("none",AllCompliance,&draw_info->fill,
anthonya89dd172011-10-04 13:29:35 +00002943 exception);
anthony805a2d42011-09-25 08:25:12 +00002944 break;
2945 }
anthony1afdc7a2011-10-05 11:54:28 +00002946 (void) QueryColorCompliance(argv[1],AllCompliance,&draw_info->fill,
anthonya89dd172011-10-04 13:29:35 +00002947 exception);
anthony805a2d42011-09-25 08:25:12 +00002948 break;
2949 }
2950 if (LocaleCompare("pointsize",argv[0]+1) == 0)
2951 {
2952 if (*argv[0] == '+')
2953 (void) ParseGeometry("12",&geometry_info);
2954 else
2955 (void) ParseGeometry(argv[1],&geometry_info);
2956 draw_info->pointsize=geometry_info.rho;
2957 break;
2958 }
2959 if (LocaleCompare("polaroid",argv[0]+1) == 0)
2960 {
2961 double
2962 angle;
2963
2964 RandomInfo
2965 *random_info;
2966
2967 /*
2968 Simulate a Polaroid picture.
2969 */
2970 (void) SyncImageSettings(image_info,*image);
2971 random_info=AcquireRandomInfo();
2972 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2973 random_info=DestroyRandomInfo(random_info);
2974 if (*argv[0] == '-')
2975 {
2976 SetGeometryInfo(&geometry_info);
2977 flags=ParseGeometry(argv[1],&geometry_info);
2978 angle=geometry_info.rho;
2979 }
2980 new_image=PolaroidImage(*image,draw_info,angle,
2981 interpolate_method,exception);
2982 break;
2983 }
2984 if (LocaleCompare("posterize",argv[0]+1) == 0)
2985 {
2986 /*
2987 Posterize image.
2988 */
2989 (void) SyncImageSettings(image_info,*image);
2990 (void) PosterizeImage(*image,StringToUnsignedLong(argv[1]),
2991 quantize_info->dither,exception);
2992 break;
2993 }
2994 if (LocaleCompare("preview",argv[0]+1) == 0)
2995 {
2996 PreviewType
2997 preview_type;
2998
2999 /*
3000 Preview image.
3001 */
3002 (void) SyncImageSettings(image_info,*image);
3003 if (*argv[0] == '+')
3004 preview_type=UndefinedPreview;
3005 else
3006 preview_type=(PreviewType) ParseCommandOption(
3007 MagickPreviewOptions,MagickFalse,argv[1]);
3008 new_image=PreviewImage(*image,preview_type,exception);
3009 break;
3010 }
3011 if (LocaleCompare("profile",argv[0]+1) == 0)
3012 {
3013 const char
3014 *name;
3015
3016 const StringInfo
3017 *profile;
3018
3019 Image
3020 *profile_image;
3021
3022 ImageInfo
3023 *profile_info;
3024
3025 (void) SyncImageSettings(image_info,*image);
3026 if (*argv[0] == '+')
3027 {
3028 /*
3029 Remove a profile from the image.
3030 */
3031 (void) ProfileImage(*image,argv[1],(const unsigned char *)
3032 NULL,0,MagickTrue);
3033 InheritException(exception,&(*image)->exception);
3034 break;
3035 }
3036 /*
3037 Associate a profile with the image.
3038 */
3039 profile_info=CloneImageInfo(image_info);
3040 profile=GetImageProfile(*image,"iptc");
3041 if (profile != (StringInfo *) NULL)
3042 profile_info->profile=(void *) CloneStringInfo(profile);
3043 profile_image=GetImageCache(profile_info,argv[1],exception);
3044 profile_info=DestroyImageInfo(profile_info);
3045 if (profile_image == (Image *) NULL)
3046 {
3047 StringInfo
3048 *profile;
3049
3050 profile_info=CloneImageInfo(image_info);
3051 (void) CopyMagickString(profile_info->filename,argv[1],
3052 MaxTextExtent);
3053 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
3054 if (profile != (StringInfo *) NULL)
3055 {
3056 (void) ProfileImage(*image,profile_info->magick,
3057 GetStringInfoDatum(profile),(size_t)
3058 GetStringInfoLength(profile),MagickFalse);
3059 profile=DestroyStringInfo(profile);
3060 }
3061 profile_info=DestroyImageInfo(profile_info);
3062 break;
3063 }
3064 ResetImageProfileIterator(profile_image);
3065 name=GetNextImageProfile(profile_image);
3066 while (name != (const char *) NULL)
3067 {
3068 profile=GetImageProfile(profile_image,name);
3069 if (profile != (StringInfo *) NULL)
3070 (void) ProfileImage(*image,name,GetStringInfoDatum(profile),
3071 (size_t) GetStringInfoLength(profile),MagickFalse);
3072 name=GetNextImageProfile(profile_image);
3073 }
3074 profile_image=DestroyImage(profile_image);
3075 break;
3076 }
3077 break;
3078 }
3079 case 'q':
3080 {
3081 if (LocaleCompare("quantize",argv[0]+1) == 0)
3082 {
3083 if (*argv[0] == '+')
3084 {
3085 quantize_info->colorspace=UndefinedColorspace;
3086 break;
3087 }
3088 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
3089 MagickColorspaceOptions,MagickFalse,argv[1]);
3090 break;
3091 }
3092 break;
3093 }
3094 case 'r':
3095 {
3096 if (LocaleCompare("radial-blur",argv[0]+1) == 0)
3097 {
3098 /*
3099 Radial blur image.
3100 */
3101 (void) SyncImageSettings(image_info,*image);
3102 flags=ParseGeometry(argv[1],&geometry_info);
3103 new_image=RadialBlurImage(*image,geometry_info.rho,
3104 geometry_info.sigma,exception);
3105 break;
3106 }
3107 if (LocaleCompare("raise",argv[0]+1) == 0)
3108 {
3109 /*
3110 Surround image with a raise of solid color.
3111 */
3112 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3113 if ((flags & SigmaValue) == 0)
3114 geometry.height=geometry.width;
3115 (void) RaiseImage(*image,&geometry,*argv[0] == '-' ? MagickTrue :
3116 MagickFalse,exception);
3117 break;
3118 }
3119 if (LocaleCompare("random-threshold",argv[0]+1) == 0)
3120 {
3121 /*
3122 Threshold image.
3123 */
3124 (void) SyncImageSettings(image_info,*image);
3125 (void) RandomThresholdImage(*image,argv[1],exception);
3126 break;
3127 }
3128 if (LocaleCompare("recolor",argv[0]+1) == 0)
3129 {
3130 KernelInfo
3131 *kernel;
3132
3133 (void) SyncImageSettings(image_info,*image);
3134 kernel=AcquireKernelInfo(argv[1]);
3135 if (kernel == (KernelInfo *) NULL)
3136 break;
3137 new_image=ColorMatrixImage(*image,kernel,exception);
3138 kernel=DestroyKernelInfo(kernel);
3139 break;
3140 }
3141 if (LocaleCompare("render",argv[0]+1) == 0)
3142 {
3143 (void) SyncImageSettings(image_info,*image);
3144 draw_info->render=(*argv[0] == '+') ? MagickTrue : MagickFalse;
3145 break;
3146 }
3147 if (LocaleCompare("remap",argv[0]+1) == 0)
3148 {
3149 Image
3150 *remap_image;
3151
3152 /*
3153 Transform image colors to match this set of colors.
3154 */
3155 (void) SyncImageSettings(image_info,*image);
3156 if (*argv[0] == '+')
3157 break;
3158 remap_image=GetImageCache(image_info,argv[1],exception);
3159 if (remap_image == (Image *) NULL)
3160 break;
3161 (void) RemapImage(quantize_info,*image,remap_image,exception);
3162 remap_image=DestroyImage(remap_image);
3163 break;
3164 }
3165 if (LocaleCompare("repage",argv[0]+1) == 0)
3166 {
3167 if (*argv[0] == '+')
3168 {
3169 (void) ParseAbsoluteGeometry("0x0+0+0",&(*image)->page);
3170 break;
3171 }
3172 (void) ResetImagePage(*image,argv[1]);
3173 InheritException(exception,&(*image)->exception);
3174 break;
3175 }
3176 if (LocaleCompare("resample",argv[0]+1) == 0)
3177 {
3178 /*
3179 Resample image.
3180 */
3181 (void) SyncImageSettings(image_info,*image);
3182 flags=ParseGeometry(argv[1],&geometry_info);
3183 if ((flags & SigmaValue) == 0)
3184 geometry_info.sigma=geometry_info.rho;
3185 new_image=ResampleImage(*image,geometry_info.rho,
3186 geometry_info.sigma,(*image)->filter,(*image)->blur,exception);
3187 break;
3188 }
3189 if (LocaleCompare("resize",argv[0]+1) == 0)
3190 {
3191 /*
3192 Resize image.
3193 */
3194 (void) SyncImageSettings(image_info,*image);
3195 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3196 new_image=ResizeImage(*image,geometry.width,geometry.height,
3197 (*image)->filter,(*image)->blur,exception);
3198 break;
3199 }
3200 if (LocaleCompare("roll",argv[0]+1) == 0)
3201 {
3202 /*
3203 Roll image.
3204 */
3205 (void) SyncImageSettings(image_info,*image);
3206 (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
3207 new_image=RollImage(*image,geometry.x,geometry.y,exception);
3208 break;
3209 }
3210 if (LocaleCompare("rotate",argv[0]+1) == 0)
3211 {
3212 char
3213 *geometry;
3214
3215 /*
3216 Check for conditional image rotation.
3217 */
3218 (void) SyncImageSettings(image_info,*image);
3219 if (strchr(argv[1],'>') != (char *) NULL)
3220 if ((*image)->columns <= (*image)->rows)
3221 break;
3222 if (strchr(argv[1],'<') != (char *) NULL)
3223 if ((*image)->columns >= (*image)->rows)
3224 break;
3225 /*
3226 Rotate image.
3227 */
3228 geometry=ConstantString(argv[1]);
3229 (void) SubstituteString(&geometry,">","");
3230 (void) SubstituteString(&geometry,"<","");
3231 (void) ParseGeometry(geometry,&geometry_info);
3232 geometry=DestroyString(geometry);
3233 new_image=RotateImage(*image,geometry_info.rho,exception);
3234 break;
3235 }
3236 break;
3237 }
3238 case 's':
3239 {
3240 if (LocaleCompare("sample",argv[0]+1) == 0)
3241 {
3242 /*
3243 Sample image with pixel replication.
3244 */
3245 (void) SyncImageSettings(image_info,*image);
3246 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3247 new_image=SampleImage(*image,geometry.width,geometry.height,
3248 exception);
3249 break;
3250 }
3251 if (LocaleCompare("scale",argv[0]+1) == 0)
3252 {
3253 /*
3254 Resize image.
3255 */
3256 (void) SyncImageSettings(image_info,*image);
3257 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3258 new_image=ScaleImage(*image,geometry.width,geometry.height,
3259 exception);
3260 break;
3261 }
3262 if (LocaleCompare("selective-blur",argv[0]+1) == 0)
3263 {
3264 /*
3265 Selectively blur pixels within a contrast threshold.
3266 */
3267 (void) SyncImageSettings(image_info,*image);
3268 flags=ParseGeometry(argv[1],&geometry_info);
3269 if ((flags & PercentValue) != 0)
3270 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3271 new_image=SelectiveBlurImage(*image,geometry_info.rho,
3272 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3273 break;
3274 }
3275 if (LocaleCompare("separate",argv[0]+1) == 0)
3276 {
3277 /*
3278 Break channels into separate images.
3279 WARNING: This can generate multiple images!
3280 */
3281 (void) SyncImageSettings(image_info,*image);
3282 new_image=SeparateImages(*image,exception);
3283 break;
3284 }
3285 if (LocaleCompare("sepia-tone",argv[0]+1) == 0)
3286 {
3287 double
3288 threshold;
3289
3290 /*
3291 Sepia-tone image.
3292 */
3293 (void) SyncImageSettings(image_info,*image);
3294 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3295 new_image=SepiaToneImage(*image,threshold,exception);
3296 break;
3297 }
3298 if (LocaleCompare("segment",argv[0]+1) == 0)
3299 {
3300 /*
3301 Segment image.
3302 */
3303 (void) SyncImageSettings(image_info,*image);
3304 flags=ParseGeometry(argv[1],&geometry_info);
3305 if ((flags & SigmaValue) == 0)
3306 geometry_info.sigma=1.0;
3307 (void) SegmentImage(*image,(*image)->colorspace,
3308 image_info->verbose,geometry_info.rho,geometry_info.sigma,
3309 exception);
3310 break;
3311 }
3312 if (LocaleCompare("set",argv[0]+1) == 0)
3313 {
3314 char
3315 *value;
3316
anthony805a2d42011-09-25 08:25:12 +00003317 if (*argv[0] == '+')
3318 {
3319 if (LocaleNCompare(argv[1],"registry:",9) == 0)
3320 (void) DeleteImageRegistry(argv[1]+9);
3321 else
3322 if (LocaleNCompare(argv[1],"argv[0]:",7) == 0)
3323 {
3324 (void) DeleteImageOption(image_info,argv[1]+7);
3325 (void) DeleteImageArtifact(*image,argv[1]+7);
3326 }
3327 else
3328 (void) DeleteImageProperty(*image,argv[1]);
3329 break;
3330 }
3331 value=InterpretImageProperties(image_info,*image,argv[2],
3332 exception);
3333 if (value == (char *) NULL)
3334 break;
3335 if (LocaleNCompare(argv[1],"registry:",9) == 0)
3336 (void) SetImageRegistry(StringRegistryType,argv[1]+9,value,
3337 exception);
3338 else
anthonya89dd172011-10-04 13:29:35 +00003339 if (LocaleNCompare(argv[1],"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003340 {
3341 (void) SetImageOption(image_info,argv[1]+7,value);
anthony805a2d42011-09-25 08:25:12 +00003342 (void) SetImageArtifact(*image,argv[1]+7,value);
3343 }
3344 else
3345 (void) SetImageProperty(*image,argv[1],value);
3346 value=DestroyString(value);
3347 break;
3348 }
3349 if (LocaleCompare("shade",argv[0]+1) == 0)
3350 {
3351 /*
3352 Shade image.
3353 */
3354 (void) SyncImageSettings(image_info,*image);
3355 flags=ParseGeometry(argv[1],&geometry_info);
3356 if ((flags & SigmaValue) == 0)
3357 geometry_info.sigma=1.0;
3358 new_image=ShadeImage(*image,(*argv[0] == '-') ? MagickTrue :
3359 MagickFalse,geometry_info.rho,geometry_info.sigma,exception);
3360 break;
3361 }
3362 if (LocaleCompare("shadow",argv[0]+1) == 0)
3363 {
3364 /*
3365 Shadow image.
3366 */
3367 (void) SyncImageSettings(image_info,*image);
3368 flags=ParseGeometry(argv[1],&geometry_info);
3369 if ((flags & SigmaValue) == 0)
3370 geometry_info.sigma=1.0;
3371 if ((flags & XiValue) == 0)
3372 geometry_info.xi=4.0;
3373 if ((flags & PsiValue) == 0)
3374 geometry_info.psi=4.0;
3375 new_image=ShadowImage(*image,geometry_info.rho,
3376 geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3377 ceil(geometry_info.psi-0.5),exception);
3378 break;
3379 }
3380 if (LocaleCompare("sharpen",argv[0]+1) == 0)
3381 {
3382 /*
3383 Sharpen image.
3384 */
3385 (void) SyncImageSettings(image_info,*image);
3386 flags=ParseGeometry(argv[1],&geometry_info);
3387 if ((flags & SigmaValue) == 0)
3388 geometry_info.sigma=1.0;
3389 if ((flags & XiValue) == 0)
3390 geometry_info.xi=0.0;
3391 new_image=SharpenImage(*image,geometry_info.rho,
3392 geometry_info.sigma,geometry_info.xi,exception);
3393 break;
3394 }
3395 if (LocaleCompare("shave",argv[0]+1) == 0)
3396 {
3397 /*
3398 Shave the image edges.
3399 */
3400 (void) SyncImageSettings(image_info,*image);
3401 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3402 new_image=ShaveImage(*image,&geometry,exception);
3403 break;
3404 }
3405 if (LocaleCompare("shear",argv[0]+1) == 0)
3406 {
3407 /*
3408 Shear image.
3409 */
3410 (void) SyncImageSettings(image_info,*image);
3411 flags=ParseGeometry(argv[1],&geometry_info);
3412 if ((flags & SigmaValue) == 0)
3413 geometry_info.sigma=geometry_info.rho;
3414 new_image=ShearImage(*image,geometry_info.rho,
3415 geometry_info.sigma,exception);
3416 break;
3417 }
3418 if (LocaleCompare("sigmoidal-contrast",argv[0]+1) == 0)
3419 {
3420 /*
3421 Sigmoidal non-linearity contrast control.
3422 */
3423 (void) SyncImageSettings(image_info,*image);
3424 flags=ParseGeometry(argv[1],&geometry_info);
3425 if ((flags & SigmaValue) == 0)
3426 geometry_info.sigma=(double) QuantumRange/2.0;
3427 if ((flags & PercentValue) != 0)
3428 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3429 100.0;
3430 (void) SigmoidalContrastImage(*image,(*argv[0] == '-') ?
3431 MagickTrue : MagickFalse,geometry_info.rho,geometry_info.sigma,
3432 exception);
3433 break;
3434 }
3435 if (LocaleCompare("sketch",argv[0]+1) == 0)
3436 {
3437 /*
3438 Sketch image.
3439 */
3440 (void) SyncImageSettings(image_info,*image);
3441 flags=ParseGeometry(argv[1],&geometry_info);
3442 if ((flags & SigmaValue) == 0)
3443 geometry_info.sigma=1.0;
3444 new_image=SketchImage(*image,geometry_info.rho,
3445 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3446 break;
3447 }
3448 if (LocaleCompare("solarize",argv[0]+1) == 0)
3449 {
3450 double
3451 threshold;
3452
3453 (void) SyncImageSettings(image_info,*image);
3454 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3455 (void) SolarizeImage(*image,threshold,exception);
3456 break;
3457 }
3458 if (LocaleCompare("sparse-color",argv[0]+1) == 0)
3459 {
3460 SparseColorMethod
3461 method;
3462
3463 char
3464 *arguments;
3465
3466 /*
3467 Sparse Color Interpolated Gradient
3468 */
3469 (void) SyncImageSettings(image_info,*image);
3470 method=(SparseColorMethod) ParseCommandOption(
3471 MagickSparseColorOptions,MagickFalse,argv[1]);
3472 arguments=InterpretImageProperties(image_info,*image,argv[2],
3473 exception);
3474 if (arguments == (char *) NULL)
3475 break;
3476 new_image=SparseColorOption(*image,method,arguments,
3477 argv[0][0] == '+' ? MagickTrue : MagickFalse,exception);
3478 arguments=DestroyString(arguments);
3479 break;
3480 }
3481 if (LocaleCompare("splice",argv[0]+1) == 0)
3482 {
3483 /*
3484 Splice a solid color into the image.
3485 */
3486 (void) SyncImageSettings(image_info,*image);
3487 (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
3488 new_image=SpliceImage(*image,&geometry,exception);
3489 break;
3490 }
3491 if (LocaleCompare("spread",argv[0]+1) == 0)
3492 {
3493 /*
3494 Spread an image.
3495 */
3496 (void) SyncImageSettings(image_info,*image);
3497 (void) ParseGeometry(argv[1],&geometry_info);
3498 new_image=SpreadImage(*image,geometry_info.rho,
3499 interpolate_method,exception);
3500 break;
3501 }
3502 if (LocaleCompare("statistic",argv[0]+1) == 0)
3503 {
3504 StatisticType
3505 type;
3506
3507 (void) SyncImageSettings(image_info,*image);
3508 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
3509 MagickFalse,argv[1]);
3510 (void) ParseGeometry(argv[2],&geometry_info);
3511 new_image=StatisticImage(*image,type,(size_t) geometry_info.rho,
3512 (size_t) geometry_info.sigma,exception);
3513 break;
3514 }
3515 if (LocaleCompare("stretch",argv[0]+1) == 0)
3516 {
3517 if (*argv[0] == '+')
3518 {
3519 draw_info->stretch=UndefinedStretch;
3520 break;
3521 }
3522 draw_info->stretch=(StretchType) ParseCommandOption(
3523 MagickStretchOptions,MagickFalse,argv[1]);
3524 break;
3525 }
3526 if (LocaleCompare("strip",argv[0]+1) == 0)
3527 {
3528 /*
3529 Strip image of profiles and comments.
3530 */
3531 (void) SyncImageSettings(image_info,*image);
3532 (void) StripImage(*image);
3533 InheritException(exception,&(*image)->exception);
3534 break;
3535 }
3536 if (LocaleCompare("stroke",argv[0]+1) == 0)
3537 {
3538 ExceptionInfo
3539 *sans;
3540
3541 if (*argv[0] == '+')
3542 {
anthony1afdc7a2011-10-05 11:54:28 +00003543 (void) QueryColorCompliance("none",AllCompliance,&draw_info->stroke,
anthonya89dd172011-10-04 13:29:35 +00003544 exception);
anthony805a2d42011-09-25 08:25:12 +00003545 if (draw_info->stroke_pattern != (Image *) NULL)
3546 draw_info->stroke_pattern=DestroyImage(
3547 draw_info->stroke_pattern);
3548 break;
3549 }
3550 sans=AcquireExceptionInfo();
anthony1afdc7a2011-10-05 11:54:28 +00003551 status=QueryColorCompliance(argv[1],AllCompliance,&draw_info->stroke,sans);
anthony805a2d42011-09-25 08:25:12 +00003552 sans=DestroyExceptionInfo(sans);
3553 if (status == MagickFalse)
3554 draw_info->stroke_pattern=GetImageCache(image_info,argv[1],
3555 exception);
3556 break;
3557 }
3558 if (LocaleCompare("strokewidth",argv[0]+1) == 0)
3559 {
3560 draw_info->stroke_width=InterpretLocaleValue(argv[1],
3561 (char **) NULL);
3562 break;
3563 }
3564 if (LocaleCompare("style",argv[0]+1) == 0)
3565 {
3566 if (*argv[0] == '+')
3567 {
3568 draw_info->style=UndefinedStyle;
3569 break;
3570 }
3571 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
3572 MagickFalse,argv[1]);
3573 break;
3574 }
3575 if (LocaleCompare("swirl",argv[0]+1) == 0)
3576 {
3577 /*
3578 Swirl image.
3579 */
3580 (void) SyncImageSettings(image_info,*image);
3581 (void) ParseGeometry(argv[1],&geometry_info);
3582 new_image=SwirlImage(*image,geometry_info.rho,
3583 interpolate_method,exception);
3584 break;
3585 }
3586 break;
3587 }
3588 case 't':
3589 {
3590 if (LocaleCompare("threshold",argv[0]+1) == 0)
3591 {
3592 double
3593 threshold;
3594
3595 /*
3596 Threshold image.
3597 */
3598 (void) SyncImageSettings(image_info,*image);
3599 if (*argv[0] == '+')
3600 threshold=(double) QuantumRange/2;
3601 else
3602 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3603 (void) BilevelImage(*image,threshold);
3604 InheritException(exception,&(*image)->exception);
3605 break;
3606 }
3607 if (LocaleCompare("thumbnail",argv[0]+1) == 0)
3608 {
3609 /*
3610 Thumbnail image.
3611 */
3612 (void) SyncImageSettings(image_info,*image);
3613 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3614 new_image=ThumbnailImage(*image,geometry.width,geometry.height,
3615 exception);
3616 break;
3617 }
3618 if (LocaleCompare("tile",argv[0]+1) == 0)
3619 {
3620 if (*argv[0] == '+')
3621 {
3622 if (draw_info->fill_pattern != (Image *) NULL)
3623 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
3624 break;
3625 }
3626 draw_info->fill_pattern=GetImageCache(image_info,argv[1],
3627 exception);
3628 break;
3629 }
3630 if (LocaleCompare("tint",argv[0]+1) == 0)
3631 {
3632 /*
3633 Tint the image.
3634 */
3635 (void) SyncImageSettings(image_info,*image);
3636 new_image=TintImage(*image,argv[1],&fill,exception);
3637 break;
3638 }
3639 if (LocaleCompare("transform",argv[0]+1) == 0)
3640 {
3641 /*
3642 Affine transform image.
3643 */
3644 (void) SyncImageSettings(image_info,*image);
3645 new_image=AffineTransformImage(*image,&draw_info->affine,
3646 exception);
3647 break;
3648 }
3649 if (LocaleCompare("transparent",argv[0]+1) == 0)
3650 {
3651 PixelInfo
3652 target;
3653
3654 (void) SyncImageSettings(image_info,*image);
anthonya89dd172011-10-04 13:29:35 +00003655 (void) QueryMagickColorCompliance(argv[1],AllCompliance,&target,
3656 exception);
anthony805a2d42011-09-25 08:25:12 +00003657 (void) TransparentPaintImage(*image,&target,(Quantum)
3658 TransparentAlpha,*argv[0] == '-' ? MagickFalse : MagickTrue,
3659 &(*image)->exception);
3660 break;
3661 }
3662 if (LocaleCompare("transpose",argv[0]+1) == 0)
3663 {
3664 /*
3665 Transpose image scanlines.
3666 */
3667 (void) SyncImageSettings(image_info,*image);
3668 new_image=TransposeImage(*image,exception);
3669 break;
3670 }
3671 if (LocaleCompare("transverse",argv[0]+1) == 0)
3672 {
3673 /*
3674 Transverse image scanlines.
3675 */
3676 (void) SyncImageSettings(image_info,*image);
3677 new_image=TransverseImage(*image,exception);
3678 break;
3679 }
3680 if (LocaleCompare("treedepth",argv[0]+1) == 0)
3681 {
3682 quantize_info->tree_depth=StringToUnsignedLong(argv[1]);
3683 break;
3684 }
3685 if (LocaleCompare("trim",argv[0]+1) == 0)
3686 {
3687 /*
3688 Trim image.
3689 */
3690 (void) SyncImageSettings(image_info,*image);
3691 new_image=TrimImage(*image,exception);
3692 break;
3693 }
3694 if (LocaleCompare("type",argv[0]+1) == 0)
3695 {
3696 ImageType
3697 type;
3698
3699 (void) SyncImageSettings(image_info,*image);
3700 if (*argv[0] == '+')
3701 type=UndefinedType;
3702 else
3703 type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
3704 argv[1]);
3705 (*image)->type=UndefinedType;
3706 (void) SetImageType(*image,type,exception);
3707 break;
3708 }
3709 break;
3710 }
3711 case 'u':
3712 {
3713 if (LocaleCompare("undercolor",argv[0]+1) == 0)
3714 {
anthony1afdc7a2011-10-05 11:54:28 +00003715 (void) QueryColorCompliance(argv[1],AllCompliance,&draw_info->undercolor,
anthony805a2d42011-09-25 08:25:12 +00003716 exception);
3717 break;
3718 }
3719 if (LocaleCompare("unique",argv[0]+1) == 0)
3720 {
3721 if (*argv[0] == '+')
3722 {
3723 (void) DeleteImageArtifact(*image,"identify:unique-colors");
3724 break;
3725 }
3726 (void) SetImageArtifact(*image,"identify:unique-colors","true");
3727 (void) SetImageArtifact(*image,"verbose","true");
3728 break;
3729 }
3730 if (LocaleCompare("unique-colors",argv[0]+1) == 0)
3731 {
3732 /*
3733 Unique image colors.
3734 */
3735 (void) SyncImageSettings(image_info,*image);
3736 new_image=UniqueImageColors(*image,exception);
3737 break;
3738 }
3739 if (LocaleCompare("unsharp",argv[0]+1) == 0)
3740 {
3741 /*
3742 Unsharp mask image.
3743 */
3744 (void) SyncImageSettings(image_info,*image);
3745 flags=ParseGeometry(argv[1],&geometry_info);
3746 if ((flags & SigmaValue) == 0)
3747 geometry_info.sigma=1.0;
3748 if ((flags & XiValue) == 0)
3749 geometry_info.xi=1.0;
3750 if ((flags & PsiValue) == 0)
3751 geometry_info.psi=0.05;
3752 new_image=UnsharpMaskImage(*image,geometry_info.rho,
3753 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3754 break;
3755 }
3756 break;
3757 }
3758 case 'v':
3759 {
3760 if (LocaleCompare("verbose",argv[0]+1) == 0)
3761 {
3762 (void) SetImageArtifact(*image,argv[0]+1,
3763 *argv[0] == '+' ? "false" : "true");
3764 break;
3765 }
3766 if (LocaleCompare("vignette",argv[0]+1) == 0)
3767 {
3768 /*
3769 Vignette image.
3770 */
3771 (void) SyncImageSettings(image_info,*image);
3772 flags=ParseGeometry(argv[1],&geometry_info);
3773 if ((flags & SigmaValue) == 0)
3774 geometry_info.sigma=1.0;
3775 if ((flags & XiValue) == 0)
3776 geometry_info.xi=0.1*(*image)->columns;
3777 if ((flags & PsiValue) == 0)
3778 geometry_info.psi=0.1*(*image)->rows;
3779 new_image=VignetteImage(*image,geometry_info.rho,
3780 geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3781 ceil(geometry_info.psi-0.5),exception);
3782 break;
3783 }
3784 if (LocaleCompare("virtual-pixel",argv[0]+1) == 0)
3785 {
3786 if (*argv[0] == '+')
3787 {
3788 (void) SetImageVirtualPixelMethod(*image,
3789 UndefinedVirtualPixelMethod);
3790 break;
3791 }
3792 (void) SetImageVirtualPixelMethod(*image,(VirtualPixelMethod)
3793 ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
3794 argv[1]));
3795 break;
3796 }
3797 break;
3798 }
3799 case 'w':
3800 {
3801 if (LocaleCompare("wave",argv[0]+1) == 0)
3802 {
3803 /*
3804 Wave image.
3805 */
3806 (void) SyncImageSettings(image_info,*image);
3807 flags=ParseGeometry(argv[1],&geometry_info);
3808 if ((flags & SigmaValue) == 0)
3809 geometry_info.sigma=1.0;
3810 new_image=WaveImage(*image,geometry_info.rho,
anthonya89dd172011-10-04 13:29:35 +00003811 geometry_info.sigma,interpolate_method,exception);
anthony805a2d42011-09-25 08:25:12 +00003812 break;
3813 }
3814 if (LocaleCompare("weight",argv[0]+1) == 0)
3815 {
3816 draw_info->weight=StringToUnsignedLong(argv[1]);
3817 if (LocaleCompare(argv[1],"all") == 0)
3818 draw_info->weight=0;
3819 if (LocaleCompare(argv[1],"bold") == 0)
3820 draw_info->weight=700;
3821 if (LocaleCompare(argv[1],"bolder") == 0)
3822 if (draw_info->weight <= 800)
3823 draw_info->weight+=100;
3824 if (LocaleCompare(argv[1],"lighter") == 0)
3825 if (draw_info->weight >= 100)
3826 draw_info->weight-=100;
3827 if (LocaleCompare(argv[1],"normal") == 0)
3828 draw_info->weight=400;
3829 break;
3830 }
3831 if (LocaleCompare("white-threshold",argv[0]+1) == 0)
3832 {
3833 /*
3834 White threshold image.
3835 */
3836 (void) SyncImageSettings(image_info,*image);
3837 (void) WhiteThresholdImage(*image,argv[1],exception);
3838 InheritException(exception,&(*image)->exception);
3839 break;
3840 }
3841 break;
3842 }
3843 default:
3844 break;
3845 }
3846 /*
3847 Replace current image with any image that was generated
3848 */
3849 if (new_image != (Image *) NULL)
3850 ReplaceImageInListReturnLast(image,new_image);
3851
3852 /*
3853 Free resources.
3854 */
3855 quantize_info=DestroyQuantizeInfo(quantize_info);
3856 draw_info=DestroyDrawInfo(draw_info);
anthonya89dd172011-10-04 13:29:35 +00003857 status=(MagickStatusType) ((*image)->exception.severity ==
3858 UndefinedException ? 1 : 0);
3859 return(status == 0 ? MagickFalse : MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003860}
3861
3862/*
3863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3864% %
3865% %
3866% %
3867+ S e q u e n c e O p e r a t i o n I m a g e s %
3868% %
3869% %
3870% %
3871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3872%
3873% SequenceOperationImages() applies a single operation that apply to the
3874% entire image list (e.g. -append, -layers, -coalesce, etc.).
3875%
3876% The format of the MogrifyImage method is:
3877%
3878% MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
3879% const int argc, const char **argv,Image **images,
3880% ExceptionInfo *exception)
3881%
3882% A description of each parameter follows:
3883%
3884% o image_info: the image info..
3885%
3886% o argc: Specifies a pointer to an integer describing the number of
3887% elements in the argument vector.
3888%
3889% o argv: Specifies a pointer to a text array containing the command line
3890% arguments.
3891%
3892% o images: pointer to pointer of the first image in image list.
3893%
3894% o exception: return any errors or warnings in this structure.
3895%
3896*/
3897WandExport MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
3898 const int argc,const char **argv,Image **images,ExceptionInfo *exception)
3899{
3900
3901 MagickStatusType
3902 status;
3903
3904 QuantizeInfo
3905 *quantize_info;
3906
3907 assert(image_info != (ImageInfo *) NULL);
3908 assert(image_info->signature == MagickSignature);
3909 assert(images != (Image **) NULL);
3910 assert((*images)->previous == (Image *) NULL);
3911 assert((*images)->signature == MagickSignature);
3912 if ((*images)->debug != MagickFalse)
3913 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3914 (*images)->filename);
anthonya89dd172011-10-04 13:29:35 +00003915 if ((argc <= 0) || (*argv == (char *) NULL))
3916 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003917 status=MagickTrue;
3918
3919 switch (*(argv[0]+1))
3920 {
3921 case 'a':
3922 {
3923 if (LocaleCompare("affinity",argv[0]+1) == 0)
3924 {
3925 (void) SyncImagesSettings(image_info,*images);
3926 if (*argv[0] == '+')
3927 {
3928 (void) RemapImages(quantize_info,*images,(Image *) NULL,
3929 exception);
3930 break;
3931 }
3932 break;
3933 }
3934 if (LocaleCompare("append",argv[0]+1) == 0)
3935 {
3936 Image
3937 *append_image;
3938
3939 (void) SyncImagesSettings(image_info,*images);
3940 append_image=AppendImages(*images,*argv[0] == '-' ? MagickTrue :
3941 MagickFalse,exception);
3942 if (append_image == (Image *) NULL)
3943 {
3944 status=MagickFalse;
3945 break;
3946 }
3947 *images=DestroyImageList(*images);
3948 *images=append_image;
3949 break;
3950 }
3951 if (LocaleCompare("average",argv[0]+1) == 0)
3952 {
3953 Image
3954 *average_image;
3955
3956 /*
3957 Average an image sequence (deprecated).
3958 */
3959 (void) SyncImagesSettings(image_info,*images);
3960 average_image=EvaluateImages(*images,MeanEvaluateOperator,
3961 exception);
3962 if (average_image == (Image *) NULL)
3963 {
3964 status=MagickFalse;
3965 break;
3966 }
3967 *images=DestroyImageList(*images);
3968 *images=average_image;
3969 break;
3970 }
3971 break;
3972 }
3973 case 'c':
3974 {
3975 if (LocaleCompare("channel",argv[0]+1) == 0)
3976 {
3977 ChannelType
3978 channel;
3979
3980 if (*argv[0] == '+')
3981 {
3982 channel=DefaultChannels;
3983 break;
3984 }
3985 channel=(ChannelType) ParseChannelOption(argv[1]);
3986 SetPixelChannelMap(*images,channel);
3987 break;
3988 }
3989 if (LocaleCompare("clut",argv[0]+1) == 0)
3990 {
3991 Image
3992 *clut_image,
3993 *image;
3994
3995 (void) SyncImagesSettings(image_info,*images);
3996 image=RemoveFirstImageFromList(images);
3997 clut_image=RemoveFirstImageFromList(images);
3998 if (clut_image == (Image *) NULL)
3999 {
4000 status=MagickFalse;
4001 break;
4002 }
anthonya89dd172011-10-04 13:29:35 +00004003 (void) ClutImage(image,clut_image,interpolate_method,exception);
anthony805a2d42011-09-25 08:25:12 +00004004 clut_image=DestroyImage(clut_image);
4005 *images=DestroyImageList(*images);
4006 *images=image;
4007 break;
4008 }
4009 if (LocaleCompare("coalesce",argv[0]+1) == 0)
4010 {
4011 Image
4012 *coalesce_image;
4013
4014 (void) SyncImagesSettings(image_info,*images);
4015 coalesce_image=CoalesceImages(*images,exception);
4016 if (coalesce_image == (Image *) NULL)
4017 {
4018 status=MagickFalse;
4019 break;
4020 }
4021 *images=DestroyImageList(*images);
4022 *images=coalesce_image;
4023 break;
4024 }
4025 if (LocaleCompare("combine",argv[0]+1) == 0)
4026 {
4027 Image
4028 *combine_image;
4029
4030 (void) SyncImagesSettings(image_info,*images);
4031 combine_image=CombineImages(*images,exception);
4032 if (combine_image == (Image *) NULL)
4033 {
4034 status=MagickFalse;
4035 break;
4036 }
4037 *images=DestroyImageList(*images);
4038 *images=combine_image;
4039 break;
4040 }
4041 if (LocaleCompare("composite",argv[0]+1) == 0)
4042 {
4043 Image
4044 *mask_image,
4045 *composite_image,
4046 *image;
4047
4048 RectangleInfo
4049 geometry;
4050
anthony5f867ae2011-10-09 10:28:34 +00004051 ComposeOperator
4052 compose;
4053
4054 const char*
4055 value;
4056
4057 value=GetImageOption(image_info,"compose");
4058 if (value != (const char *) NULL)
4059 compose=(CompositeOperator) ParseCommandOption(
4060 MagickComposeOptions,MagickFalse,value);
4061 else
4062 compose=OverCompositeOp; /* use Over not image->compose */
4063
4064 const char*
4065 value=GetImageOption(image_info,"compose");
4066
4067 if (value != (const char *) NULL)
4068 compose=(CompositeOperator) ParseCommandOption(
4069 MagickComposeOptions,MagickFalse,value);
4070 else
4071 compose=OverCompositeOp; /* use Over not image->compose */
4072
4073
anthony805a2d42011-09-25 08:25:12 +00004074 (void) SyncImagesSettings(image_info,*images);
4075 image=RemoveFirstImageFromList(images);
4076 composite_image=RemoveFirstImageFromList(images);
4077 if (composite_image == (Image *) NULL)
4078 {
4079 status=MagickFalse;
4080 break;
4081 }
4082 (void) TransformImage(&composite_image,(char *) NULL,
4083 composite_image->geometry);
4084 SetGeometry(composite_image,&geometry);
4085 (void) ParseAbsoluteGeometry(composite_image->geometry,&geometry);
4086 GravityAdjustGeometry(image->columns,image->rows,image->gravity,
4087 &geometry);
4088 mask_image=RemoveFirstImageFromList(images);
4089 if (mask_image != (Image *) NULL)
4090 {
anthony5f867ae2011-10-09 10:28:34 +00004091 if ((compose == DisplaceCompositeOp) ||
4092 (compose == DistortCompositeOp))
anthony805a2d42011-09-25 08:25:12 +00004093 {
4094 /*
4095 Merge Y displacement into X displacement image.
4096 */
4097 (void) CompositeImage(composite_image,CopyGreenCompositeOp,
4098 mask_image,0,0);
4099 mask_image=DestroyImage(mask_image);
4100 }
4101 else
4102 {
4103 /*
4104 Set a blending mask for the composition.
4105 Posible error, what if image->mask already set.
4106 */
4107 image->mask=mask_image;
4108 (void) NegateImage(image->mask,MagickFalse,exception);
4109 }
4110 }
anthony5f867ae2011-10-09 10:28:34 +00004111 (void) CompositeImage(image,compose,composite_image,
anthony805a2d42011-09-25 08:25:12 +00004112 geometry.x,geometry.y);
4113 if (mask_image != (Image *) NULL)
4114 mask_image=image->mask=DestroyImage(image->mask);
4115 composite_image=DestroyImage(composite_image);
4116 InheritException(exception,&image->exception);
4117 *images=DestroyImageList(*images);
4118 *images=image;
4119 break;
4120 }
4121 break;
4122 }
4123 case 'd':
4124 {
4125 if (LocaleCompare("deconstruct",argv[0]+1) == 0)
4126 {
4127 Image
4128 *deconstruct_image;
4129
4130 (void) SyncImagesSettings(image_info,*images);
4131 deconstruct_image=CompareImagesLayers(*images,CompareAnyLayer,
4132 exception);
4133 if (deconstruct_image == (Image *) NULL)
4134 {
4135 status=MagickFalse;
4136 break;
4137 }
4138 *images=DestroyImageList(*images);
4139 *images=deconstruct_image;
4140 break;
4141 }
4142 if (LocaleCompare("delete",argv[0]+1) == 0)
4143 {
4144 if (*argv[0] == '+')
4145 DeleteImages(images,"-1",exception);
4146 else
4147 DeleteImages(images,argv[1],exception);
4148 break;
4149 }
4150 if (LocaleCompare("dither",argv[0]+1) == 0)
4151 {
4152 if (*argv[0] == '+')
4153 {
4154 quantize_info->dither=MagickFalse;
4155 break;
4156 }
4157 quantize_info->dither=MagickTrue;
4158 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
4159 MagickDitherOptions,MagickFalse,argv[1]);
4160 break;
4161 }
4162 if (LocaleCompare("duplicate",argv[0]+1) == 0)
4163 {
4164 Image
4165 *duplicate_images;
4166
4167 if (*argv[0] == '+')
4168 duplicate_images=DuplicateImages(*images,1,"-1",exception);
4169 else
4170 {
4171 const char
4172 *p;
4173
4174 size_t
4175 number_duplicates;
4176
4177 number_duplicates=(size_t) StringToLong(argv[1]);
4178 p=strchr(argv[1],',');
4179 if (p == (const char *) NULL)
4180 duplicate_images=DuplicateImages(*images,number_duplicates,
4181 "-1",exception);
4182 else
4183 duplicate_images=DuplicateImages(*images,number_duplicates,p,
4184 exception);
4185 }
4186 AppendImageToList(images, duplicate_images);
4187 (void) SyncImagesSettings(image_info,*images);
4188 break;
4189 }
4190 break;
4191 }
4192 case 'e':
4193 {
4194 if (LocaleCompare("evaluate-sequence",argv[0]+1) == 0)
4195 {
4196 Image
4197 *evaluate_image;
4198
4199 MagickEvaluateOperator
4200 op;
4201
4202 (void) SyncImageSettings(image_info,*images);
4203 op=(MagickEvaluateOperator) ParseCommandOption(
4204 MagickEvaluateOptions,MagickFalse,argv[1]);
4205 evaluate_image=EvaluateImages(*images,op,exception);
4206 if (evaluate_image == (Image *) NULL)
4207 {
4208 status=MagickFalse;
4209 break;
4210 }
4211 *images=DestroyImageList(*images);
4212 *images=evaluate_image;
4213 break;
4214 }
4215 break;
4216 }
4217 case 'f':
4218 {
4219 if (LocaleCompare("fft",argv[0]+1) == 0)
4220 {
4221 Image
4222 *fourier_image;
4223
4224 /*
4225 Implements the discrete Fourier transform (DFT).
4226 */
4227 (void) SyncImageSettings(image_info,*images);
4228 fourier_image=ForwardFourierTransformImage(*images,*argv[0] == '-' ?
4229 MagickTrue : MagickFalse,exception);
4230 if (fourier_image == (Image *) NULL)
4231 break;
4232 *images=DestroyImage(*images);
4233 *images=fourier_image;
4234 break;
4235 }
4236 if (LocaleCompare("flatten",argv[0]+1) == 0)
4237 {
4238 Image
4239 *flatten_image;
4240
4241 (void) SyncImagesSettings(image_info,*images);
4242 flatten_image=MergeImageLayers(*images,FlattenLayer,exception);
4243 if (flatten_image == (Image *) NULL)
4244 break;
4245 *images=DestroyImageList(*images);
4246 *images=flatten_image;
4247 break;
4248 }
4249 if (LocaleCompare("fx",argv[0]+1) == 0)
4250 {
4251 Image
4252 *fx_image;
4253
4254 (void) SyncImagesSettings(image_info,*images);
4255 fx_image=FxImage(*images,argv[1],exception);
4256 if (fx_image == (Image *) NULL)
4257 {
4258 status=MagickFalse;
4259 break;
4260 }
4261 *images=DestroyImageList(*images);
4262 *images=fx_image;
4263 break;
4264 }
4265 break;
4266 }
4267 case 'h':
4268 {
4269 if (LocaleCompare("hald-clut",argv[0]+1) == 0)
4270 {
4271 Image
4272 *hald_image,
4273 *image;
4274
4275 (void) SyncImagesSettings(image_info,*images);
4276 image=RemoveFirstImageFromList(images);
4277 hald_image=RemoveFirstImageFromList(images);
4278 if (hald_image == (Image *) NULL)
4279 {
4280 status=MagickFalse;
4281 break;
4282 }
4283 (void) HaldClutImage(image,hald_image,exception);
4284 hald_image=DestroyImage(hald_image);
4285 if (*images != (Image *) NULL)
4286 *images=DestroyImageList(*images);
4287 *images=image;
4288 break;
4289 }
4290 break;
4291 }
4292 case 'i':
4293 {
4294 if (LocaleCompare("ift",argv[0]+1) == 0)
4295 {
4296 Image
4297 *fourier_image,
4298 *magnitude_image,
4299 *phase_image;
4300
4301 /*
4302 Implements the inverse fourier discrete Fourier transform (DFT).
4303 */
4304 (void) SyncImagesSettings(image_info,*images);
4305 magnitude_image=RemoveFirstImageFromList(images);
4306 phase_image=RemoveFirstImageFromList(images);
4307 if (phase_image == (Image *) NULL)
4308 {
4309 status=MagickFalse;
4310 break;
4311 }
4312 fourier_image=InverseFourierTransformImage(magnitude_image,
4313 phase_image,*argv[0] == '-' ? MagickTrue : MagickFalse,exception);
4314 if (fourier_image == (Image *) NULL)
4315 break;
4316 if (*images != (Image *) NULL)
4317 *images=DestroyImage(*images);
4318 *images=fourier_image;
4319 break;
4320 }
4321 if (LocaleCompare("insert",argv[0]+1) == 0)
4322 {
4323 Image
4324 *p,
4325 *q;
4326
4327 index=0;
4328 if (*argv[0] != '+')
4329 index=(ssize_t) StringToLong(argv[1]);
4330 p=RemoveLastImageFromList(images);
4331 if (p == (Image *) NULL)
4332 {
4333 (void) ThrowMagickException(exception,GetMagickModule(),
4334 OptionError,"NoSuchImage","`%s'",argv[1]);
4335 status=MagickFalse;
4336 break;
4337 }
4338 q=p;
4339 if (index == 0)
4340 PrependImageToList(images,q);
4341 else
4342 if (index == (ssize_t) GetImageListLength(*images))
4343 AppendImageToList(images,q);
4344 else
4345 {
4346 q=GetImageFromList(*images,index-1);
4347 if (q == (Image *) NULL)
4348 {
4349 (void) ThrowMagickException(exception,GetMagickModule(),
4350 OptionError,"NoSuchImage","`%s'",argv[1]);
4351 status=MagickFalse;
4352 break;
4353 }
4354 InsertImageInList(&q,p);
4355 }
4356 *images=GetFirstImageInList(q);
4357 break;
4358 }
4359 if (LocaleCompare("interpolate",argv[0]+1) == 0)
4360 {
4361 interpolate_method=(PixelInterpolateMethod) ParseCommandOption(
4362 MagickInterpolateOptions,MagickFalse,argv[1]);
4363 break;
4364 }
4365 break;
4366 }
4367 case 'l':
4368 {
4369 if (LocaleCompare("layers",argv[0]+1) == 0)
4370 {
4371 Image
4372 *layers;
4373
4374 ImageLayerMethod
4375 method;
4376
4377 (void) SyncImagesSettings(image_info,*images);
4378 layers=(Image *) NULL;
4379 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
4380 MagickFalse,argv[1]);
4381 switch (method)
4382 {
4383 case CoalesceLayer:
4384 {
4385 layers=CoalesceImages(*images,exception);
4386 break;
4387 }
4388 case CompareAnyLayer:
4389 case CompareClearLayer:
4390 case CompareOverlayLayer:
4391 default:
4392 {
4393 layers=CompareImagesLayers(*images,method,exception);
4394 break;
4395 }
4396 case MergeLayer:
4397 case FlattenLayer:
4398 case MosaicLayer:
4399 case TrimBoundsLayer:
4400 {
4401 layers=MergeImageLayers(*images,method,exception);
4402 break;
4403 }
4404 case DisposeLayer:
4405 {
4406 layers=DisposeImages(*images,exception);
4407 break;
4408 }
4409 case OptimizeImageLayer:
4410 {
4411 layers=OptimizeImageLayers(*images,exception);
4412 break;
4413 }
4414 case OptimizePlusLayer:
4415 {
4416 layers=OptimizePlusImageLayers(*images,exception);
4417 break;
4418 }
4419 case OptimizeTransLayer:
4420 {
4421 OptimizeImageTransparency(*images,exception);
4422 break;
4423 }
4424 case RemoveDupsLayer:
4425 {
4426 RemoveDuplicateLayers(images,exception);
4427 break;
4428 }
4429 case RemoveZeroLayer:
4430 {
4431 RemoveZeroDelayLayers(images,exception);
4432 break;
4433 }
4434 case OptimizeLayer:
4435 {
4436 /*
4437 General Purpose, GIF Animation Optimizer.
4438 */
4439 layers=CoalesceImages(*images,exception);
4440 if (layers == (Image *) NULL)
4441 {
4442 status=MagickFalse;
4443 break;
4444 }
4445 *images=DestroyImageList(*images);
4446 *images=layers;
4447 layers=OptimizeImageLayers(*images,exception);
4448 if (layers == (Image *) NULL)
4449 {
4450 status=MagickFalse;
4451 break;
4452 }
4453 *images=DestroyImageList(*images);
4454 *images=layers;
4455 layers=(Image *) NULL;
4456 OptimizeImageTransparency(*images,exception);
4457 (void) RemapImages(quantize_info,*images,(Image *) NULL,
4458 exception);
4459 break;
4460 }
4461 case CompositeLayer:
4462 {
anthony805a2d42011-09-25 08:25:12 +00004463 Image
4464 *source;
4465
4466 RectangleInfo
4467 geometry;
4468
anthony5f867ae2011-10-09 10:28:34 +00004469 ComposeOperator
4470 compose;
4471
4472 const char*
4473 value;
4474
4475 value=GetImageOption(image_info,"compose");
4476 if (value != (const char *) NULL)
4477 compose=(CompositeOperator) ParseCommandOption(
4478 MagickComposeOptions,MagickFalse,value);
4479 else
4480 compose=OverCompositeOp; /* use Over not image->compose */
4481
anthony805a2d42011-09-25 08:25:12 +00004482 /*
4483 Split image sequence at the first 'NULL:' image.
4484 */
4485 source=(*images);
4486 while (source != (Image *) NULL)
4487 {
4488 source=GetNextImageInList(source);
4489 if ((source != (Image *) NULL) &&
4490 (LocaleCompare(source->magick,"NULL") == 0))
4491 break;
4492 }
4493 if (source != (Image *) NULL)
4494 {
4495 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4496 (GetNextImageInList(source) == (Image *) NULL))
4497 source=(Image *) NULL;
4498 else
4499 {
4500 /*
4501 Separate the two lists, junk the null: image.
4502 */
4503 source=SplitImageList(source->previous);
4504 DeleteImageFromList(&source);
4505 }
4506 }
4507 if (source == (Image *) NULL)
4508 {
4509 (void) ThrowMagickException(exception,GetMagickModule(),
4510 OptionError,"MissingNullSeparator","layers Composite");
4511 status=MagickFalse;
4512 break;
4513 }
4514 /*
4515 Adjust offset with gravity and virtual canvas.
4516 */
4517 SetGeometry(*images,&geometry);
4518 (void) ParseAbsoluteGeometry((*images)->geometry,&geometry);
4519 geometry.width=source->page.width != 0 ?
4520 source->page.width : source->columns;
4521 geometry.height=source->page.height != 0 ?
4522 source->page.height : source->rows;
4523 GravityAdjustGeometry((*images)->page.width != 0 ?
4524 (*images)->page.width : (*images)->columns,
4525 (*images)->page.height != 0 ? (*images)->page.height :
4526 (*images)->rows,(*images)->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004527
4528 /*
4529 Compose the two image sequences together
4530 */
anthony805a2d42011-09-25 08:25:12 +00004531 CompositeLayers(*images,compose,source,geometry.x,geometry.y,
4532 exception);
4533 source=DestroyImageList(source);
4534 break;
4535 }
4536 }
4537 if (layers == (Image *) NULL)
4538 break;
4539 InheritException(exception,&layers->exception);
4540 *images=DestroyImageList(*images);
4541 *images=layers;
4542 break;
4543 }
4544 break;
4545 }
4546 case 'm':
4547 {
4548 if (LocaleCompare("map",argv[0]+1) == 0)
4549 {
4550 (void) SyncImagesSettings(image_info,*images);
4551 if (*argv[0] == '+')
4552 {
4553 (void) RemapImages(quantize_info,*images,(Image *) NULL,
4554 exception);
4555 break;
4556 }
4557 break;
4558 }
4559 if (LocaleCompare("maximum",argv[0]+1) == 0)
4560 {
4561 Image
4562 *maximum_image;
4563
4564 /*
4565 Maximum image sequence (deprecated).
4566 */
4567 (void) SyncImagesSettings(image_info,*images);
4568 maximum_image=EvaluateImages(*images,MaxEvaluateOperator,exception);
4569 if (maximum_image == (Image *) NULL)
4570 {
4571 status=MagickFalse;
4572 break;
4573 }
4574 *images=DestroyImageList(*images);
4575 *images=maximum_image;
4576 break;
4577 }
4578 if (LocaleCompare("minimum",argv[0]+1) == 0)
4579 {
4580 Image
4581 *minimum_image;
4582
4583 /*
4584 Minimum image sequence (deprecated).
4585 */
4586 (void) SyncImagesSettings(image_info,*images);
4587 minimum_image=EvaluateImages(*images,MinEvaluateOperator,exception);
4588 if (minimum_image == (Image *) NULL)
4589 {
4590 status=MagickFalse;
4591 break;
4592 }
4593 *images=DestroyImageList(*images);
4594 *images=minimum_image;
4595 break;
4596 }
4597 if (LocaleCompare("morph",argv[0]+1) == 0)
4598 {
4599 Image
4600 *morph_image;
4601
4602 (void) SyncImagesSettings(image_info,*images);
4603 morph_image=MorphImages(*images,StringToUnsignedLong(argv[1]),
4604 exception);
4605 if (morph_image == (Image *) NULL)
4606 {
4607 status=MagickFalse;
4608 break;
4609 }
4610 *images=DestroyImageList(*images);
4611 *images=morph_image;
4612 break;
4613 }
4614 if (LocaleCompare("mosaic",argv[0]+1) == 0)
4615 {
4616 Image
4617 *mosaic_image;
4618
4619 (void) SyncImagesSettings(image_info,*images);
4620 mosaic_image=MergeImageLayers(*images,MosaicLayer,exception);
4621 if (mosaic_image == (Image *) NULL)
4622 {
4623 status=MagickFalse;
4624 break;
4625 }
4626 *images=DestroyImageList(*images);
4627 *images=mosaic_image;
4628 break;
4629 }
4630 break;
4631 }
4632 case 'p':
4633 {
4634 if (LocaleCompare("print",argv[0]+1) == 0)
4635 {
4636 char
4637 *string;
4638
4639 (void) SyncImagesSettings(image_info,*images);
4640 string=InterpretImageProperties(image_info,*images,argv[1],
4641 exception);
4642 if (string == (char *) NULL)
4643 break;
4644 (void) FormatLocaleFile(stdout,"%s",string);
4645 string=DestroyString(string);
4646 }
4647 if (LocaleCompare("process",argv[0]+1) == 0)
4648 {
4649 char
4650 **arguments;
4651
4652 int
4653 j,
4654 number_arguments;
4655
4656 (void) SyncImagesSettings(image_info,*images);
4657 arguments=StringToArgv(argv[1],&number_arguments);
4658 if (arguments == (char **) NULL)
4659 break;
4660 if ((argc > 1) && (strchr(arguments[1],'=') != (char *) NULL))
4661 {
4662 char
4663 breaker,
4664 quote,
4665 *token;
4666
4667 const char
4668 *arguments;
4669
4670 int
4671 next,
4672 status;
4673
4674 size_t
4675 length;
4676
4677 TokenInfo
4678 *token_info;
4679
4680 /*
4681 Support old style syntax, filter="-option arg".
4682 */
4683 length=strlen(argv[1]);
4684 token=(char *) NULL;
4685 if (~length >= (MaxTextExtent-1))
4686 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4687 sizeof(*token));
4688 if (token == (char *) NULL)
4689 break;
4690 next=0;
4691 arguments=argv[1];
4692 token_info=AcquireTokenInfo();
4693 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4694 "\"",'\0',&breaker,&next,&quote);
4695 token_info=DestroyTokenInfo(token_info);
4696 if (status == 0)
4697 {
4698 const char
4699 *argv;
4700
4701 argv=(&(arguments[next]));
4702 (void) InvokeDynamicImageFilter(token,&(*images),1,&argv,
4703 exception);
4704 }
4705 token=DestroyString(token);
4706 break;
4707 }
4708 (void) SubstituteString(&arguments[1],"-","");
4709 (void) InvokeDynamicImageFilter(arguments[1],&(*images),
4710 number_arguments-2,(const char **) arguments+2,exception);
4711 for (j=0; j < number_arguments; j++)
4712 arguments[j]=DestroyString(arguments[j]);
4713 arguments=(char **) RelinquishMagickMemory(arguments);
4714 break;
4715 }
4716 break;
4717 }
4718 case 'r':
4719 {
4720 if (LocaleCompare("reverse",argv[0]+1) == 0)
4721 {
4722 ReverseImageList(images);
4723 InheritException(exception,&(*images)->exception);
4724 break;
4725 }
4726 break;
4727 }
4728 case 's':
4729 {
4730 if (LocaleCompare("smush",argv[0]+1) == 0)
4731 {
4732 Image
4733 *smush_image;
4734
4735 ssize_t
4736 offset;
4737
4738 (void) SyncImagesSettings(image_info,*images);
4739 offset=(ssize_t) StringToLong(argv[1]);
4740 smush_image=SmushImages(*images,*argv[0] == '-' ? MagickTrue :
4741 MagickFalse,offset,exception);
4742 if (smush_image == (Image *) NULL)
4743 {
4744 status=MagickFalse;
4745 break;
4746 }
4747 *images=DestroyImageList(*images);
4748 *images=smush_image;
4749 break;
4750 }
4751 if (LocaleCompare("swap",argv[0]+1) == 0)
4752 {
4753 Image
4754 *p,
4755 *q,
4756 *swap;
4757
4758 ssize_t
4759 swap_index;
4760
4761 index=(-1);
4762 swap_index=(-2);
4763 if (*argv[0] != '+')
4764 {
4765 GeometryInfo
4766 geometry_info;
4767
4768 MagickStatusType
4769 flags;
4770
4771 swap_index=(-1);
4772 flags=ParseGeometry(argv[1],&geometry_info);
4773 index=(ssize_t) geometry_info.rho;
4774 if ((flags & SigmaValue) != 0)
4775 swap_index=(ssize_t) geometry_info.sigma;
4776 }
4777 p=GetImageFromList(*images,index);
4778 q=GetImageFromList(*images,swap_index);
4779 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4780 {
4781 (void) ThrowMagickException(exception,GetMagickModule(),
4782 OptionError,"NoSuchImage","`%s'",(*images)->filename);
4783 status=MagickFalse;
4784 break;
4785 }
4786 if (p == q)
4787 break;
4788 swap=CloneImage(p,0,0,MagickTrue,exception);
4789 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4790 ReplaceImageInList(&q,swap);
4791 *images=GetFirstImageInList(q);
4792 break;
4793 }
4794 break;
4795 }
4796 case 'w':
4797 {
4798 if (LocaleCompare("write",argv[0]+1) == 0)
4799 {
4800 char
4801 key[MaxTextExtent];
4802
4803 Image
4804 *write_images;
4805
4806 ImageInfo
4807 *write_info;
4808
4809 (void) SyncImagesSettings(image_info,*images);
4810 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",argv[1]);
4811 (void) DeleteImageRegistry(key);
4812 write_images=(*images);
4813 if (*argv[0] == '+')
4814 write_images=CloneImageList(*images,exception);
4815 write_info=CloneImageInfo(image_info);
4816 status&=WriteImages(write_info,write_images,argv[1],exception);
4817 write_info=DestroyImageInfo(write_info);
4818 if (*argv[0] == '+')
4819 write_images=DestroyImageList(write_images);
4820 break;
4821 }
4822 break;
4823 }
4824 default:
4825 break;
4826 }
4827 quantize_info=DestroyQuantizeInfo(quantize_info);
4828
anthonya89dd172011-10-04 13:29:35 +00004829 status=(MagickStatusType) ((*image)->exception.severity ==
4830 UndefinedException ? 1 : 0);
anthony805a2d42011-09-25 08:25:12 +00004831 return(status != 0 ? MagickTrue : MagickFalse);
4832}
cristy0a0ca4f2011-09-28 01:15:28 +00004833#endif