|
MagickWand
6.7.7
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % M M AAA GGGG IIIII CCCC K K % 00007 % MM MM A A G I C K K % 00008 % M M M AAAAA G GGG I C KKK % 00009 % M M A A G G I C K K % 00010 % M M A A GGGG IIIII CCCC K K % 00011 % % 00012 % CCCC L IIIII % 00013 % C L I % 00014 % C L I % 00015 % C L I % 00016 % CCCC LLLLL IIIII % 00017 % % 00018 % Perform "Magick" on Images via the Command Line Interface % 00019 % % 00020 % Dragon Computing % 00021 % Anthony Thyssen % 00022 % January 2012 % 00023 % % 00024 % % 00025 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00026 % dedicated to making software imaging solutions freely available. % 00027 % % 00028 % You may not use this file except in compliance with the License. You may % 00029 % obtain a copy of the License at % 00030 % % 00031 % http://www.imagemagick.org/script/license.php % 00032 % % 00033 % Unless required by applicable law or agreed to in writing, software % 00034 % distributed under the License is distributed on an "AS IS" BASIS, % 00035 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00036 % See the License for the specific language governing permissions and % 00037 % limitations under the License. % 00038 % % 00039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00040 % 00041 % Read CLI arguments, script files, and pipelines, to provide options that 00042 % manipulate images from many different formats. 00043 % 00044 */ 00045 00046 /* 00047 Include declarations. 00048 */ 00049 #include "MagickWand/studio.h" 00050 #include "MagickWand/MagickWand.h" 00051 #include "MagickWand/magick-wand-private.h" 00052 #include "MagickWand/wandcli.h" 00053 #include "MagickWand/wandcli-private.h" 00054 #include "MagickWand/operation.h" 00055 #include "MagickWand/magick-cli.h" 00056 #include "MagickWand/script-token.h" 00057 #include "MagickCore/utility-private.h" 00058 #include "MagickCore/exception-private.h" 00059 #include "MagickCore/version.h" 00060 00061 /* verbose debugging, 00062 3 - option type details 00063 9 - output options/artifacts/propertys 00064 */ 00065 #define MagickCommandDebug 0 00066 00067 #if MagickCommandDebug >= 9 00068 /* 00069 Temporary Debugging Information 00070 FUTURE: these should be able to be printed out using 'percent escapes' 00071 Actually 'Properities' can already be output with "%[*]" 00072 */ 00073 static void OutputOptions(ImageInfo *image_info) 00074 { 00075 const char 00076 *option, 00077 *value; 00078 00079 (void) FormatLocaleFile(stderr," Global Options:\n"); 00080 ResetImageOptionIterator(image_info); 00081 while ((option=GetNextImageOption(image_info)) != (const char *) NULL ) { 00082 (void) FormatLocaleFile(stderr," %s: ",option); 00083 value=GetImageOption(image_info,option); 00084 if (value != (const char *) NULL) 00085 (void) FormatLocaleFile(stderr,"%s\n",value); 00086 } 00087 ResetImageOptionIterator(image_info); 00088 } 00089 00090 static void OutputArtifacts(Image *image) 00091 { 00092 const char 00093 *artifact, 00094 *value; 00095 00096 (void) FormatLocaleFile(stderr," Image Artifacts:\n"); 00097 ResetImageArtifactIterator(image); 00098 while ((artifact=GetNextImageArtifact(image)) != (const char *) NULL ) { 00099 (void) FormatLocaleFile(stderr," %s: ",artifact); 00100 value=GetImageArtifact(image,artifact); 00101 if (value != (const char *) NULL) 00102 (void) FormatLocaleFile(stderr,"%s\n",value); 00103 } 00104 ResetImageArtifactIterator(image); 00105 } 00106 00107 static void OutputProperties(Image *image,ExceptionInfo *exception) 00108 { 00109 const char 00110 *property, 00111 *value; 00112 00113 (void) FormatLocaleFile(stderr," Image Properity:\n"); 00114 ResetImagePropertyIterator(image); 00115 while ((property=GetNextImageProperty(image)) != (const char *) NULL ) { 00116 (void) FormatLocaleFile(stderr," %s: ",property); 00117 value=GetImageProperty(image,property,exception); 00118 if (value != (const char *) NULL) 00119 (void) FormatLocaleFile(stderr,"%s\n",value); 00120 } 00121 ResetImagePropertyIterator(image); 00122 } 00123 #endif 00124 00125 00126 /* 00127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00128 % % 00129 % % 00130 % % 00131 + P r o c e s s S c r i p t O p t i o n s % 00132 % % 00133 % % 00134 % % 00135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00136 % 00137 % ProcessScriptOptions() reads options and processes options as they are 00138 % found in the given file, or pipeline. The filename to open and read 00139 % options is given as the 'index' argument of the argument array given. 00140 % 00141 % Other arguments following index may be read by special script options 00142 % as settings (strings), images, or as operations to be processed in various 00143 % ways. How they are treated is up to the script being processed. 00144 % 00145 % Note that a script not 'return' to the command line processing, nor can 00146 % they call (and return from) other scripts. At least not at this time. 00147 % 00148 % There are no 'ProcessOptionFlags' control flags at this time. 00149 % 00150 % The format of the ProcessScriptOptions method is: 00151 % 00152 % void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv, 00153 % int index) 00154 % 00155 % A description of each parameter follows: 00156 % 00157 % o cli_wand: the main CLI Wand to use. 00158 % 00159 % o argc: the number of elements in the argument vector. 00160 % 00161 % o argv: A text array containing the command line arguments. 00162 % 00163 % o index: offset for argc to CLI argumnet count 00164 % 00165 */ 00166 WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv, 00167 int index) 00168 { 00169 ScriptTokenInfo 00170 *token_info; 00171 00172 CommandOptionFlags 00173 option_type; 00174 00175 int 00176 count; 00177 00178 char 00179 *option, 00180 *arg1, 00181 *arg2; 00182 00183 assert(argc>index); /* at least one argument - script name */ 00184 assert(argv != (char **)NULL); 00185 assert(argv[index] != (char *)NULL); 00186 assert(argv[argc-1] != (char *)NULL); 00187 assert(cli_wand != (MagickCLI *) NULL); 00188 assert(cli_wand->signature == WandSignature); 00189 if (cli_wand->wand.debug != MagickFalse) 00190 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); 00191 00192 /* open file script or stream, and set up tokenizer */ 00193 token_info = AcquireScriptTokenInfo(argv[index]); 00194 if (token_info == (ScriptTokenInfo *) NULL) { 00195 CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",argv[index]); 00196 return; 00197 } 00198 00199 /* define the error location string for use in exceptions 00200 order of localtion format escapes: filename, line, column */ 00201 cli_wand->location="in \"%s\" at line %u,column %u"; 00202 if ( LocaleCompare("-", argv[index]) == 0 ) 00203 cli_wand->filename="stdin"; 00204 else 00205 cli_wand->filename=argv[index]; 00206 00207 /* Process Options from Script */ 00208 option = arg1 = arg2 = (char*)NULL; 00209 while (1) { 00210 00211 { MagickBooleanType status = GetScriptToken(token_info); 00212 cli_wand->line=token_info->token_line; 00213 cli_wand->column=token_info->token_column; 00214 if( IfMagickFalse(status) ) 00215 break; /* error or end of options */ 00216 } 00217 00218 do { /* use break to loop to exception handler and loop */ 00219 00220 /* save option details */ 00221 CloneString(&option,token_info->token); 00222 00223 /* get option, its argument count, and option type */ 00224 cli_wand->command = GetCommandOptionInfo(option); 00225 count=cli_wand->command->type; 00226 option_type=(CommandOptionFlags) cli_wand->command->flags; 00227 #if 0 00228 (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n", 00229 cli_wand->line, cli_wand->line, option, cli_wand->command->mnemonic ); 00230 #endif 00231 00232 /* handle a undefined option - image read - always for "magick-script" */ 00233 if ( option_type == UndefinedOptionFlag || 00234 (option_type & NonMagickOptionFlag) != 0 ) { 00235 #if MagickCommandDebug >= 3 00236 (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n", 00237 cli_wand->line, cli_wand->line, option); 00238 #endif 00239 if ( IfMagickFalse(IsCommandOption(option))) { 00240 /* non-option -- treat as a image read */ 00241 cli_wand->command=(const OptionInfo *)NULL; 00242 CLIOption(cli_wand,"-read",option); 00243 break; /* next option */ 00244 } 00245 CLIWandException(OptionFatalError,"UnrecognizedOption",option); 00246 break; /* next option */ 00247 } 00248 00249 if ( count >= 1 ) { 00250 if( IfMagickFalse(GetScriptToken(token_info)) ) 00251 CLIWandException(OptionFatalError,"MissingArgument",option); 00252 CloneString(&arg1,token_info->token); 00253 } 00254 else 00255 CloneString(&arg1,(char *)NULL); 00256 00257 if ( count >= 2 ) { 00258 if( IfMagickFalse(GetScriptToken(token_info)) ) 00259 CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option); 00260 CloneString(&arg2,token_info->token); 00261 } 00262 else 00263 CloneString(&arg2,(char *)NULL); 00264 00265 /* 00266 Process Options 00267 */ 00268 #if MagickCommandDebug >= 3 00269 (void) FormatLocaleFile(stderr, 00270 "Script %u,%u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n", 00271 cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2); 00272 #endif 00273 /* Hard Depreciated Options, no code to execute - error */ 00274 if ( (option_type & DeprecateOptionFlag) != 0 ) { 00275 CLIWandException(OptionError,"DeprecatedOptionNoCode",option); 00276 break; /* next option */ 00277 } 00278 00279 /* MagickCommandGenesis() options have no place in a magick script */ 00280 if ( (option_type & GenesisOptionFlag) != 0 ) { 00281 CLIWandException(OptionError,"InvalidUseOfOption",option); 00282 break; /* next option */ 00283 } 00284 00285 /* handle any special 'script' options */ 00286 if ( (option_type & SpecialOptionFlag) != 0 ) { 00287 if ( LocaleCompare(option,"-exit") == 0 ) { 00288 break; /* forced end of script */ 00289 } 00290 if ( LocaleCompare(option,"-script") == 0 ) { 00291 /* FUTURE: call new script from this script - error for now */ 00292 CLIWandException(OptionError,"InvalidUseOfOption",option); 00293 break; /* next option */ 00294 } 00295 /* FUTURE: handle special script-argument options here */ 00296 /* handle any other special operators now */ 00297 CLIWandException(OptionError,"InvalidUseOfOption",option); 00298 break; /* next option */ 00299 } 00300 00301 /* Process non-specific Option */ 00302 CLIOption(cli_wand, option, arg1, arg2); 00303 00304 } while (0); /* break block to next option */ 00305 00306 #if MagickCommandDebug >= 9 00307 OutputOptions(cli_wand->wand.image_info); 00308 if ( cli_wand->wand.images != (Image *)NULL ) { 00309 OutputArtifacts(cli_wand->wand.images); 00310 OutputProperties(cli_wand->wand.images,cli_wand->wand.exception); 00311 } 00312 #endif 00313 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) ) 00314 break; /* exit loop */ 00315 } 00316 00317 /* 00318 Loop exit - check for some tokenization error 00319 */ 00320 #if MagickCommandDebug >= 3 00321 (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status); 00322 #endif 00323 switch( token_info->status ) { 00324 case TokenStatusOK: 00325 case TokenStatusEOF: 00326 if (cli_wand->image_list_stack != (Stack *)NULL) 00327 CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)"); 00328 else if (cli_wand->image_info_stack != (Stack *)NULL) 00329 CLIWandException(OptionError,"UnbalancedBraces", "(eof)"); 00330 break; 00331 case TokenStatusBadQuotes: 00332 /* Ensure last token has a sane length for error report */ 00333 if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) { 00334 token_info->token[INITAL_TOKEN_LENGTH-4] = '.'; 00335 token_info->token[INITAL_TOKEN_LENGTH-3] = '.'; 00336 token_info->token[INITAL_TOKEN_LENGTH-2] = '.'; 00337 token_info->token[INITAL_TOKEN_LENGTH-1] = '\0'; 00338 } 00339 CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes", 00340 token_info->token); 00341 break; 00342 case TokenStatusMemoryFailed: 00343 CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed",""); 00344 break; 00345 case TokenStatusBinary: 00346 CLIWandException(OptionFatalError,"ScriptIsBinary",""); 00347 break; 00348 } 00349 00350 /* Clean up */ 00351 token_info = DestroyScriptTokenInfo(token_info); 00352 00353 CloneString(&option,(char *)NULL); 00354 CloneString(&arg1,(char *)NULL); 00355 CloneString(&arg2,(char *)NULL); 00356 00357 return; 00358 } 00359 00360 /* 00361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00362 % % 00363 % % 00364 % % 00365 + P r o c e s s C o m m a n d O p t i o n s % 00366 % % 00367 % % 00368 % % 00369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00370 % 00371 % ProcessCommandOptions() reads and processes arguments in the given 00372 % command line argument array. The array does not contain the command 00373 % being processed, only the options. 00374 % 00375 % The 'process_flags' can be used to control and limit option processing. 00376 % For example, to only process one option, or how unknown and special options 00377 % are to be handled, and if the last argument in array is to be regarded as a 00378 % final image write argument (filename or special coder). 00379 % 00380 % The format of the ProcessCommandOptions method is: 00381 % 00382 % int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv, 00383 % int index, ProcessOptionFlags process_flags ) 00384 % 00385 % A description of each parameter follows: 00386 % 00387 % o cli_wand: the main CLI Wand to use. 00388 % 00389 % o argc: the number of elements in the argument vector. 00390 % 00391 % o argv: A text array containing the command line arguments. 00392 % 00393 % o process_flags: What type of arguments will be processed, ignored 00394 % or return errors. 00395 % 00396 % o index: index in the argv array to start processing from 00397 % 00398 % The function returns the index ot the next option to be processed. This 00399 % is really only releven if process_flags contains a ProcessOneOptionOnly 00400 % flag. 00401 % 00402 */ 00403 WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, 00404 char **argv, int index ) 00405 { 00406 const char 00407 *option, 00408 *arg1, 00409 *arg2; 00410 00411 int 00412 i, 00413 end, 00414 count; 00415 00416 CommandOptionFlags 00417 option_type; 00418 00419 assert(argc>=index); /* you may have no arguments left! */ 00420 assert(argv != (char **)NULL); 00421 assert(argv[index] != (char *)NULL); 00422 assert(argv[argc-1] != (char *)NULL); 00423 assert(cli_wand != (MagickCLI *) NULL); 00424 assert(cli_wand->signature == WandSignature); 00425 if (cli_wand->wand.debug != MagickFalse) 00426 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); 00427 00428 /* define the error location string for use in exceptions 00429 order of localtion format escapes: filename, line, column */ 00430 cli_wand->location="at %s argument %u"; 00431 cli_wand->filename="CLI"; 00432 00433 end = argc; 00434 if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 ) 00435 end--; /* the last arument is an implied write, do not process directly */ 00436 00437 for (i=index; i < end; i += count +1) { 00438 /* Finished processing one option? */ 00439 if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index ) 00440 return(i); 00441 00442 do { /* use break to loop to exception handler and loop */ 00443 00444 option=argv[i]; 00445 cli_wand->line=i; /* note the argument for this option */ 00446 00447 /* get option, its argument count, and option type */ 00448 cli_wand->command = GetCommandOptionInfo(argv[i]); 00449 count=cli_wand->command->type; 00450 option_type=(CommandOptionFlags) cli_wand->command->flags; 00451 #if 0 00452 (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n", 00453 i, argv[i], cli_wand->command->mnemonic ); 00454 #endif 00455 00456 if ( option_type == UndefinedOptionFlag || 00457 (option_type & NonMagickOptionFlag) != 0 ) { 00458 #if MagickCommandDebug >= 3 00459 (void) FormatLocaleFile(stderr, "CLI %d Non-Option: \"%s\"\n", i, option); 00460 #endif 00461 if ( IfMagickFalse(IsCommandOption(option)) ) { 00462 if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) { 00463 /* non-option -- treat as a image read */ 00464 cli_wand->command=(const OptionInfo *)NULL; 00465 CLIOption(cli_wand,"-read",option); 00466 break; /* next option */ 00467 } 00468 } 00469 CLIWandException(OptionFatalError,"UnrecognizedOption",option); 00470 break; /* next option */ 00471 } 00472 00473 if ( ((option_type & SpecialOptionFlag) != 0 ) && 00474 ((cli_wand->process_flags & ProcessScriptOption) != 0) && 00475 (LocaleCompare(option,"-script") == 0) ) { 00476 /* Call Script from CLI, with a filename as a zeroth argument. 00477 NOTE: -script may need to use the 'implict write filename' argument 00478 so it must be handled specially to prevent a 'missing argument' error. 00479 */ 00480 if ( (i+count) >= argc ) 00481 CLIWandException(OptionFatalError,"MissingArgument",option); 00482 ProcessScriptOptions(cli_wand,argc,argv,i+1); 00483 return(argc); /* Script does not return to CLI -- Yet */ 00484 /* FUTURE: when it does, their may be no write arg! */ 00485 } 00486 00487 if ((i+count) >= end ) { 00488 CLIWandException(OptionFatalError,"MissingArgument",option); 00489 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse ) 00490 return(end); 00491 break; /* next option - not that their is any! */ 00492 } 00493 00494 arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL; 00495 arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL; 00496 00497 /* 00498 Process Known Options 00499 */ 00500 #if MagickCommandDebug >= 3 00501 (void) FormatLocaleFile(stderr, 00502 "CLI %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n", 00503 i,option,count,option_type,arg1,arg2); 00504 #endif 00505 00506 /* ignore 'genesis options' in command line args */ 00507 if ( (option_type & GenesisOptionFlag) != 0 ) 00508 break; /* next option */ 00509 00510 /* Handle any special options for CLI (-script handled above) */ 00511 if ( (option_type & SpecialOptionFlag) != 0 ) { 00512 if ( (cli_wand->process_flags & ProcessExitOption) != 0 00513 && LocaleCompare(option,"-exit") == 0 ) 00514 return(i+count); 00515 break; /* next option */ 00516 } 00517 00518 /* Process standard image option */ 00519 CLIOption(cli_wand, option, arg1, arg2); 00520 00521 } while (0); /* break block to next option */ 00522 00523 #if MagickCommandDebug >= 9 00524 OutputOptions(cli_wand->wand.image_info); 00525 if ( cli_wand->wand.images != (Image *)NULL ) { 00526 OutputArtifacts(cli_wand->wand.images); 00527 OutputProperties(cli_wand->wand.images,cli_wand->wand.exception); 00528 } 00529 #endif 00530 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse ) 00531 return(i+count); 00532 } 00533 assert(i==end); 00534 00535 if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 ) 00536 return(end); /* no implied write -- just return to caller */ 00537 00538 assert(end==argc-1); /* end should not include last argument */ 00539 00540 /* 00541 Implicit Write of images to final CLI argument 00542 */ 00543 option=argv[i]; 00544 cli_wand->line=i; 00545 00546 /* check that stacks are empty - or cause exception */ 00547 if (cli_wand->image_list_stack != (Stack *)NULL) 00548 CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)"); 00549 else if (cli_wand->image_info_stack != (Stack *)NULL) 00550 CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)"); 00551 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse ) 00552 return(argc); 00553 00554 #if MagickCommandDebug >= 3 00555 (void) FormatLocaleFile(stderr, "CLI %d Write File: \"%s\"\n", i, option ); 00556 #endif 00557 00558 /* Valid 'do no write' replacement option (instead of "null:") */ 00559 if (LocaleCompare(option,"-exit") == 0 ) 00560 return(argc); /* just exit, no image write */ 00561 00562 /* If filename looks like an option, 00563 Or the common 'end of line' error of a single space. 00564 -- produce an error */ 00565 if (IfMagickTrue(IsCommandOption(option)) || 00566 (option[0] == ' ' && option[1] == '\0') ) { 00567 CLIWandException(OptionError,"MissingOutputFilename",option); 00568 return(argc); 00569 } 00570 00571 cli_wand->command=(const OptionInfo *)NULL; 00572 CLIOption(cli_wand,"-write",option); 00573 return(argc); 00574 } 00575 00576 /* 00577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00578 % % 00579 % % 00580 % % 00581 + M a g i c k I m a g e C o m m a n d % 00582 % % 00583 % % 00584 % % 00585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00586 % 00587 % MagickImageCommand() Handle special use CLI arguments and prepare a 00588 % CLI MagickCLI to process the command line or directly specified script. 00589 % 00590 % This is essentualy interface function between the MagickCore library 00591 % initialization function MagickCommandGenesis(), and the option MagickCLI 00592 % processing functions ProcessCommandOptions() or ProcessScriptOptions() 00593 % 00594 % The format of the MagickImageCommand method is: 00595 % 00596 % MagickBooleanType MagickImageCommand(ImageInfo *image_info, 00597 % int argc, char **argv, char **metadata, ExceptionInfo *exception) 00598 % 00599 % A description of each parameter follows: 00600 % 00601 % o image_info: the starting image_info structure 00602 % (for compatibilty with MagickCommandGenisis()) 00603 % 00604 % o argc: the number of elements in the argument vector. 00605 % 00606 % o argv: A text array containing the command line arguments. 00607 % 00608 % o metadata: any metadata (for VBS) is returned here. 00609 % (for compatibilty with MagickCommandGenisis()) 00610 % 00611 % o exception: return any errors or warnings in this structure. 00612 % 00613 */ 00614 00615 static void MagickUsage(MagickBooleanType verbose) 00616 { 00617 const char 00618 *name; 00619 00620 size_t 00621 len; 00622 00623 name=GetClientName(); 00624 len=strlen(name); 00625 00626 if (len>=7 && LocaleCompare("convert",name+len-7) == 0) { 00627 /* convert usage */ 00628 (void) FormatLocaleFile(stdout, 00629 "Usage: %s [{option}|{image}...] {output_image}\n",name); 00630 (void) FormatLocaleFile(stdout, 00631 " %s -help|-version|-usage|-list {option}\n\n",name); 00632 return; 00633 } 00634 else if (len>=6 && LocaleCompare("script",name+len-6) == 0) { 00635 /* magick-script usage */ 00636 (void) FormatLocaleFile(stdout, 00637 "Usage: %s {filename} [{script_args}...]\n",name); 00638 } 00639 else { 00640 /* magick usage */ 00641 (void) FormatLocaleFile(stdout, 00642 "Usage: %s [{option}|{image}...] {output_image}\n",name); 00643 (void) FormatLocaleFile(stdout, 00644 " %s [{option}|{image}...] -script {filename} [{script_args}...]\n", 00645 name); 00646 } 00647 (void) FormatLocaleFile(stdout, 00648 " %s -help|-version|-usage|-list {option}\n\n",name); 00649 00650 if (IfMagickFalse(verbose)) 00651 return; 00652 00653 (void) FormatLocaleFile(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", 00654 "All options are performed in a strict 'as you see them' order\n", 00655 "You must read-in images before you can operate on them.\n", 00656 "\n", 00657 "Magick Script files can use any of the following forms...\n", 00658 " #!/path/to/magick -script\n", 00659 "or\n", 00660 " #!/bin/sh\n", 00661 " :; exec magick -script \"$0\" \"$@\"; exit 10\n", 00662 " # Magick script from here...\n", 00663 "or\n", 00664 " #!/usr/bin/env magick-script\n", 00665 "The latter two forms do not require the path to the command hard coded.\n", 00666 "Note: \"magick-script\" needs to be linked to the \"magick\" command.\n", 00667 "\n", 00668 "For more information on usage, options, examples, and techniques\n", 00669 "see the ImageMagick website at ", MagickAuthoritativeURL); 00670 00671 return; 00672 } 00673 00674 /* 00675 Concatanate given file arguments to the given output argument. 00676 Used for a special -concatenate option used for specific 'delegates'. 00677 The option is not formally documented. 00678 00679 magick -concatenate files... output 00680 00681 This is much like the UNIX "cat" command, but for both UNIX and Windows, 00682 however the last argument provides the output filename. 00683 */ 00684 static MagickBooleanType ConcatenateImages(int argc,char **argv, 00685 ExceptionInfo *exception ) 00686 { 00687 FILE 00688 *input, 00689 *output; 00690 00691 int 00692 c; 00693 00694 register ssize_t 00695 i; 00696 00697 if (IfMagickFalse( ExpandFilenames(&argc,&argv) )) 00698 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed", 00699 GetExceptionMessage(errno)); 00700 00701 output=fopen_utf8(argv[argc-1],"wb"); 00702 if (output == (FILE *) NULL) { 00703 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]); 00704 return(MagickFalse); 00705 } 00706 for (i=2; i < (ssize_t) (argc-1); i++) { 00707 #if 0 00708 fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]); 00709 #endif 00710 input=fopen_utf8(argv[i],"rb"); 00711 if (input == (FILE *) NULL) { 00712 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]); 00713 continue; 00714 } 00715 for (c=fgetc(input); c != EOF; c=fgetc(input)) 00716 (void) fputc((char) c,output); 00717 (void) fclose(input); 00718 (void) remove_utf8(argv[i]); 00719 } 00720 (void) fclose(output); 00721 return(MagickTrue); 00722 } 00723 00724 WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info, 00725 int argc,char **argv,char **metadata,ExceptionInfo *exception) 00726 { 00727 MagickCLI 00728 *cli_wand; 00729 00730 size_t 00731 len; 00732 00733 /* For specific OS command line requirements */ 00734 ReadCommandlLine(argc,&argv); 00735 00736 /* Initialize special "CLI Wand" to hold images and settings (empty) */ 00737 cli_wand=AcquireMagickCLI(image_info,exception); 00738 cli_wand->line=1; 00739 00740 GetPathComponent(argv[0],TailPath,cli_wand->wand.name); 00741 SetClientName(cli_wand->wand.name); 00742 ConcatenateMagickString(cli_wand->wand.name,"-CLI",MaxTextExtent); 00743 00744 len=strlen(argv[0]); /* precaution */ 00745 00746 /* "convert" command - give a "depreciation" warning" */ 00747 if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) { 00748 cli_wand->process_flags = ConvertCommandOptionFlags; 00749 /*(void) FormatLocaleFile(stderr,"WARNING: %s\n", 00750 "The convert is depreciated in IMv7, use \"magick\"\n");*/ 00751 } 00752 00753 /* Special Case: If command name ends with "script" implied "-script" */ 00754 if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) { 00755 if (argc >= 2 && ( (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) { 00756 GetPathComponent(argv[1],TailPath,cli_wand->wand.name); 00757 ProcessScriptOptions(cli_wand,argc,argv,1); 00758 goto Magick_Command_Cleanup; 00759 } 00760 } 00761 00762 /* Special Case: Version Information and Abort */ 00763 if (argc == 2) { 00764 if (LocaleCompare("-version",argv[1]) == 0) { /* just version */ 00765 CLIOption(cli_wand, "-version"); 00766 goto Magick_Command_Exit; 00767 } 00768 if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */ 00769 (LocaleCompare("--help",argv[1]) == 0) ) { /* just a brief summary */ 00770 MagickUsage(MagickFalse); 00771 goto Magick_Command_Exit; 00772 } 00773 if (LocaleCompare("-usage",argv[1]) == 0) { /* both version & usage */ 00774 CLIOption(cli_wand, "-version" ); 00775 MagickUsage(MagickTrue); 00776 goto Magick_Command_Exit; 00777 } 00778 } 00779 00780 /* not enough arguments -- including -help */ 00781 if (argc < 3) { 00782 (void) FormatLocaleFile(stderr, 00783 "Error: Invalid argument or not enough arguments\n\n"); 00784 MagickUsage(MagickFalse); 00785 goto Magick_Command_Exit; 00786 } 00787 00788 /* Special "concatenate option (hidden) for delegate usage */ 00789 if (LocaleCompare("-concatenate",argv[1]) == 0) { 00790 ConcatenateImages(argc,argv,exception); 00791 goto Magick_Command_Exit; 00792 } 00793 00794 /* List Information and Abort */ 00795 if (argc == 3 && LocaleCompare("-list",argv[1]) == 0) { 00796 CLIOption(cli_wand, argv[1], argv[2]); 00797 goto Magick_Command_Exit; 00798 } 00799 00800 /* ------------- */ 00801 /* The Main Call */ 00802 00803 if (LocaleCompare("-script",argv[1]) == 0) { 00804 /* Start processing directly from script, no pre-script options 00805 Replace wand command name with script name 00806 First argument in the argv array is the script name to read. 00807 */ 00808 GetPathComponent(argv[2],TailPath,cli_wand->wand.name); 00809 ProcessScriptOptions(cli_wand,argc,argv,2); 00810 } 00811 else { 00812 /* Normal Command Line, assumes output file as last option */ 00813 ProcessCommandOptions(cli_wand,argc,argv,1); 00814 } 00815 /* ------------- */ 00816 00817 Magick_Command_Cleanup: 00818 /* recover original image_info and clean up stacks 00819 FUTURE: "-reset stacks" option */ 00820 while (cli_wand->image_list_stack != (Stack *)NULL) 00821 CLIOption(cli_wand,")"); 00822 while (cli_wand->image_info_stack != (Stack *)NULL) 00823 CLIOption(cli_wand,"}"); 00824 00825 /* assert we have recovered the original structures */ 00826 assert(cli_wand->wand.image_info == image_info); 00827 assert(cli_wand->wand.exception == exception); 00828 00829 /* Handle metadata for ImageMagickObject COM object for Windows VBS */ 00830 if (metadata != (char **) NULL) { 00831 const char 00832 *format; 00833 00834 char 00835 *text; 00836 00837 format="%w,%h,%m"; // Get this from image_info Option splaytree 00838 00839 text=InterpretImageProperties(image_info,cli_wand->wand.images,format, 00840 exception); 00841 if (text == (char *) NULL) 00842 ThrowMagickException(exception,GetMagickModule(),ResourceLimitError, 00843 "MemoryAllocationFailed","'%s'", GetExceptionMessage(errno)); 00844 else { 00845 (void) ConcatenateString(&(*metadata),text); 00846 text=DestroyString(text); 00847 } 00848 } 00849 00850 Magick_Command_Exit: 00851 /* Destroy the special CLI Wand */ 00852 cli_wand->wand.image_info = (ImageInfo *)NULL; /* not these */ 00853 cli_wand->wand.exception = (ExceptionInfo *)NULL; 00854 cli_wand=DestroyMagickCLI(cli_wand); 00855 00856 return(IsMagickTrue(exception->severity > ErrorException)); 00857 }