From: anthony Date: Sat, 14 Apr 2012 12:53:56 +0000 (+0000) Subject: Better syntax checks for "lists of numbers" arguments X-Git-Tag: 7.0.1-0~5810 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b1d483a6a6a5678173db9d60bec52dd5a37826be;p=imagemagick Better syntax checks for "lists of numbers" arguments Also adding some "compare" settings And fixed "-monitor" and "-colorspace" when no images are present. --- diff --git a/MagickCore/option.c b/MagickCore/option.c index 85623216b..5a66da5ae 100644 --- a/MagickCore/option.c +++ b/MagickCore/option.c @@ -337,6 +337,8 @@ static const OptionInfo { "-dispose", 1L, ImageInfoOptionFlag, MagickFalse }, { "+dissolve", 0L, NonMagickOptionFlag, MagickFalse }, { "-dissolve", 1L, NonMagickOptionFlag, MagickFalse }, + { "+dissimilarity-threshold", 0L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, + { "-dissimilarity-threshold", 1L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, { "+distort", 2L, SimpleOperatorOptionFlag, MagickFalse }, { "-distort", 2L, SimpleOperatorOptionFlag, MagickFalse }, { "+dither", 0L, ImageInfoOptionFlag | QuantizeInfoOptionFlag, MagickFalse }, @@ -416,8 +418,8 @@ static const OptionInfo { "-green-primary", 1L, ImageInfoOptionFlag, MagickFalse }, { "+hald-clut", 0L, DeprecateOptionFlag | FireOptionFlag, MagickTrue }, { "-hald-clut", 0L, ListOperatorOptionFlag | FireOptionFlag, MagickFalse }, - { "+highlight-color", 1L, SimpleOperatorOptionFlag, MagickFalse }, - { "-highlight-color", 1L, SimpleOperatorOptionFlag, MagickFalse }, + { "+highlight-color", 0L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, + { "-highlight-color", 1L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, { "+iconGeometry", 0L, NonMagickOptionFlag, MagickFalse }, { "-iconGeometry", 1L, NonMagickOptionFlag, MagickFalse }, { "+iconic", 0L, NonMagickOptionFlag, MagickFalse }, @@ -468,8 +470,8 @@ static const OptionInfo { "-log", 1L, GlobalOptionFlag, MagickFalse }, { "+loop", 0L, ImageInfoOptionFlag, MagickFalse }, { "-loop", 1L, ImageInfoOptionFlag, MagickFalse }, - { "+lowlight-color", 1L, ImageInfoOptionFlag, MagickFalse }, - { "-lowlight-color", 1L, ImageInfoOptionFlag, MagickFalse }, + { "+lowlight-color", 0L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, + { "-lowlight-color", 1L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, { "+magnify", 0L, NonMagickOptionFlag, MagickFalse }, { "-magnify", 1L, NonMagickOptionFlag, MagickFalse }, { "+map", 0L, ReplacedOptionFlag | ListOperatorOptionFlag | FireOptionFlag, MagickTrue }, @@ -643,7 +645,7 @@ static const OptionInfo { "-snaps", 1L, NonMagickOptionFlag, MagickFalse }, { "+solarize", 1L, DeprecateOptionFlag, MagickTrue }, { "-solarize", 1L, SimpleOperatorOptionFlag, MagickFalse }, - { "+sparse-color", 2L, DeprecateOptionFlag, MagickTrue }, + { "+sparse-color", 1L, DeprecateOptionFlag, MagickTrue }, { "-sparse-color", 2L, SimpleOperatorOptionFlag, MagickFalse }, { "+splice", 1L, DeprecateOptionFlag, MagickTrue }, { "-splice", 1L, SimpleOperatorOptionFlag, MagickFalse }, @@ -665,8 +667,8 @@ static const OptionInfo { "-strokewidth", 1L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse }, { "+style", 0L, DrawInfoOptionFlag, MagickFalse }, { "-style", 1L, DrawInfoOptionFlag, MagickFalse }, - { "+subimage-search", 0L, NonMagickOptionFlag, MagickFalse }, - { "-subimage-search", 0L, NonMagickOptionFlag, MagickFalse }, + { "+subimage-search", 0L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, + { "-subimage-search", 0L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, { "+swap", 0L, ListOperatorOptionFlag | FireOptionFlag, MagickFalse }, { "-swap", 1L, ListOperatorOptionFlag | FireOptionFlag, MagickFalse }, { "+swirl", 1L, DeprecateOptionFlag, MagickTrue }, @@ -695,7 +697,7 @@ static const OptionInfo { "-transform", 0L, ReplacedOptionFlag | SimpleOperatorOptionFlag, MagickTrue }, { "+transparent", 1L, SimpleOperatorOptionFlag, MagickFalse }, { "-transparent", 1L, SimpleOperatorOptionFlag, MagickFalse }, - { "+transparent-color", 1L, ImageInfoOptionFlag, MagickFalse }, + { "+transparent-color", 0L, ImageInfoOptionFlag, MagickFalse }, { "-transparent-color", 1L, ImageInfoOptionFlag, MagickFalse }, { "+transpose", 0L, DeprecateOptionFlag, MagickTrue }, { "-transpose", 0L, SimpleOperatorOptionFlag, MagickFalse }, diff --git a/MagickCore/option.h b/MagickCore/option.h index 3679bf0c1..79909c7af 100644 --- a/MagickCore/option.h +++ b/MagickCore/option.h @@ -137,7 +137,7 @@ typedef enum ImageInfoOptionFlag = 0x0001, /* Setting for ImageInfo */ DrawInfoOptionFlag = 0x0002, /* Setting for DrawInfo */ QuantizeInfoOptionFlag = 0x0004, /* Setting for QuantizeInfo */ - GlobalOptionFlag = 0x0008, /* Setting for Global Option */ + GlobalOptionFlag = 0x0008, /* Setting for Global Option - depreciate */ SettingOptionFlags = 0x000F, /* mask for all setting options */ SimpleOperatorOptionFlag = 0x0010, /* Simple Image processing operator */ diff --git a/MagickCore/string.c b/MagickCore/string.c index a2ed535d4..573fc26c4 100644 --- a/MagickCore/string.c +++ b/MagickCore/string.c @@ -53,6 +53,7 @@ #include "MagickCore/resource_.h" #include "MagickCore/signature-private.h" #include "MagickCore/string_.h" +#include "MagickCore/string-private.h" #include "MagickCore/utility-private.h" /* @@ -101,6 +102,9 @@ static const unsigned char % AcquireString() allocates memory for a string and copies the source string % to that memory location (and returns it). % +% The returned string shoud be freed using DestoryString() or +% RelinquishMagickMemory() when finished. +% % The format of the AcquireString method is: % % char *AcquireString(const char *source) @@ -2038,6 +2042,82 @@ MagickExport char *StringInfoToString(const StringInfo *string_info) % % % % % % +% S t r i n g I n f o T o H e x S t r i n g % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% StringInfoToHexString() converts a string info string to a C string. +% +% The format of the StringInfoToHexString method is: +% +% char *StringInfoToHexString(const StringInfo *string_info) +% +% A description of each parameter follows: +% +% o string_info: the string. +% +*/ +MagickExport char *StringInfoToHexString(const StringInfo *string_info) +{ + char + *string; + + register const unsigned char + *p; + + register ssize_t + i; + + register unsigned char + *q; + + size_t + length; + + unsigned char + hex_digits[16]; + + length=string_info->length; + if (~length < MaxTextExtent) + ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString"); + string=(char *) AcquireQuantumMemory(length+MaxTextExtent,2*sizeof(*string)); + if (string == (char *) NULL) + ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString"); + hex_digits[0]='0'; + hex_digits[1]='1'; + hex_digits[2]='2'; + hex_digits[3]='3'; + hex_digits[4]='4'; + hex_digits[5]='5'; + hex_digits[6]='6'; + hex_digits[7]='7'; + hex_digits[8]='8'; + hex_digits[9]='9'; + hex_digits[10]='a'; + hex_digits[11]='b'; + hex_digits[12]='c'; + hex_digits[13]='d'; + hex_digits[14]='e'; + hex_digits[15]='f'; + p=string_info->datum; + q=(unsigned char *) string; + for (i=0; i < (ssize_t) string_info->length; i++) + { + *q++=hex_digits[(*p >> 4) & 0x0f]; + *q++=hex_digits[*p & 0x0f]; + p++; + } + *q='\0'; + return(string); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % S t r i n g T o A r g v % % % % % @@ -2152,75 +2232,85 @@ MagickExport char **StringToArgv(const char *text,int *argc) % % % % % % -% S t r i n g I n f o T o H e x S t r i n g % +% S t r i n g T o A r r a y O f D o u b l e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% StringInfoToHexString() converts a string info string to a C string. +% StringToArrayOfDoubles() converts a string of space or comma seperated +% numbers into array of floating point numbers (doubles). Any number that +% failes to parse properly will produce a syntax error. As will two commas +% without a number between them. However a final comma at the end will +% not be regarded as an error so as to simplify automatic list generation. % -% The format of the StringInfoToHexString method is: +% A NULL value is returned on syntax or memory errors. % -% char *StringInfoToHexString(const StringInfo *string_info) +% Use RelinquishMagickMemory() to free returned array when finished. +% +% The format of the StringToArrayOfDoubles method is: +% +% double *StringToArrayOfDoubles(const char *string, +% size_t *count, ExceptionInfo *exception) % % A description of each parameter follows: % -% o string_info: the string. +% o string: the string containing the comma/space seperated values. +% +% o count: returns number of arguments in returned array +% +% o exception: return 'mamory failure' exceptions % */ -MagickExport char *StringInfoToHexString(const StringInfo *string_info) +MagickExport double *StringToArrayOfDoubles(const char *string, + ssize_t *count, ExceptionInfo *exception) { + const char + *p; + char - *string; + *q; - register const unsigned char - *p; + double + *array; register ssize_t i; - register unsigned char - *q; - - size_t - length; + /* Determine count of values, and check syntax */ + *count=0; + p=string; + i=0; + while( *p != '\0' ) + { + (void) StringToDouble(p, &q); /* get value - ignores leading space */ + if (p == q) return((double *)NULL); /* no value found */ + p=q; i++; /* inc value count */ + while ( isspace((int)*p) ) p++; /* skip spaces */ + if ( *p == ',' ) p++; /* skip comma */ + while ( isspace((int)*p) ) p++; /* and more spaces */ + } - unsigned char - hex_digits[16]; + /* Allocate floating point argument list */ + *count=i; + array=(double *) AcquireQuantumMemory(i,sizeof(*array)); + if (array == (double *) NULL) { + ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitFatalError,"MemoryAllocationFailed"," "); + return((double *)NULL); + } - length=string_info->length; - if (~length < MaxTextExtent) - ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString"); - string=(char *) AcquireQuantumMemory(length+MaxTextExtent,2*sizeof(*string)); - if (string == (char *) NULL) - ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString"); - hex_digits[0]='0'; - hex_digits[1]='1'; - hex_digits[2]='2'; - hex_digits[3]='3'; - hex_digits[4]='4'; - hex_digits[5]='5'; - hex_digits[6]='6'; - hex_digits[7]='7'; - hex_digits[8]='8'; - hex_digits[9]='9'; - hex_digits[10]='a'; - hex_digits[11]='b'; - hex_digits[12]='c'; - hex_digits[13]='d'; - hex_digits[14]='e'; - hex_digits[15]='f'; - p=string_info->datum; - q=(unsigned char *) string; - for (i=0; i < (ssize_t) string_info->length; i++) - { - *q++=hex_digits[(*p >> 4) & 0x0f]; - *q++=hex_digits[*p & 0x0f]; - p++; + /* Fill in the floating point values */ + p=string; + i=0; + while( *p != '\0' && i < *count ) { + array[i++]=StringToDouble(p,&q); + p=q; + while ( isspace((int)*p) || *p == ',' ) p++; } - *q='\0'; - return(string); + + return(array); } /* @@ -2228,13 +2318,22 @@ MagickExport char *StringInfoToHexString(const StringInfo *string_info) % % % % % % -% S t r i n g T o k e n % ++ S t r i n g T o k e n % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% StringToken() extracts a token a from the string. +% StringToken() Looks for any one of given delimiters and splits the string +% into two separate strings by replacing the delimiter character found with a +% nul character. +% +% The given string pointer is changed to point to the string following the +% delimiter character found, or NULL. A pointer to the start of the +% string is returned, representing the token before the delimiter. +% +% In may ways this is equivent to the strtok() C library function, but with +% multiple delimiter characters rather than a delimiter string. % % The format of the StringToken method is: % @@ -2266,7 +2365,8 @@ MagickExport char *StringToken(const char *delimiters,char **string) p=(*string); if (p == (char *) NULL) return((char *) NULL); - for (q=p; ; ) + q=p; + for ( ; ; ) { c=(*p++); r=delimiters; diff --git a/MagickCore/string_.h b/MagickCore/string_.h index 60640cc7a..841c40c21 100644 --- a/MagickCore/string_.h +++ b/MagickCore/string_.h @@ -58,19 +58,22 @@ extern MagickExport const char *GetStringInfoPath(const StringInfo *); extern MagickExport double - InterpretSiPrefixValue(const char *restrict,char **restrict); + InterpretSiPrefixValue(const char *restrict,char **restrict), + *StringToArrayOfDoubles(const char *,ssize_t *, ExceptionInfo *); extern MagickExport int CompareStringInfo(const StringInfo *,const StringInfo *), LocaleCompare(const char *,const char *), LocaleNCompare(const char *,const char *,const size_t); + extern MagickExport MagickBooleanType ConcatenateString(char **,const char *), IsStringTrue(const char *), IsStringNotFalse(const char *), SubstituteString(char **,const char *,const char *); + extern MagickExport size_t ConcatenateMagickString(char *,const char *,const size_t) magick_attribute((__nonnull__)), diff --git a/MagickWand/magick-cli.c b/MagickWand/magick-cli.c index 1c2a969bb..f9a97811f 100644 --- a/MagickWand/magick-cli.c +++ b/MagickWand/magick-cli.c @@ -269,37 +269,28 @@ WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv, else CloneString(&arg2,(char *)NULL); + /* + Process Options + */ #if MagickCommandDebug >= 3 (void) FormatLocaleFile(stderr, "Script %u,%u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n", cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2); #endif - - if ( (option_type & GenesisOptionFlag) != 0 ) { - /* Genesis Options have no place in a magick script */ - CLIWandExceptionBreak(OptionError,"InvalidUseOfOption",option); - goto next_token; - } + /* Hard Depreciated Options, no code to execute - error */ if ( (option_type & DeprecateOptionFlag) != 0 ) { - CLIWandException(OptionWarning,"DeprecatedOption",option); + CLIWandException(OptionError,"DeprecatedOptionNoCode",option); if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse ) break; - /* fall through - do the depreciated option */ - } - if (((option_type & ImageRequiredFlags) != 0 ) && - ( cli_wand->wand.images == (Image *)NULL ) ) { - CLIWandException(OptionError,"NoImagesFound",option); goto next_token; } - /* handle special script-argument options here */ - //either continue processing command line - // or making use of the command line options. - //CLICommandOptions(cli_wand,count+1,argv, MagickScriptArgsFlags); + /* MagickCommandGenesis() options have no place in a magick script */ + if ( (option_type & GenesisOptionFlag) != 0 ) { + CLIWandExceptionBreak(OptionError,"InvalidUseOfOption",option); + goto next_token; + } - /* - Process Option from file - */ if ( (option_type & SpecialOptionFlag) != 0 ) { if ( LocaleCompare(option,"-exit") == 0 ) { break; /* forced end of script */ @@ -309,6 +300,7 @@ WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv, CLIWandExceptionBreak(OptionError,"InvalidUseOfOption",option); goto next_token; } + /* FUTURE: handle special script-argument options here */ /* handle any other special operators now */ CLISpecialOperator(cli_wand,option,arg1); } @@ -317,9 +309,21 @@ WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv, CLISettingOptionInfo(cli_wand, option, arg1, arg2); // FUTURE: Sync Specific Settings into Image Properities (not global) } - if ( cli_wand->wand.images != (Image *)NULL ) - SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images, - cli_wand->wand.exception); + + /* FUTURE: The not a setting part below is a temporary hack to stop gap + * measure for options that are BOTH settings and optional 'Simple/List' + * operators. Specifically -monitor and -colorspace */ + if ( cli_wand->wand.images == (Image *)NULL ) { + if (((option_type & ImageRequiredFlags) != 0 ) && + ((option_type & SettingOptionFlags) == 0 )) /* temp hack */ + CLIWandException(OptionError,"NoImagesFound",option); + goto next_token; + } + + /* FUTURE: this is temporary - get 'settings' to handle + distribution of settings to images attributes,proprieties,artifacts */ + SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images, + cli_wand->wand.exception); if ( (option_type & SimpleOperatorOptionFlag) != 0) CLISimpleOperatorImages(cli_wand, option, arg1, arg2); @@ -509,24 +513,23 @@ WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL; arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL; + /* + Process Known Options + */ #if MagickCommandDebug >= 3 (void) FormatLocaleFile(stderr, "CLI %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n", i,option,count,option_type,arg1,arg2); #endif - + /* Hard Depreciated Options, no code to execute - error */ if ( (option_type & DeprecateOptionFlag) != 0 ) { CLIWandException(OptionError,"DeprecatedOptionNoCode",option); goto next_argument; } - if ( (option_type & GenesisOptionFlag) != 0 ) { - goto next_argument; /* ignore MagickCommandGenesis() Only Option */ - } - if (((option_type & ImageRequiredFlags) != 0 ) && - ( cli_wand->wand.images == (Image *)NULL ) ) { - CLIWandException(OptionError,"NoImagesFound",option); + + /* Ignore MagickCommandGenesis() only option on CLI */ + if ( (option_type & GenesisOptionFlag) != 0 ) goto next_argument; - } if ( (option_type & SpecialOptionFlag) != 0 ) { if ( (cli_wand->process_flags & ProcessExitOption) != 0 @@ -540,8 +543,20 @@ WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, CLISettingOptionInfo(cli_wand, option, arg1, arg2); // FUTURE: Sync individual Settings into images (no SyncImageSettings()) } - if ( cli_wand->wand.images != (Image *)NULL ) - SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images, + + /* FUTURE: The not a setting part below is a temporary hack to stop gap + * measure for options that are BOTH settings and optional 'Simple/List' + * operators. Specifically -monitor and -colorspace */ + if ( cli_wand->wand.images == (Image *)NULL ) { + if (((option_type & ImageRequiredFlags) != 0 ) && + ((option_type & SettingOptionFlags) == 0 ) ) /* temp hack */ + CLIWandException(OptionError,"NoImagesFound",option); + goto next_argument; + } + + /* FUTURE: this is temporary - get 'settings' to handle + distribution of settings to images attributes,proprieties,artifacts */ + SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images, cli_wand->wand.exception); if ( (option_type & SimpleOperatorOptionFlag) != 0) diff --git a/MagickWand/operation.c b/MagickWand/operation.c index 6e12e1421..f587b6cf7 100644 --- a/MagickWand/operation.c +++ b/MagickWand/operation.c @@ -65,6 +65,9 @@ #define MAX_STACK_DEPTH 32 #define UNDEFINED_COMPRESSION_QUALITY 0UL +/* FUTURE: why is this default so specific? */ +#define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154" + /* Constant declaration. (temporary exports) */ @@ -148,29 +151,6 @@ static inline Image *GetImageCache(const ImageInfo *image_info,const char *path, return(image); } -#if 0 -/* - FloatListOption() converts a string option of space or comma seperated - numbers into a list of floating point numbers, required by some operations. -*/ -static MagickBooleanType FloatListOption(const char *option, - size_t *number_arguments, double **arguments, ExceptionInfo *exception) -{ - char - token[MaxTextExtent]; - - const char - *p; - - MagickBooleanType - error; - - register size_t - x; - -} -#endif - /* SparseColorOption() parse the complex -sparse-color argument into an an array of floating point values than call SparseColorImage(). @@ -217,7 +197,8 @@ static Image *SparseColorOption(const Image *image, assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); /* - Limit channels according to image - and add up number of color channel. + Limit channels according to image + add up number of values needed per color. */ number_colors=0; if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) @@ -767,6 +748,16 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand, (void) SetImageOption(_image_info,option+1,ArgOption("undefined")); break; } + if (LocaleCompare("dissimilarity-threshold",option+1) == 0) + { + /* FUTURE: this is only used by CompareImages() which is used + only by the "compare" CLI program at this time. */ + arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD); + if (IfMagickFalse(IsGeometry(arg1))) + CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); + (void) SetImageOption(_image_info,option+1,arg1); + break; + } if (LocaleCompare("dither",option+1) == 0) { /* _image_info attr (on/off), _quantize_info attr (on/off) @@ -928,6 +919,17 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand, } CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); } + case 'h': + { + if (LocaleCompare("highlight-color",option+1) == 0) + { + /* FUTURE: this is only used by CompareImages() which is used + only by the "compare" CLI program at this time. */ + (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); + break; + } + CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); + } case 'i': { if (LocaleCompare("intent",option+1) == 0) @@ -1034,6 +1036,8 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand, } if (LocaleCompare("lowlight-color",option+1) == 0) { + /* FUTURE: this is only used by CompareImages() which is used + only by the "compare" CLI program at this time. */ (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); break; } @@ -1057,6 +1061,16 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand, (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance, &_image_info->matte_color,_exception); break; + } + if (LocaleCompare("metric",option+1) == 0) + { + /* FUTURE: this is only used by CompareImages() which is used + only by the "compare" CLI program at this time. */ + parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1); + if ( parse < 0 ) + CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType", + option,arg1); + (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); } if (LocaleCompare("monitor",option+1) == 0) { @@ -1350,6 +1364,13 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand, _draw_info->style=(StyleType) parse; break; } + if (LocaleCompare("subimage-search",option+1) == 0) + { + /* FUTURE: this is only used by CompareImages() which is used + only by the "compare" CLI program at this time. */ + (void) SetImageOption(_image_info,option+1,ArgBooleanString); + break; + } if (LocaleCompare("synchronize",option+1) == 0) { /* FUTURE: syncronize to storage - but what does that mean? */ @@ -2152,20 +2173,13 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, if (LocaleCompare("distort",option+1) == 0) { char - *args, - token[MaxTextExtent]; - - const char - *p; + *arg; double - *arguments; - - register ssize_t - x; + *args; - size_t - number_arguments; + ssize_t + count; parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1); if ( parse < 0 ) @@ -2189,42 +2203,19 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, (size_t)2,resize_args,MagickTrue,_exception); break; } - /* handle percent arguments */ - args=InterpretImageProperties(_image_info,_image,arg2,_exception); - if (args == (char *) NULL) + /* allow percent escapes in argument string */ + arg=InterpretImageProperties(_image_info,_image,arg2,_exception); + if (arg == (char *) NULL) break; - /* convert arguments into an array of doubles - FUTURE: make this a separate function. - Also make use of new 'sentinal' feature to avoid need for - tokenization. - */ - p=(char *) args; - for (x=0; *p != '\0'; x++) - { - GetMagickToken(p,&p,token); - if (*token == ',') - GetMagickToken(p,&p,token); - } - number_arguments=(size_t) x; - arguments=(double *) AcquireQuantumMemory(number_arguments, - sizeof(*arguments)); - if (arguments == (double *) NULL) - CLIWandExceptionBreak(ResourceLimitFatalError, - "MemoryAllocationFailed",option); - (void) ResetMagickMemory(arguments,0,number_arguments* - sizeof(*arguments)); - p=(char *) args; - for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++) - { - GetMagickToken(p,&p,token); - if (*token == ',') - GetMagickToken(p,&p,token); - arguments[x]=StringToDouble(token,(char **) NULL); - } - args=DestroyString(args); - new_image=DistortImage(_image,(DistortImageMethod) parse, - number_arguments,arguments,plus_alt_op,_exception); - arguments=(double *) RelinquishMagickMemory(arguments); + /* convert argument string into an array of doubles */ + args = StringToArrayOfDoubles(arg,&count,_exception); + arg=DestroyString(arg); + if (args == (double *)NULL ) + CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2); + + new_image=DistortImage(_image,(DistortImageMethod) parse,count,args, + plus_alt_op,_exception); + args=(double *) RelinquishMagickMemory(args); break; } if (LocaleCompare("draw",option+1) == 0) @@ -2386,59 +2377,31 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, if (LocaleCompare("function",option+1) == 0) { char - *arguments, - token[MaxTextExtent]; - - const char - *p; + *arg; double - *parameters; + *args; - register ssize_t - x; - - size_t - number_parameters; + ssize_t + count; - /* - Function Modify Image Values - FUTURE: code should be almost a duplicate of that is "distort" - */ parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1); if ( parse < 0 ) CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction", option,arg1); - arguments=InterpretImageProperties(_image_info,_image,arg2, - _exception); - if (arguments == (char *) NULL) - CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2); - p=(char *) arguments; - for (x=0; *p != '\0'; x++) - { - GetMagickToken(p,&p,token); - if (*token == ',') - GetMagickToken(p,&p,token); - } - number_parameters=(size_t) x; - parameters=(double *) AcquireQuantumMemory(number_parameters, - sizeof(*parameters)); - if (parameters == (double *) NULL) - ThrowWandFatalException(ResourceLimitFatalError, - "MemoryAllocationFailed",_image->filename); - (void) ResetMagickMemory(parameters,0,number_parameters* - sizeof(*parameters)); - p=(char *) arguments; - for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) { - GetMagickToken(p,&p,token); - if (*token == ',') - GetMagickToken(p,&p,token); - parameters[x]=StringToDouble(token,(char **) NULL); - } - arguments=DestroyString(arguments); - (void) FunctionImage(_image,(MagickFunction)parse,number_parameters, - parameters,_exception); - parameters=(double *) RelinquishMagickMemory(parameters); + /* allow percent escapes in argument string */ + arg=InterpretImageProperties(_image_info,_image,arg2,_exception); + if (arg == (char *) NULL) + break; + /* convert argument string into an array of doubles */ + args = StringToArrayOfDoubles(arg,&count,_exception); + arg=DestroyString(arg); + if (args == (double *)NULL ) + CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2); + + (void) FunctionImage(_image,(MagickFunction)parse,count,args, + _exception); + args=(double *) RelinquishMagickMemory(args); break; } CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); @@ -2498,15 +2461,6 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, } CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); } - case 'h': - { - if (LocaleCompare("highlight-color",option+1) == 0) - { - (void) SetImageArtifact(_image,option+1,arg1); - break; - } - CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); - } case 'i': { if (LocaleCompare("identify",option+1) == 0) @@ -3237,8 +3191,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/ 100.0; (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho, - geometry_info.sigma, - _exception); + geometry_info.sigma,_exception); break; } if (LocaleCompare("sketch",option+1) == 0) @@ -4102,6 +4055,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand, } if (LocaleCompare("process",option+1) == 0) { + /* FUTURE: better parsing using ScriptToken() from string ??? */ char **arguments; diff --git a/MagickWand/wandcli-private.h b/MagickWand/wandcli-private.h index 4b9618bb4..b0d350b44 100644 --- a/MagickWand/wandcli-private.h +++ b/MagickWand/wandcli-private.h @@ -33,7 +33,7 @@ extern "C" { #define CLIWandWarnDepreciated(message) \ if ( (cli_wand->process_flags & ProcessWarnDepreciated) != 0 ) \ (void) CLIThrowException(cli_wand,GetMagickModule(),OptionWarning, \ - "DeprecatedOption", "'%s' use \"%s\" instead",option,message) + "DeprecatedOption", "'%s', use \"%s\"",option,message) #define CLIWandExceptionFile(severity,tag,context) \ { char *message=GetExceptionMessage(errno); \ diff --git a/config/english.xml b/config/english.xml index 7e075fba3..4ff958b16 100644 --- a/config/english.xml +++ b/config/english.xml @@ -622,6 +622,9 @@ invalid image index + + invalid list of numbers + images are not the same size diff --git a/config/francais.xml b/config/francais.xml index b28612143..241798f4c 100644 --- a/config/francais.xml +++ b/config/francais.xml @@ -616,6 +616,9 @@ index de l'image non valide + + liste des numéros non valide + images diffèrent par la taille