2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M AAA GGGG IIIII CCCC K K %
7 % MM MM A A G I C K K %
8 % M M M AAAAA G GGG I C KKK %
9 % M M A A G G I C K K %
10 % M M A A GGGG IIIII CCCC K K %
18 % Perform "Magick" on Images via the Command Line Interface %
25 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
26 % dedicated to making software imaging solutions freely available. %
28 % You may not use this file except in compliance with the License. You may %
29 % obtain a copy of the License at %
31 % http://www.imagemagick.org/script/license.php %
33 % Unless required by applicable law or agreed to in writing, software %
34 % distributed under the License is distributed on an "AS IS" BASIS, %
35 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
36 % See the License for the specific language governing permissions and %
37 % limitations under the License. %
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 % Read CLI arguments, script files, and pipelines, to provide options that
42 % manipulate images from many different formats.
49 #include "MagickWand/studio.h"
50 #include "MagickWand/MagickWand.h"
51 #include "MagickWand/magick-wand-private.h"
52 #include "MagickWand/wandcli.h"
53 #include "MagickWand/wandcli-private.h"
54 #include "MagickWand/operation.h"
55 #include "MagickWand/magick-cli.h"
56 #include "MagickWand/script-token.h"
57 #include "MagickCore/utility-private.h"
58 #include "MagickCore/exception-private.h"
59 #include "MagickCore/version.h"
62 3 - option type details
63 5 - include image counts
64 9 - output options/artifacts/propertys
66 #define MagickCommandDebug 0
68 #if MagickCommandDebug >= 9
70 Temporary Debugging Information
71 FUTURE: these should be able to be printed out using 'percent escapes'
72 Actually 'Properities' can already be output with "%[*]"
74 static void OutputOptions(ImageInfo *image_info)
80 (void) FormatLocaleFile(stderr," Global Options:\n");
81 ResetImageOptionIterator(image_info);
82 while ((option=GetNextImageOption(image_info)) != (const char *) NULL ) {
83 (void) FormatLocaleFile(stderr," %s: ",option);
84 value=GetImageOption(image_info,option);
85 if (value != (const char *) NULL)
86 (void) FormatLocaleFile(stderr,"%s\n",value);
88 ResetImageOptionIterator(image_info);
91 static void OutputArtifacts(Image *image)
97 (void) FormatLocaleFile(stderr," Image Artifacts:\n");
98 ResetImageArtifactIterator(image);
99 while ((artifact=GetNextImageArtifact(image)) != (const char *) NULL ) {
100 (void) FormatLocaleFile(stderr," %s: ",artifact);
101 value=GetImageArtifact(image,artifact);
102 if (value != (const char *) NULL)
103 (void) FormatLocaleFile(stderr,"%s\n",value);
105 ResetImageArtifactIterator(image);
108 static void OutputProperties(Image *image,ExceptionInfo *exception)
114 (void) FormatLocaleFile(stderr," Image Properity:\n");
115 ResetImagePropertyIterator(image);
116 while ((property=GetNextImageProperty(image)) != (const char *) NULL ) {
117 (void) FormatLocaleFile(stderr," %s: ",property);
118 value=GetImageProperty(image,property,exception);
119 if (value != (const char *) NULL)
120 (void) FormatLocaleFile(stderr,"%s\n",value);
122 ResetImagePropertyIterator(image);
128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132 + P r o c e s s S c r i p t O p t i o n s %
136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 % ProcessScriptOptions() reads options and processes options as they are
139 % found in the given file, or pipeline. The filename to open and read
140 % options is given as the 'index' argument of the argument array given.
142 % Other arguments following index may be read by special script options
143 % as settings (strings), images, or as operations to be processed in various
144 % ways. How they are treated is up to the script being processed.
146 % Note that a script not 'return' to the command line processing, nor can
147 % they call (and return from) other scripts. At least not at this time.
149 % There are no 'ProcessOptionFlags' control flags at this time.
151 % The format of the ProcessScriptOptions method is:
153 % void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv,
156 % A description of each parameter follows:
158 % o cli_wand: the main CLI Wand to use.
160 % o argc: the number of elements in the argument vector.
162 % o argv: A text array containing the command line arguments.
164 % o index: offset for argc to CLI argumnet count
167 WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv,
184 assert(argc>index); /* at least one argument - script name */
185 assert(argv != (char **)NULL);
186 assert(argv[index] != (char *)NULL);
187 assert(argv[argc-1] != (char *)NULL);
188 assert(cli_wand != (MagickCLI *) NULL);
189 assert(cli_wand->signature == WandSignature);
190 if (cli_wand->wand.debug != MagickFalse)
191 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
193 /* open file script or stream, and set up tokenizer */
194 token_info = AcquireScriptTokenInfo(argv[index]);
195 if (token_info == (ScriptTokenInfo *) NULL) {
196 CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",argv[index]);
200 /* define the error location string for use in exceptions
201 order of localtion format escapes: filename, line, column */
202 cli_wand->location="in \"%s\" at line %u,column %u";
203 if ( LocaleCompare("-", argv[index]) == 0 )
204 cli_wand->filename="stdin";
206 cli_wand->filename=argv[index];
208 /* Process Options from Script */
209 option = arg1 = arg2 = (char*)NULL;
212 { MagickBooleanType status = GetScriptToken(token_info);
213 cli_wand->line=token_info->token_line;
214 cli_wand->column=token_info->token_column;
215 if( IfMagickFalse(status) )
216 break; /* error or end of options */
219 do { /* use break to loop to exception handler and loop */
221 /* save option details */
222 CloneString(&option,token_info->token);
224 /* get option, its argument count, and option type */
225 cli_wand->command = GetCommandOptionInfo(option);
226 count=cli_wand->command->type;
227 option_type=(CommandOptionFlags) cli_wand->command->flags;
229 (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n",
230 cli_wand->line, cli_wand->line, option, cli_wand->command->mnemonic );
233 /* handle a undefined option - image read - always for "magick-script" */
234 if ( option_type == UndefinedOptionFlag ||
235 (option_type & NonMagickOptionFlag) != 0 ) {
236 #if MagickCommandDebug >= 3
237 (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n",
238 cli_wand->line, cli_wand->line, option);
240 if ( IfMagickFalse(IsCommandOption(option))) {
241 /* non-option -- treat as a image read */
242 cli_wand->command=(const OptionInfo *)NULL;
243 CLIOption(cli_wand,"-read",option);
244 break; /* next option */
246 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
247 break; /* next option */
251 if( IfMagickFalse(GetScriptToken(token_info)) )
252 CLIWandException(OptionFatalError,"MissingArgument",option);
253 CloneString(&arg1,token_info->token);
256 CloneString(&arg1,(char *)NULL);
259 if( IfMagickFalse(GetScriptToken(token_info)) )
260 CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option);
261 CloneString(&arg2,token_info->token);
264 CloneString(&arg2,(char *)NULL);
269 #if MagickCommandDebug >= 3
270 (void) FormatLocaleFile(stderr,
271 "Script %u,%u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
272 cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2);
274 /* Hard Depreciated Options, no code to execute - error */
275 if ( (option_type & DeprecateOptionFlag) != 0 ) {
276 CLIWandException(OptionError,"DeprecatedOptionNoCode",option);
277 break; /* next option */
280 /* MagickCommandGenesis() options have no place in a magick script */
281 if ( (option_type & GenesisOptionFlag) != 0 ) {
282 CLIWandException(OptionError,"InvalidUseOfOption",option);
283 break; /* next option */
286 /* handle any special 'script' options */
287 if ( (option_type & SpecialOptionFlag) != 0 ) {
288 if ( LocaleCompare(option,"-exit") == 0 ) {
289 goto loop_exit; /* break out of loop - return from script */
291 if ( LocaleCompare(option,"-script") == 0 ) {
292 /* FUTURE: call new script from this script - error for now */
293 CLIWandException(OptionError,"InvalidUseOfOption",option);
294 break; /* next option */
296 /* FUTURE: handle special script-argument options here */
297 /* handle any other special operators now */
298 CLIWandException(OptionError,"InvalidUseOfOption",option);
299 break; /* next option */
302 /* Process non-specific Option */
303 CLIOption(cli_wand, option, arg1, arg2);
305 } while (0); /* break block to next option */
307 #if MagickCommandDebug >= 5
308 fprintf(stderr, "Script Image Count = %ld\n",
309 GetImageListLength(cli_wand->wand.images) );
311 #if MagickCommandDebug >= 9
312 OutputOptions(cli_wand->wand.image_info);
313 if ( cli_wand->wand.images != (Image *)NULL ) {
314 OutputArtifacts(cli_wand->wand.images);
315 OutputProperties(cli_wand->wand.images,cli_wand->wand.exception);
318 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
319 break; /* exit loop */
323 Loop exit - check for some tokenization error
326 #if MagickCommandDebug >= 3
327 (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
329 switch( token_info->status ) {
332 if (cli_wand->image_list_stack != (Stack *)NULL)
333 CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
334 else if (cli_wand->image_info_stack != (Stack *)NULL)
335 CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
337 case TokenStatusBadQuotes:
338 /* Ensure last token has a sane length for error report */
339 if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) {
340 token_info->token[INITAL_TOKEN_LENGTH-4] = '.';
341 token_info->token[INITAL_TOKEN_LENGTH-3] = '.';
342 token_info->token[INITAL_TOKEN_LENGTH-2] = '.';
343 token_info->token[INITAL_TOKEN_LENGTH-1] = '\0';
345 CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
348 case TokenStatusMemoryFailed:
349 CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
351 case TokenStatusBinary:
352 CLIWandException(OptionFatalError,"ScriptIsBinary","");
357 token_info = DestroyScriptTokenInfo(token_info);
359 CloneString(&option,(char *)NULL);
360 CloneString(&arg1,(char *)NULL);
361 CloneString(&arg2,(char *)NULL);
367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
371 + P r o c e s s C o m m a n d O p t i o n s %
375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
377 % ProcessCommandOptions() reads and processes arguments in the given
378 % command line argument array. The array does not contain the command
379 % being processed, only the options.
381 % The 'process_flags' can be used to control and limit option processing.
382 % For example, to only process one option, or how unknown and special options
383 % are to be handled, and if the last argument in array is to be regarded as a
384 % final image write argument (filename or special coder).
386 % The format of the ProcessCommandOptions method is:
388 % int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
389 % int index, ProcessOptionFlags process_flags )
391 % A description of each parameter follows:
393 % o cli_wand: the main CLI Wand to use.
395 % o argc: the number of elements in the argument vector.
397 % o argv: A text array containing the command line arguments.
399 % o process_flags: What type of arguments will be processed, ignored
402 % o index: index in the argv array to start processing from
404 % The function returns the index ot the next option to be processed. This
405 % is really only releven if process_flags contains a ProcessOneOptionOnly
409 WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc,
410 char **argv, int index )
425 assert(argc>=index); /* you may have no arguments left! */
426 assert(argv != (char **)NULL);
427 assert(argv[index] != (char *)NULL);
428 assert(argv[argc-1] != (char *)NULL);
429 assert(cli_wand != (MagickCLI *) NULL);
430 assert(cli_wand->signature == WandSignature);
431 if (cli_wand->wand.debug != MagickFalse)
432 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
434 /* define the error location string for use in exceptions
435 order of localtion format escapes: filename, line, column */
436 cli_wand->location="at %s argument %u";
437 cli_wand->filename="CLI";
440 if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 )
441 end--; /* the last arument is an implied write, do not process directly */
443 for (i=index; i < end; i += count +1) {
444 /* Finished processing one option? */
445 if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
448 do { /* use break to loop to exception handler and loop */
451 cli_wand->line=i; /* note the argument for this option */
453 /* get option, its argument count, and option type */
454 cli_wand->command = GetCommandOptionInfo(argv[i]);
455 count=cli_wand->command->type;
456 option_type=(CommandOptionFlags) cli_wand->command->flags;
458 (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n",
459 i, argv[i], cli_wand->command->mnemonic );
462 if ( option_type == UndefinedOptionFlag ||
463 (option_type & NonMagickOptionFlag) != 0 ) {
464 #if MagickCommandDebug >= 3
465 (void) FormatLocaleFile(stderr, "CLI %d Non-Option: \"%s\"\n", i, option);
467 if ( IfMagickFalse(IsCommandOption(option)) ) {
468 if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) {
469 /* non-option -- treat as a image read */
470 cli_wand->command=(const OptionInfo *)NULL;
471 CLIOption(cli_wand,"-read",option);
472 break; /* next option */
475 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
476 break; /* next option */
479 if ( ((option_type & SpecialOptionFlag) != 0 ) &&
480 ((cli_wand->process_flags & ProcessScriptOption) != 0) &&
481 (LocaleCompare(option,"-script") == 0) ) {
482 /* Call Script from CLI, with a filename as a zeroth argument.
483 NOTE: -script may need to use the 'implict write filename' argument
484 so it must be handled specially to prevent a 'missing argument' error.
486 if ( (i+count) >= argc )
487 CLIWandException(OptionFatalError,"MissingArgument",option);
488 ProcessScriptOptions(cli_wand,argc,argv,i+1);
489 return(argc); /* Script does not return to CLI -- Yet */
490 /* FUTURE: when it does, their may be no write arg! */
493 if ((i+count) >= end ) {
494 CLIWandException(OptionFatalError,"MissingArgument",option);
495 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
497 break; /* next option - not that their is any! */
500 arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL;
501 arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL;
504 Process Known Options
506 #if MagickCommandDebug >= 3
507 (void) FormatLocaleFile(stderr,
508 "CLI %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
509 i,option,count,option_type,arg1,arg2);
512 /* ignore 'genesis options' in command line args */
513 if ( (option_type & GenesisOptionFlag) != 0 )
514 break; /* next option */
516 /* Handle any special options for CLI (-script handled above) */
517 if ( (option_type & SpecialOptionFlag) != 0 ) {
518 if ( (cli_wand->process_flags & ProcessExitOption) != 0
519 && LocaleCompare(option,"-exit") == 0 )
521 break; /* next option */
524 /* Process standard image option */
525 CLIOption(cli_wand, option, arg1, arg2);
527 } while (0); /* break block to next option */
529 #if MagickCommandDebug >= 5
530 fprintf(stderr, "CLI Image Count = %ld\n",
531 GetImageListLength(cli_wand->wand.images) );
533 #if MagickCommandDebug >= 9
534 OutputOptions(cli_wand->wand.image_info);
535 if ( cli_wand->wand.images != (Image *)NULL ) {
536 OutputArtifacts(cli_wand->wand.images);
537 OutputProperties(cli_wand->wand.images,cli_wand->wand.exception);
540 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
545 if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 )
546 return(end); /* no implied write -- just return to caller */
548 assert(end==argc-1); /* end should not include last argument */
551 Implicit Write of images to final CLI argument
556 /* check that stacks are empty - or cause exception */
557 if (cli_wand->image_list_stack != (Stack *)NULL)
558 CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)");
559 else if (cli_wand->image_info_stack != (Stack *)NULL)
560 CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)");
561 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
564 #if MagickCommandDebug >= 3
565 (void) FormatLocaleFile(stderr, "CLI %d Write File: \"%s\"\n", i, option );
568 /* Valid 'do no write' replacement option (instead of "null:") */
569 if (LocaleCompare(option,"-exit") == 0 )
570 return(argc); /* just exit, no image write */
572 /* If filename looks like an option,
573 Or the common 'end of line' error of a single space.
574 -- produce an error */
575 if (IfMagickTrue(IsCommandOption(option)) ||
576 (option[0] == ' ' && option[1] == '\0') ) {
577 CLIWandException(OptionError,"MissingOutputFilename",option);
581 cli_wand->command=(const OptionInfo *)NULL;
582 CLIOption(cli_wand,"-write",option);
587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 + M a g i c k I m a g e C o m m a n d %
595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597 % MagickImageCommand() Handle special use CLI arguments and prepare a
598 % CLI MagickCLI to process the command line or directly specified script.
600 % This is essentualy interface function between the MagickCore library
601 % initialization function MagickCommandGenesis(), and the option MagickCLI
602 % processing functions ProcessCommandOptions() or ProcessScriptOptions()
604 % The format of the MagickImageCommand method is:
606 % MagickBooleanType MagickImageCommand(ImageInfo *image_info,
607 % int argc, char **argv, char **metadata, ExceptionInfo *exception)
609 % A description of each parameter follows:
611 % o image_info: the starting image_info structure
612 % (for compatibilty with MagickCommandGenisis())
614 % o argc: the number of elements in the argument vector.
616 % o argv: A text array containing the command line arguments.
618 % o metadata: any metadata (for VBS) is returned here.
619 % (for compatibilty with MagickCommandGenisis())
621 % o exception: return any errors or warnings in this structure.
625 static void MagickUsage(MagickBooleanType verbose)
633 name=GetClientName();
636 if (len>=7 && LocaleCompare("convert",name+len-7) == 0) {
638 (void) FormatLocaleFile(stdout,
639 "Usage: %s [{option}|{image}...] {output_image}\n",name);
640 (void) FormatLocaleFile(stdout,
641 " %s -help|-version|-usage|-list {option}\n\n",name);
644 else if (len>=6 && LocaleCompare("script",name+len-6) == 0) {
645 /* magick-script usage */
646 (void) FormatLocaleFile(stdout,
647 "Usage: %s {filename} [{script_args}...]\n",name);
651 (void) FormatLocaleFile(stdout,
652 "Usage: %s [{option}|{image}...] {output_image}\n",name);
653 (void) FormatLocaleFile(stdout,
654 " %s [{option}|{image}...] -script {filename} [{script_args}...]\n",
657 (void) FormatLocaleFile(stdout,
658 " %s -help|-version|-usage|-list {option}\n\n",name);
660 if (IfMagickFalse(verbose))
663 (void) FormatLocaleFile(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
664 "All options are performed in a strict 'as you see them' order\n",
665 "You must read-in images before you can operate on them.\n",
667 "Magick Script files can use any of the following forms...\n",
668 " #!/path/to/magick -script\n",
671 " :; exec magick -script \"$0\" \"$@\"; exit 10\n",
672 " # Magick script from here...\n",
674 " #!/usr/bin/env magick-script\n",
675 "The latter two forms do not require the path to the command hard coded.\n",
676 "Note: \"magick-script\" needs to be linked to the \"magick\" command.\n",
678 "For more information on usage, options, examples, and techniques\n",
679 "see the ImageMagick website at ", MagickAuthoritativeURL);
685 Concatanate given file arguments to the given output argument.
686 Used for a special -concatenate option used for specific 'delegates'.
687 The option is not formally documented.
689 magick -concatenate files... output
691 This is much like the UNIX "cat" command, but for both UNIX and Windows,
692 however the last argument provides the output filename.
694 static MagickBooleanType ConcatenateImages(int argc,char **argv,
695 ExceptionInfo *exception )
707 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
708 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
709 GetExceptionMessage(errno));
711 output=fopen_utf8(argv[argc-1],"wb");
712 if (output == (FILE *) NULL) {
713 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
716 for (i=2; i < (ssize_t) (argc-1); i++) {
718 fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
720 input=fopen_utf8(argv[i],"rb");
721 if (input == (FILE *) NULL) {
722 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
725 for (c=fgetc(input); c != EOF; c=fgetc(input))
726 (void) fputc((char) c,output);
727 (void) fclose(input);
728 (void) remove_utf8(argv[i]);
730 (void) fclose(output);
734 WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info,
735 int argc,char **argv,char **metadata,ExceptionInfo *exception)
743 /* For specific OS command line requirements */
744 ReadCommandlLine(argc,&argv);
746 /* Initialize special "CLI Wand" to hold images and settings (empty) */
747 cli_wand=AcquireMagickCLI(image_info,exception);
750 GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
751 SetClientName(cli_wand->wand.name);
752 ConcatenateMagickString(cli_wand->wand.name,"-CLI",MaxTextExtent);
754 len=strlen(argv[0]); /* precaution */
756 /* "convert" command - give a "depreciation" warning" */
757 if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) {
758 cli_wand->process_flags = ConvertCommandOptionFlags;
759 /*(void) FormatLocaleFile(stderr,"WARNING: %s\n",
760 "The convert is depreciated in IMv7, use \"magick\"\n");*/
763 /* Special Case: If command name ends with "script" implied "-script" */
764 if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) {
765 if (argc >= 2 && ( (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) {
766 GetPathComponent(argv[1],TailPath,cli_wand->wand.name);
767 ProcessScriptOptions(cli_wand,argc,argv,1);
768 goto Magick_Command_Cleanup;
772 /* Special Case: Version Information and Abort */
774 if (LocaleCompare("-version",argv[1]) == 0) { /* just version */
775 CLIOption(cli_wand, "-version");
776 goto Magick_Command_Exit;
778 if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */
779 (LocaleCompare("--help",argv[1]) == 0) ) { /* just a brief summary */
780 MagickUsage(MagickFalse);
781 goto Magick_Command_Exit;
783 if (LocaleCompare("-usage",argv[1]) == 0) { /* both version & usage */
784 CLIOption(cli_wand, "-version" );
785 MagickUsage(MagickTrue);
786 goto Magick_Command_Exit;
790 /* not enough arguments -- including -help */
792 (void) FormatLocaleFile(stderr,
793 "Error: Invalid argument or not enough arguments\n\n");
794 MagickUsage(MagickFalse);
795 goto Magick_Command_Exit;
798 /* Special "concatenate option (hidden) for delegate usage */
799 if (LocaleCompare("-concatenate",argv[1]) == 0) {
800 ConcatenateImages(argc,argv,exception);
801 goto Magick_Command_Exit;
804 /* List Information and Abort */
805 if (argc == 3 && LocaleCompare("-list",argv[1]) == 0) {
806 CLIOption(cli_wand, argv[1], argv[2]);
807 goto Magick_Command_Exit;
813 if (LocaleCompare("-script",argv[1]) == 0) {
814 /* Start processing directly from script, no pre-script options
815 Replace wand command name with script name
816 First argument in the argv array is the script name to read.
818 GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
819 ProcessScriptOptions(cli_wand,argc,argv,2);
822 /* Normal Command Line, assumes output file as last option */
823 ProcessCommandOptions(cli_wand,argc,argv,1);
827 Magick_Command_Cleanup:
828 /* recover original image_info and clean up stacks
829 FUTURE: "-reset stacks" option */
830 while (cli_wand->image_list_stack != (Stack *)NULL)
831 CLIOption(cli_wand,")");
832 while (cli_wand->image_info_stack != (Stack *)NULL)
833 CLIOption(cli_wand,"}");
835 /* assert we have recovered the original structures */
836 assert(cli_wand->wand.image_info == image_info);
837 assert(cli_wand->wand.exception == exception);
839 /* Handle metadata for ImageMagickObject COM object for Windows VBS */
840 if (metadata != (char **) NULL) {
847 format="%w,%h,%m"; // Get this from image_info Option splaytree
849 text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
851 if (text == (char *) NULL)
852 ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
853 "MemoryAllocationFailed","'%s'", GetExceptionMessage(errno));
855 (void) ConcatenateString(&(*metadata),text);
856 text=DestroyString(text);
861 /* Destroy the special CLI Wand */
862 cli_wand->wand.image_info = (ImageInfo *)NULL; /* not these */
863 cli_wand->wand.exception = (ExceptionInfo *)NULL;
864 cli_wand=DestroyMagickCLI(cli_wand);
866 return(IsMagickTrue(exception->severity > ErrorException));