|
MagickWand
6.7.7
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % OOO PPPP EEEE RRRR AA TTTTT III OOO N N % 00007 % O O P P E R R A A T I O O NN N % 00008 % O O PPPP EEE RRRR AAAA T I O O N N N % 00009 % O O P E R R A A T I O O N NN % 00010 % OOO P EEEE R RR A A T III OOO N N % 00011 % % 00012 % % 00013 % CLI Magick Option Methods % 00014 % % 00015 % Dragon Computing % 00016 % Anthony Thyssen % 00017 % September 2011 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % Apply the given options (settings, and simple, or sequence operations) to 00037 % the given image(s) according to the current "image_info", "draw_info", and 00038 % "quantize_info" settings, stored in a special CLI Image Wand. 00039 % 00040 % The final goal is to allow the execution in a strict one option at a time 00041 % manner that is needed for 'pipelining and file scripting' of options in 00042 % IMv7. 00043 % 00044 % Anthony Thyssen, September 2011 00045 */ 00046 00047 /* 00048 Include declarations. 00049 */ 00050 #include "MagickWand/studio.h" 00051 #include "MagickWand/MagickWand.h" 00052 #include "MagickWand/magick-wand-private.h" 00053 #include "MagickWand/wand.h" 00054 #include "MagickWand/wandcli.h" 00055 #include "MagickWand/wandcli-private.h" 00056 #include "MagickWand/operation.h" 00057 #include "MagickCore/monitor-private.h" 00058 #include "MagickCore/thread-private.h" 00059 #include "MagickCore/string-private.h" 00060 00061 /* 00062 Define declarations. 00063 */ 00064 #define USE_WAND_METHODS 0 00065 #define MAX_STACK_DEPTH 32 00066 #define UNDEFINED_COMPRESSION_QUALITY 0UL 00067 00068 /* FUTURE: why is this default so specific? */ 00069 #define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154" 00070 00071 /* 00072 Constant declaration. (temporary exports) 00073 */ 00074 static const char 00075 BackgroundColor[] = "#fff", /* white */ 00076 BorderColor[] = "#dfdfdf", /* sRGB gray */ 00077 MatteColor[] = "#bdbdbd"; /* slightly darker gray */ 00078 00079 /* For Debugging Geometry Input */ 00080 #define ReportGeometry(flags,info) \ 00081 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \ 00082 flags, info.rho, info.sigma, info.xi, info.psi ) 00083 00084 /* 00085 ** Function to report on the progress of image operations 00086 */ 00087 static MagickBooleanType MonitorProgress(const char *text, 00088 const MagickOffsetType offset,const MagickSizeType extent, 00089 void *wand_unused(cli_wandent_data)) 00090 { 00091 char 00092 message[MaxTextExtent], 00093 tag[MaxTextExtent]; 00094 00095 const char 00096 *locale_message; 00097 00098 register char 00099 *p; 00100 00101 if (extent < 2) 00102 return(MagickTrue); 00103 (void) CopyMagickMemory(tag,text,MaxTextExtent); 00104 p=strrchr(tag,'/'); 00105 if (p != (char *) NULL) 00106 *p='\0'; 00107 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag); 00108 locale_message=GetLocaleMessage(message); 00109 if (locale_message == message) 00110 locale_message=tag; 00111 if (p == (char *) NULL) 00112 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r", 00113 locale_message,(long) offset,(unsigned long) extent,(long) 00114 (100L*offset/(extent-1))); 00115 else 00116 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r", 00117 locale_message,p+1,(long) offset,(unsigned long) extent,(long) 00118 (100L*offset/(extent-1))); 00119 if (offset == (MagickOffsetType) (extent-1)) 00120 (void) FormatLocaleFile(stderr,"\n"); 00121 (void) fflush(stderr); 00122 return(MagickTrue); 00123 } 00124 00125 /* 00126 ** GetImageCache() will read an image into a image cache if not already 00127 ** present then return the image that is in the cache under that filename. 00128 */ 00129 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path, 00130 ExceptionInfo *exception) 00131 { 00132 char 00133 key[MaxTextExtent]; 00134 00135 ExceptionInfo 00136 *sans_exception; 00137 00138 Image 00139 *image; 00140 00141 ImageInfo 00142 *read_info; 00143 00144 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path); 00145 sans_exception=AcquireExceptionInfo(); 00146 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception); 00147 sans_exception=DestroyExceptionInfo(sans_exception); 00148 if (image != (Image *) NULL) 00149 return(image); 00150 read_info=CloneImageInfo(image_info); 00151 (void) CopyMagickString(read_info->filename,path,MaxTextExtent); 00152 image=ReadImage(read_info,exception); 00153 read_info=DestroyImageInfo(read_info); 00154 if (image != (Image *) NULL) 00155 (void) SetImageRegistry(ImageRegistryType,key,image,exception); 00156 return(image); 00157 } 00158 00159 /* 00160 SparseColorOption() parse the complex -sparse-color argument into an 00161 an array of floating point values than call SparseColorImage(). 00162 Argument is a complex mix of floating-point pixel coodinates, and color 00163 specifications (or direct floating point numbers). The number of floats 00164 needed to represent a color varies depending on teh current channel 00165 setting. 00166 00167 This really should be in MagickCore, so that other API's can make use of it. 00168 */ 00169 static Image *SparseColorOption(const Image *image, 00170 const SparseColorMethod method,const char *arguments, 00171 ExceptionInfo *exception) 00172 { 00173 char 00174 token[MaxTextExtent]; 00175 00176 const char 00177 *p; 00178 00179 double 00180 *sparse_arguments; 00181 00182 Image 00183 *sparse_image; 00184 00185 PixelInfo 00186 color; 00187 00188 MagickBooleanType 00189 error; 00190 00191 register size_t 00192 x; 00193 00194 size_t 00195 number_arguments, 00196 number_colors; 00197 00198 assert(image != (Image *) NULL); 00199 assert(image->signature == MagickSignature); 00200 if (IfMagickTrue(image->debug)) 00201 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00202 assert(exception != (ExceptionInfo *) NULL); 00203 assert(exception->signature == MagickSignature); 00204 /* 00205 Limit channels according to image 00206 add up number of values needed per color. 00207 */ 00208 number_colors=0; 00209 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) 00210 number_colors++; 00211 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) 00212 number_colors++; 00213 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) 00214 number_colors++; 00215 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) && 00216 (image->colorspace == CMYKColorspace)) 00217 number_colors++; 00218 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) && 00219 IfMagickTrue(image->matte)) 00220 number_colors++; 00221 00222 /* 00223 Read string, to determine number of arguments needed, 00224 */ 00225 p=arguments; 00226 x=0; 00227 while( *p != '\0' ) 00228 { 00229 GetMagickToken(p,&p,token); 00230 if ( token[0] == ',' ) continue; 00231 if ( isalpha((int) token[0]) || token[0] == '#' ) 00232 x += number_colors; /* color argument found */ 00233 else 00234 x++; /* floating point argument */ 00235 } 00236 /* control points and color values */ 00237 error = IsMagickTrue( x % (2+number_colors) ); 00238 number_arguments=x; 00239 if ( IfMagickTrue(error) ) { 00240 (void) ThrowMagickException(exception,GetMagickModule(), 00241 OptionError, "InvalidArgument", "'%s': %s", "sparse-color", 00242 "Invalid number of Arguments"); 00243 return( (Image *)NULL); 00244 } 00245 00246 /* Allocate and fill in the floating point arguments */ 00247 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments, 00248 sizeof(*sparse_arguments)); 00249 if (sparse_arguments == (double *) NULL) { 00250 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError, 00251 "MemoryAllocationFailed","%s","SparseColorOption"); 00252 return( (Image *)NULL); 00253 } 00254 (void) ResetMagickMemory(sparse_arguments,0,number_arguments* 00255 sizeof(*sparse_arguments)); 00256 p=arguments; 00257 x=0; 00258 while( *p != '\0' && x < number_arguments ) { 00259 /* X coordinate */ 00260 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token); 00261 if ( token[0] == '\0' ) break; 00262 if ( isalpha((int) token[0]) || token[0] == '#' ) { 00263 (void) ThrowMagickException(exception,GetMagickModule(), 00264 OptionError, "InvalidArgument", "'%s': %s", "sparse-color", 00265 "Color found, instead of X-coord"); 00266 error = MagickTrue; 00267 break; 00268 } 00269 sparse_arguments[x++]=StringToDouble(token,(char **) NULL); 00270 /* Y coordinate */ 00271 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token); 00272 if ( token[0] == '\0' ) break; 00273 if ( isalpha((int) token[0]) || token[0] == '#' ) { 00274 (void) ThrowMagickException(exception,GetMagickModule(), 00275 OptionError, "InvalidArgument", "'%s': %s", "sparse-color", 00276 "Color found, instead of Y-coord"); 00277 error = MagickTrue; 00278 break; 00279 } 00280 sparse_arguments[x++]=StringToDouble(token,(char **) NULL); 00281 /* color name or function given in string argument */ 00282 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token); 00283 if ( token[0] == '\0' ) break; 00284 if ( isalpha((int) token[0]) || token[0] == '#' ) { 00285 /* Color string given */ 00286 (void) QueryColorCompliance(token,AllCompliance,&color, 00287 exception); 00288 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) 00289 sparse_arguments[x++] = QuantumScale*color.red; 00290 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) 00291 sparse_arguments[x++] = QuantumScale*color.green; 00292 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) 00293 sparse_arguments[x++] = QuantumScale*color.blue; 00294 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) && 00295 (image->colorspace == CMYKColorspace)) 00296 sparse_arguments[x++] = QuantumScale*color.black; 00297 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) && 00298 IfMagickTrue(image->matte)) 00299 sparse_arguments[x++] = QuantumScale*color.alpha; 00300 } 00301 else { 00302 /* Colors given as a set of floating point values - experimental */ 00303 /* NB: token contains the first floating point value to use! */ 00304 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) 00305 { 00306 while ( token[0] == ',' ) GetMagickToken(p,&p,token); 00307 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' ) 00308 break; 00309 sparse_arguments[x++]=StringToDouble(token,(char **) NULL); 00310 token[0] = ','; /* used this token - get another */ 00311 } 00312 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) 00313 { 00314 while ( token[0] == ',' ) GetMagickToken(p,&p,token); 00315 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' ) 00316 break; 00317 sparse_arguments[x++]=StringToDouble(token,(char **) NULL); 00318 token[0] = ','; /* used this token - get another */ 00319 } 00320 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) 00321 { 00322 while ( token[0] == ',' ) GetMagickToken(p,&p,token); 00323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' ) 00324 break; 00325 sparse_arguments[x++]=StringToDouble(token,(char **) NULL); 00326 token[0] = ','; /* used this token - get another */ 00327 } 00328 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) && 00329 (image->colorspace == CMYKColorspace)) 00330 { 00331 while ( token[0] == ',' ) GetMagickToken(p,&p,token); 00332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' ) 00333 break; 00334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL); 00335 token[0] = ','; /* used this token - get another */ 00336 } 00337 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) && 00338 IfMagickTrue(image->matte)) 00339 { 00340 while ( token[0] == ',' ) GetMagickToken(p,&p,token); 00341 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' ) 00342 break; 00343 sparse_arguments[x++]=StringToDouble(token,(char **) NULL); 00344 token[0] = ','; /* used this token - get another */ 00345 } 00346 } 00347 } 00348 if ( number_arguments != x && !error ) { 00349 (void) ThrowMagickException(exception,GetMagickModule(),OptionError, 00350 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error"); 00351 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments); 00352 return( (Image *)NULL); 00353 } 00354 if ( error ) 00355 return( (Image *)NULL); 00356 00357 /* Call the Sparse Color Interpolation function with the parsed arguments */ 00358 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments, 00359 exception); 00360 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments); 00361 return( sparse_image ); 00362 } 00363 00364 /* 00365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00366 % % 00367 % % 00368 % % 00369 % C L I S e t t i n g O p t i o n I n f o % 00370 % % 00371 % % 00372 % % 00373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00374 % 00375 % CLISettingOptionInfo() applies a single settings option into a CLI wand 00376 % holding the image_info, draw_info, quantize_info structures that will be 00377 % used when processing the images. 00378 % 00379 % These options do no require images to be present in the CLI wand for them 00380 % to be able to be set, in which case they will generally be applied to image 00381 % that are read in later 00382 % 00383 % Options handled by this function are listed in CommandOptions[] of 00384 % "option.c" that is one of "SettingOptionFlags" option flags. 00385 % 00386 % The format of the CLISettingOptionInfo method is: 00387 % 00388 % void CLISettingOptionInfo(MagickCLI *cli_wand, 00389 % const char *option, const char *arg1, const char *arg2) 00390 % 00391 % A description of each parameter follows: 00392 % 00393 % o cli_wand: structure holding settings to be applied 00394 % 00395 % o option: The option string to be set 00396 % 00397 % o arg1, arg2: optional argument strings to the operation 00398 % arg2 is currently only used by "-limit" 00399 % 00400 */ 00401 WandExport void CLISettingOptionInfo(MagickCLI *cli_wand, 00402 const char *option,const char *arg1, const char *arg2) 00403 { 00404 ssize_t 00405 parse; /* option argument parsing (string to value table lookup) */ 00406 00407 assert(cli_wand != (MagickCLI *) NULL); 00408 assert(cli_wand->signature == WandSignature); 00409 assert(cli_wand->wand.signature == WandSignature); 00410 if (IfMagickTrue(cli_wand->wand.debug)) 00411 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); 00412 00413 #define _image_info (cli_wand->wand.image_info) 00414 #define _exception (cli_wand->wand.exception) 00415 #define _draw_info (cli_wand->draw_info) 00416 #define _quantize_info (cli_wand->quantize_info) 00417 #define IfSetOption (*option=='-') 00418 #define ArgBoolean IsMagickTrue(IfSetOption) 00419 #define ArgBooleanNot IsMagickFalse(IfSetOption) 00420 #define ArgBooleanString (IfSetOption?"true":"false") 00421 #define ArgOption(def) (IfSetOption?arg1:(const char *)(def)) 00422 00423 switch (*(option+1)) 00424 { 00425 case 'a': 00426 { 00427 if (LocaleCompare("adjoin",option+1) == 0) 00428 { 00429 _image_info->adjoin = ArgBoolean; 00430 break; 00431 } 00432 if (LocaleCompare("affine",option+1) == 0) 00433 { 00434 CLIWandWarnReplaced("-draw 'affine ...'"); 00435 if (IfSetOption) 00436 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception); 00437 else 00438 GetAffineMatrix(&_draw_info->affine); 00439 break; 00440 } 00441 if (LocaleCompare("antialias",option+1) == 0) 00442 { 00443 _image_info->antialias = 00444 _draw_info->stroke_antialias = 00445 _draw_info->text_antialias = ArgBoolean; 00446 break; 00447 } 00448 if (LocaleCompare("attenuate",option+1) == 0) 00449 { 00450 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 00451 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00452 (void) SetImageOption(_image_info,option+1,ArgOption("1.0")); 00453 break; 00454 } 00455 if (LocaleCompare("authenticate",option+1) == 0) 00456 { 00457 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00458 break; 00459 } 00460 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00461 } 00462 case 'b': 00463 { 00464 if (LocaleCompare("background",option+1) == 0) 00465 { 00466 /* FUTURE: both _image_info attribute & ImageOption in use! 00467 _image_info only used directly for generating new images. 00468 SyncImageSettings() used to set per-image attribute. 00469 00470 FUTURE: if _image_info->background_color is not set then 00471 we should fall back to per-image background_color 00472 00473 At this time -background will 'wipe out' the per-image 00474 background color! 00475 00476 Better error handling of QueryColorCompliance() needed. 00477 */ 00478 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00479 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance, 00480 &_image_info->background_color,_exception); 00481 break; 00482 } 00483 if (LocaleCompare("bias",option+1) == 0) 00484 { 00485 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias" 00486 as it is actually rarely used except in direct convolve operations 00487 Usage outside a direct convolve operation is actally non-sensible! 00488 00489 SyncImageSettings() used to set per-image attribute. 00490 */ 00491 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 00492 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00493 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL)); 00494 break; 00495 } 00496 if (LocaleCompare("black-point-compensation",option+1) == 0) 00497 { 00498 /* Used as a image chromaticity setting 00499 SyncImageSettings() used to set per-image attribute. 00500 */ 00501 (void) SetImageOption(_image_info,option+1,ArgBooleanString); 00502 break; 00503 } 00504 if (LocaleCompare("blue-primary",option+1) == 0) 00505 { 00506 /* Image chromaticity X,Y NB: Y=X if Y not defined 00507 Used by many coders including PNG 00508 SyncImageSettings() used to set per-image attribute. 00509 */ 00510 arg1=ArgOption("0.0"); 00511 if (IfMagickFalse(IsGeometry(arg1))) 00512 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00513 (void) SetImageOption(_image_info,option+1,arg1); 00514 break; 00515 } 00516 if (LocaleCompare("bordercolor",option+1) == 0) 00517 { 00518 /* FUTURE: both _image_info attribute & ImageOption in use! 00519 SyncImageSettings() used to set per-image attribute. 00520 Better error checking of QueryColorCompliance(). 00521 */ 00522 if (IfSetOption) 00523 { 00524 (void) SetImageOption(_image_info,option+1,arg1); 00525 (void) QueryColorCompliance(arg1,AllCompliance, 00526 &_image_info->border_color,_exception); 00527 (void) QueryColorCompliance(arg1,AllCompliance, 00528 &_draw_info->border_color,_exception); 00529 break; 00530 } 00531 (void) DeleteImageOption(_image_info,option+1); 00532 (void) QueryColorCompliance(BorderColor,AllCompliance, 00533 &_image_info->border_color,_exception); 00534 (void) QueryColorCompliance(BorderColor,AllCompliance, 00535 &_draw_info->border_color,_exception); 00536 break; 00537 } 00538 if (LocaleCompare("box",option+1) == 0) 00539 { 00540 CLIWandWarnReplaced("-undercolor"); 00541 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2); 00542 break; 00543 } 00544 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00545 } 00546 case 'c': 00547 { 00548 if (LocaleCompare("cache",option+1) == 0) 00549 { 00550 MagickSizeType 00551 limit; 00552 00553 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 00554 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00555 limit=MagickResourceInfinity; 00556 if (LocaleCompare("unlimited",arg1) != 0) 00557 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0); 00558 (void) SetMagickResourceLimit(MemoryResource,limit); 00559 (void) SetMagickResourceLimit(MapResource,2*limit); 00560 break; 00561 } 00562 if (LocaleCompare("caption",option+1) == 0) 00563 { 00564 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00565 break; 00566 } 00567 if (LocaleCompare("channel",option+1) == 0) 00568 { 00569 arg1=ArgOption("default"); 00570 parse=ParseChannelOption(arg1); 00571 if (parse < 0) 00572 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType", 00573 option,arg1); 00574 _image_info->channel=(ChannelType) parse; 00575 (void) SetImageOption(_image_info,option+1,arg1); 00576 break; 00577 } 00578 if (LocaleCompare("colorspace",option+1) == 0) 00579 { 00580 /* Setting used for new images via AquireImage() 00581 But also used as a SimpleImageOperator 00582 Undefined colorspace means don't modify images on 00583 read or as a operation */ 00584 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse, 00585 ArgOption("undefined")); 00586 if (parse < 0) 00587 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace", 00588 option,arg1); 00589 _image_info->colorspace=(ColorspaceType) parse; 00590 break; 00591 } 00592 if (LocaleCompare("comment",option+1) == 0) 00593 { 00594 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00595 break; 00596 } 00597 if (LocaleCompare("compose",option+1) == 0) 00598 { 00599 /* FUTURE: _image_info should be used, 00600 SyncImageSettings() used to set per-image attribute. - REMOVE 00601 00602 This setting should NOT be used to set image 'compose' 00603 "-layer" operators shoud use _image_info if defined otherwise 00604 they should use a per-image compose setting. 00605 */ 00606 parse = ParseCommandOption(MagickComposeOptions,MagickFalse, 00607 ArgOption("undefined")); 00608 if (parse < 0) 00609 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator", 00610 option,arg1); 00611 _image_info->compose=(CompositeOperator) parse; 00612 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00613 break; 00614 } 00615 if (LocaleCompare("compress",option+1) == 0) 00616 { 00617 /* FUTURE: What should be used? _image_info or ImageOption ??? 00618 The former is more efficent, but Crisy prefers the latter! 00619 SyncImageSettings() used to set per-image attribute. 00620 00621 The coders appears to use _image_info, not Image_Option 00622 however the image attribute (for save) is set from the 00623 ImageOption! 00624 00625 Note that "undefined" is a different setting to "none". 00626 */ 00627 parse = ParseCommandOption(MagickCompressOptions,MagickFalse, 00628 ArgOption("undefined")); 00629 if (parse < 0) 00630 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression", 00631 option,arg1); 00632 _image_info->compression=(CompressionType) parse; 00633 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00634 break; 00635 } 00636 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00637 } 00638 case 'd': 00639 { 00640 if (LocaleCompare("debug",option+1) == 0) 00641 { 00642 /* SyncImageSettings() used to set per-image attribute. */ 00643 arg1=ArgOption("none"); 00644 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1); 00645 if (parse < 0) 00646 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType", 00647 option,arg1); 00648 (void) SetLogEventMask(arg1); 00649 _image_info->debug=IsEventLogging(); /* extract logging*/ 00650 cli_wand->wand.debug=IsEventLogging(); 00651 break; 00652 } 00653 if (LocaleCompare("define",option+1) == 0) 00654 { 00655 if (LocaleNCompare(arg1,"registry:",9) == 0) 00656 { 00657 if (IfSetOption) 00658 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception); 00659 else 00660 (void) DeleteImageRegistry(arg1+9); 00661 break; 00662 } 00663 /* DefineImageOption() equals SetImageOption() but with '=' */ 00664 if (IfSetOption) 00665 (void) DefineImageOption(_image_info,arg1); 00666 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1))) 00667 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1); 00668 break; 00669 } 00670 if (LocaleCompare("delay",option+1) == 0) 00671 { 00672 /* Only used for new images via AcquireImage() 00673 FUTURE: Option should also be used for "-morph" (color morphing) 00674 */ 00675 arg1=ArgOption("0"); 00676 if (IfMagickFalse(IsGeometry(arg1))) 00677 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00678 (void) SetImageOption(_image_info,option+1,arg1); 00679 break; 00680 } 00681 if (LocaleCompare("density",option+1) == 0) 00682 { 00683 /* FUTURE: strings used in _image_info attr and _draw_info! 00684 Basically as density can be in a XxY form! 00685 00686 SyncImageSettings() used to set per-image attribute. 00687 */ 00688 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 00689 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00690 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00691 (void) CloneString(&_image_info->density,ArgOption(NULL)); 00692 (void) CloneString(&_draw_info->density,_image_info->density); 00693 break; 00694 } 00695 if (LocaleCompare("depth",option+1) == 0) 00696 { 00697 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!! 00698 SyncImageSettings() used to set per-image attribute. 00699 */ 00700 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 00701 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00702 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1) 00703 :MAGICKCORE_QUANTUM_DEPTH; 00704 break; 00705 } 00706 if (LocaleCompare("direction",option+1) == 0) 00707 { 00708 /* Image Option is only used to set _draw_info */ 00709 arg1=ArgOption("undefined"); 00710 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1); 00711 if (parse < 0) 00712 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType", 00713 option,arg1); 00714 _draw_info->direction=(DirectionType) parse; 00715 (void) SetImageOption(_image_info,option+1,arg1); 00716 break; 00717 } 00718 if (LocaleCompare("display",option+1) == 0) 00719 { 00720 (void) CloneString(&_image_info->server_name,ArgOption(NULL)); 00721 (void) CloneString(&_draw_info->server_name,_image_info->server_name); 00722 break; 00723 } 00724 if (LocaleCompare("dispose",option+1) == 0) 00725 { 00726 /* only used in setting new images */ 00727 arg1=ArgOption("undefined"); 00728 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1); 00729 if (parse < 0) 00730 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod", 00731 option,arg1); 00732 (void) SetImageOption(_image_info,option+1,ArgOption("undefined")); 00733 break; 00734 } 00735 if (LocaleCompare("dissimilarity-threshold",option+1) == 0) 00736 { 00737 /* FUTURE: this is only used by CompareImages() which is used 00738 only by the "compare" CLI program at this time. */ 00739 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD); 00740 if (IfMagickFalse(IsGeometry(arg1))) 00741 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00742 (void) SetImageOption(_image_info,option+1,arg1); 00743 break; 00744 } 00745 if (LocaleCompare("dither",option+1) == 0) 00746 { 00747 /* _image_info attr (on/off), _quantize_info attr (on/off) 00748 but also ImageInfo and _quantize_info method! 00749 FUTURE: merge the duality of the dithering options 00750 */ 00751 _image_info->dither = _quantize_info->dither = ArgBoolean; 00752 (void) SetImageOption(_image_info,option+1,ArgOption("none")); 00753 _quantize_info->dither_method=(DitherMethod) ParseCommandOption( 00754 MagickDitherOptions,MagickFalse,ArgOption("none")); 00755 if (_quantize_info->dither_method == NoDitherMethod) 00756 _image_info->dither = _quantize_info->dither = MagickFalse; 00757 break; 00758 } 00759 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00760 } 00761 case 'e': 00762 { 00763 if (LocaleCompare("encoding",option+1) == 0) 00764 { 00765 (void) CloneString(&_draw_info->encoding,ArgOption("undefined")); 00766 (void) SetImageOption(_image_info,option+1,_draw_info->encoding); 00767 break; 00768 } 00769 if (LocaleCompare("endian",option+1) == 0) 00770 { 00771 /* Both _image_info attr and ImageInfo */ 00772 arg1 = ArgOption("undefined"); 00773 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1); 00774 if (parse < 0) 00775 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType", 00776 option,arg1); 00777 /* FUTURE: check alloc/free of endian string! - remove? */ 00778 _image_info->endian=(EndianType) (*arg1); 00779 (void) SetImageOption(_image_info,option+1,arg1); 00780 break; 00781 } 00782 if (LocaleCompare("extract",option+1) == 0) 00783 { 00784 (void) CloneString(&_image_info->extract,ArgOption(NULL)); 00785 break; 00786 } 00787 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00788 } 00789 case 'f': 00790 { 00791 if (LocaleCompare("family",option+1) == 0) 00792 { 00793 (void) CloneString(&_draw_info->family,ArgOption(NULL)); 00794 break; 00795 } 00796 if (LocaleCompare("fill",option+1) == 0) 00797 { 00798 /* Set "fill" OR "fill-pattern" in _draw_info 00799 The original fill color is preserved if a fill-pattern is given. 00800 That way it does not effect other operations that directly using 00801 the fill color and, can be retored using "+tile". 00802 */ 00803 MagickBooleanType 00804 status; 00805 00806 ExceptionInfo 00807 *sans; 00808 00809 PixelInfo 00810 color; 00811 00812 arg1 = ArgOption("none"); /* +fill turns it off! */ 00813 (void) SetImageOption(_image_info,option+1,arg1); 00814 if (_draw_info->fill_pattern != (Image *) NULL) 00815 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern); 00816 00817 /* is it a color or a image? -- ignore exceptions */ 00818 sans=AcquireExceptionInfo(); 00819 status=QueryColorCompliance(arg1,AllCompliance,&color,sans); 00820 sans=DestroyExceptionInfo(sans); 00821 00822 if (IfMagickFalse(status)) 00823 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception); 00824 else 00825 _draw_info->fill=color; 00826 break; 00827 } 00828 if (LocaleCompare("filter",option+1) == 0) 00829 { 00830 /* SyncImageSettings() used to set per-image attribute. */ 00831 arg1 = ArgOption("undefined"); 00832 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1); 00833 if (parse < 0) 00834 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter", 00835 option,arg1); 00836 (void) SetImageOption(_image_info,option+1,arg1); 00837 break; 00838 } 00839 if (LocaleCompare("font",option+1) == 0) 00840 { 00841 (void) CloneString(&_draw_info->font,ArgOption(NULL)); 00842 (void) CloneString(&_image_info->font,_draw_info->font); 00843 break; 00844 } 00845 if (LocaleCompare("format",option+1) == 0) 00846 { 00847 /* FUTURE: why the ping test, you could set ping after this! */ 00848 /* 00849 register const char 00850 *q; 00851 00852 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%')) 00853 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL) 00854 _image_info->ping=MagickFalse; 00855 */ 00856 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00857 break; 00858 } 00859 if (LocaleCompare("fuzz",option+1) == 0) 00860 { 00861 /* Option used to set image fuzz! unless blank canvas (from color) 00862 Image attribute used for color compare operations 00863 SyncImageSettings() used to set per-image attribute. 00864 00865 FUTURE: Can't find anything else using _image_info->fuzz directly! 00866 remove direct sttribute from image_info 00867 */ 00868 arg1=ArgOption("0"); 00869 if (IfMagickFalse(IsGeometry(arg1))) 00870 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00871 _image_info->fuzz=StringToDoubleInterval(arg1,(double) 00872 QuantumRange+1.0); 00873 (void) SetImageOption(_image_info,option+1,arg1); 00874 break; 00875 } 00876 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00877 } 00878 case 'g': 00879 { 00880 if (LocaleCompare("gravity",option+1) == 0) 00881 { 00882 /* SyncImageSettings() used to set per-image attribute. */ 00883 arg1 = ArgOption("none"); 00884 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1); 00885 if (parse < 0) 00886 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType", 00887 option,arg1); 00888 _draw_info->gravity=(GravityType) parse; 00889 (void) SetImageOption(_image_info,option+1,arg1); 00890 break; 00891 } 00892 if (LocaleCompare("green-primary",option+1) == 0) 00893 { 00894 /* Image chromaticity X,Y NB: Y=X if Y not defined 00895 SyncImageSettings() used to set per-image attribute. 00896 Used directly by many coders 00897 */ 00898 arg1=ArgOption("0.0"); 00899 if (IfMagickFalse(IsGeometry(arg1))) 00900 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00901 (void) SetImageOption(_image_info,option+1,arg1); 00902 break; 00903 } 00904 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00905 } 00906 case 'h': 00907 { 00908 if (LocaleCompare("highlight-color",option+1) == 0) 00909 { 00910 /* FUTURE: this is only used by CompareImages() which is used 00911 only by the "compare" CLI program at this time. */ 00912 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00913 break; 00914 } 00915 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00916 } 00917 case 'i': 00918 { 00919 if (LocaleCompare("intent",option+1) == 0) 00920 { 00921 /* Only used by coders: MIFF, MPC, BMP, PNG 00922 and for image profile call to AcquireTransformThreadSet() 00923 SyncImageSettings() used to set per-image attribute. 00924 */ 00925 arg1 = ArgOption("indefined"); 00926 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1); 00927 if (parse < 0) 00928 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType", 00929 option,arg1); 00930 (void) SetImageOption(_image_info,option+1,arg1); 00931 break; 00932 } 00933 if (LocaleCompare("interlace",option+1) == 0) 00934 { 00935 /* _image_info is directly used by coders (so why an image setting?) 00936 SyncImageSettings() used to set per-image attribute. 00937 */ 00938 arg1 = ArgOption("undefined"); 00939 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1); 00940 if (parse < 0) 00941 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType", 00942 option,arg1); 00943 _image_info->interlace=(InterlaceType) parse; 00944 (void) SetImageOption(_image_info,option+1,arg1); 00945 break; 00946 } 00947 if (LocaleCompare("interline-spacing",option+1) == 0) 00948 { 00949 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 00950 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00951 (void) SetImageOption(_image_info,option+1, ArgOption(NULL)); 00952 _draw_info->interline_spacing=StringToDouble(ArgOption("0"), 00953 (char **) NULL); 00954 break; 00955 } 00956 if (LocaleCompare("interpolate",option+1) == 0) 00957 { 00958 /* SyncImageSettings() used to set per-image attribute. */ 00959 arg1 = ArgOption("undefined"); 00960 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1); 00961 if (parse < 0) 00962 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod", 00963 option,arg1); 00964 (void) SetImageOption(_image_info,option+1,arg1); 00965 break; 00966 } 00967 if (LocaleCompare("interword-spacing",option+1) == 0) 00968 { 00969 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 00970 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00971 (void) SetImageOption(_image_info,option+1, ArgOption(NULL)); 00972 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL); 00973 break; 00974 } 00975 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00976 } 00977 case 'k': 00978 { 00979 if (LocaleCompare("kerning",option+1) == 0) 00980 { 00981 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 00982 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 00983 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00984 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL); 00985 break; 00986 } 00987 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 00988 } 00989 case 'l': 00990 { 00991 if (LocaleCompare("label",option+1) == 0) 00992 { 00993 /* only used for new images - not in SyncImageOptions() */ 00994 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 00995 break; 00996 } 00997 if (LocaleCompare("limit",option+1) == 0) 00998 { 00999 MagickSizeType 01000 limit; 01001 01002 limit=MagickResourceInfinity; 01003 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1); 01004 if ( parse < 0 ) 01005 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType", 01006 option,arg1); 01007 if (LocaleCompare("unlimited",arg2) != 0) 01008 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0); 01009 (void) SetMagickResourceLimit((ResourceType)parse,limit); 01010 break; 01011 } 01012 if (LocaleCompare("log",option+1) == 0) 01013 { 01014 if (IfSetOption) { 01015 if ((strchr(arg1,'%') == (char *) NULL)) 01016 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01017 (void) SetLogFormat(arg1); 01018 } 01019 break; 01020 } 01021 if (LocaleCompare("lowlight-color",option+1) == 0) 01022 { 01023 /* FUTURE: this is only used by CompareImages() which is used 01024 only by the "compare" CLI program at this time. */ 01025 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01026 break; 01027 } 01028 if (LocaleCompare("loop",option+1) == 0) 01029 { 01030 /* SyncImageSettings() used to set per-image attribute. */ 01031 arg1=ArgOption("0"); 01032 if (IfMagickFalse(IsGeometry(arg1))) 01033 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01034 (void) SetImageOption(_image_info,option+1,arg1); 01035 break; 01036 } 01037 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01038 } 01039 case 'm': 01040 { 01041 if (LocaleCompare("mattecolor",option+1) == 0) 01042 { 01043 /* SyncImageSettings() used to set per-image attribute. */ 01044 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01045 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance, 01046 &_image_info->matte_color,_exception); 01047 break; 01048 } 01049 if (LocaleCompare("metric",option+1) == 0) 01050 { 01051 /* FUTURE: this is only used by CompareImages() which is used 01052 only by the "compare" CLI program at this time. */ 01053 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1); 01054 if ( parse < 0 ) 01055 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType", 01056 option,arg1); 01057 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01058 break; 01059 } 01060 if (LocaleCompare("monitor",option+1) == 0) 01061 { 01062 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption? 01063 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL); 01064 break; 01065 } 01066 if (LocaleCompare("monochrome",option+1) == 0) 01067 { 01068 /* Setting (used by some input coders!) -- why? 01069 Warning: This is also Special '-type' SimpleOperator 01070 */ 01071 _image_info->monochrome= ArgBoolean; 01072 break; 01073 } 01074 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01075 } 01076 case 'o': 01077 { 01078 if (LocaleCompare("orient",option+1) == 0) 01079 { 01080 /* Is not used when defining for new images. 01081 This makes it more of a 'operation' than a setting 01082 FUTURE: make set meta-data operator instead. 01083 SyncImageSettings() used to set per-image attribute. 01084 */ 01085 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse, 01086 ArgOption("undefined")); 01087 if (parse < 0) 01088 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation", 01089 option,arg1); 01090 _image_info->orientation=(OrientationType)parse; 01091 (void) SetImageOption(_image_info,option+1, ArgOption(NULL)); 01092 break; 01093 } 01094 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01095 } 01096 case 'p': 01097 { 01098 if (LocaleCompare("page",option+1) == 0) 01099 { 01100 /* Only used for new images and image generators. 01101 SyncImageSettings() used to set per-image attribute. ????? 01102 That last is WRONG!!!! 01103 FUTURE: adjust named 'page' sizes according density 01104 */ 01105 char 01106 *canonical_page, 01107 page[MaxTextExtent]; 01108 01109 const char 01110 *image_option; 01111 01112 MagickStatusType 01113 flags; 01114 01115 RectangleInfo 01116 geometry; 01117 01118 if (!IfSetOption) 01119 { 01120 (void) DeleteImageOption(_image_info,option+1); 01121 (void) CloneString(&_image_info->page,(char *) NULL); 01122 break; 01123 } 01124 (void) ResetMagickMemory(&geometry,0,sizeof(geometry)); 01125 image_option=GetImageOption(_image_info,"page"); 01126 if (image_option != (const char *) NULL) 01127 flags=ParseAbsoluteGeometry(image_option,&geometry); 01128 canonical_page=GetPageGeometry(arg1); 01129 flags=ParseAbsoluteGeometry(canonical_page,&geometry); 01130 canonical_page=DestroyString(canonical_page); 01131 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu", 01132 (unsigned long) geometry.width,(unsigned long) geometry.height); 01133 if (((flags & XValue) != 0) || ((flags & YValue) != 0)) 01134 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld", 01135 (unsigned long) geometry.width,(unsigned long) geometry.height, 01136 (long) geometry.x,(long) geometry.y); 01137 (void) SetImageOption(_image_info,option+1,page); 01138 (void) CloneString(&_image_info->page,page); 01139 break; 01140 } 01141 if (LocaleCompare("ping",option+1) == 0) 01142 { 01143 _image_info->ping = ArgBoolean; 01144 break; 01145 } 01146 if (LocaleCompare("pointsize",option+1) == 0) 01147 { 01148 if (IfSetOption) { 01149 if (IfMagickFalse(IsGeometry(arg1))) 01150 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01151 _image_info->pointsize = 01152 _draw_info->pointsize = 01153 StringToDouble(arg1,(char **) NULL); 01154 } 01155 else { 01156 _image_info->pointsize=0.0; /* unset pointsize */ 01157 _draw_info->pointsize=12.0; 01158 } 01159 break; 01160 } 01161 if (LocaleCompare("precision",option+1) == 0) 01162 { 01163 arg1=ArgOption("-1"); 01164 if (IfMagickFalse(IsGeometry(arg1))) 01165 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01166 (void) SetMagickPrecision(StringToInteger(arg1)); 01167 break; 01168 } 01169 /* FUTURE: Only the 'preview' coder appears to use this 01170 * DEPRECIATE the coder? Leaving only the 'preview' operator. 01171 if (LocaleCompare("preview",option+1) == 0) 01172 { 01173 _image_info->preview_type=UndefinedPreview; 01174 if (IfSetOption) 01175 _image_info->preview_type=(PreviewType) ParseCommandOption( 01176 MagickPreviewOptions,MagickFalse,arg1); 01177 break; 01178 } 01179 */ 01180 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01181 } 01182 case 'q': 01183 { 01184 if (LocaleCompare("quality",option+1) == 0) 01185 { 01186 if (IfMagickFalse(IsGeometry(arg1))) 01187 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01188 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1) 01189 : UNDEFINED_COMPRESSION_QUALITY; 01190 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01191 break; 01192 } 01193 if (LocaleCompare("quantize",option+1) == 0) 01194 { 01195 /* Just a set direct in _quantize_info */ 01196 arg1=ArgOption("undefined"); 01197 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1); 01198 if (parse < 0) 01199 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace", 01200 option,arg1); 01201 _quantize_info->colorspace=(ColorspaceType)parse; 01202 break; 01203 } 01204 if (LocaleCompare("quiet",option+1) == 0) 01205 { 01206 /* FUTURE: if two -quiet is performed you can not do +quiet! 01207 This needs to be checked over thoughly. 01208 */ 01209 static WarningHandler 01210 warning_handler = (WarningHandler) NULL; 01211 01212 WarningHandler 01213 tmp = SetWarningHandler((WarningHandler) NULL); 01214 01215 if ( tmp != (WarningHandler) NULL) 01216 warning_handler = tmp; /* remember the old handler */ 01217 if (!IfSetOption) /* set the old handler */ 01218 warning_handler=SetWarningHandler(warning_handler); 01219 break; 01220 } 01221 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01222 } 01223 case 'r': 01224 { 01225 if (LocaleCompare("red-primary",option+1) == 0) 01226 { 01227 /* Image chromaticity X,Y NB: Y=X if Y not defined 01228 Used by many coders 01229 SyncImageSettings() used to set per-image attribute. 01230 */ 01231 arg1=ArgOption("0.0"); 01232 if (IfMagickFalse(IsGeometry(arg1))) 01233 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01234 (void) SetImageOption(_image_info,option+1,arg1); 01235 break; 01236 } 01237 if (LocaleCompare("regard-warnings",option+1) == 0) 01238 /* FUTURE: to be replaced by a 'fatal-level' type setting */ 01239 break; 01240 if (LocaleCompare("render",option+1) == 0) 01241 { 01242 /* _draw_info only setting */ 01243 _draw_info->render= ArgBooleanNot; 01244 break; 01245 } 01246 if (LocaleCompare("respect-parenthesis",option+1) == 0) 01247 { 01248 /* link image and setting stacks - option is itself saved on stack! */ 01249 (void) SetImageOption(_image_info,option+1,ArgBooleanString); 01250 break; 01251 } 01252 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01253 } 01254 case 's': 01255 { 01256 if (LocaleCompare("sampling-factor",option+1) == 0) 01257 { 01258 /* FUTURE: should be converted to jpeg:sampling_factor */ 01259 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 01260 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01261 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL)); 01262 break; 01263 } 01264 if (LocaleCompare("scene",option+1) == 0) 01265 { 01266 /* SyncImageSettings() used to set this as a per-image attribute. 01267 What ??? Why ???? 01268 */ 01269 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 01270 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01271 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01272 _image_info->scene=StringToUnsignedLong(ArgOption("0")); 01273 break; 01274 } 01275 if (LocaleCompare("seed",option+1) == 0) 01276 { 01277 if (IfMagickFalse(IsGeometry(arg1))) 01278 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01279 SetRandomSecretKey( 01280 IfSetOption ? (size_t) StringToUnsignedLong(arg1) 01281 : (size_t) time((time_t *) NULL) ); 01282 break; 01283 } 01284 if (LocaleCompare("size",option+1) == 0) 01285 { 01286 /* FUTURE: string in _image_info -- convert to Option ??? 01287 Look at the special handling for "size" in SetImageOption() 01288 */ 01289 (void) CloneString(&_image_info->size,ArgOption(NULL)); 01290 break; 01291 } 01292 if (LocaleCompare("stretch",option+1) == 0) 01293 { 01294 arg1=ArgOption("undefined"); 01295 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1); 01296 if (parse < 0) 01297 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType", 01298 option,arg1); 01299 _draw_info->stretch=(StretchType) parse; 01300 break; 01301 } 01302 if (LocaleCompare("stroke",option+1) == 0) 01303 { 01304 /* set stroke color OR stroke-pattern 01305 UPDATE: ensure stroke color is not destroyed is a pattern 01306 is given. Just in case the color is also used for other purposes. 01307 */ 01308 MagickBooleanType 01309 status; 01310 01311 ExceptionInfo 01312 *sans; 01313 01314 PixelInfo 01315 color; 01316 01317 arg1 = ArgOption("none"); /* +fill turns it off! */ 01318 (void) SetImageOption(_image_info,option+1,arg1); 01319 if (_draw_info->stroke_pattern != (Image *) NULL) 01320 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern); 01321 01322 /* is it a color or a image? -- ignore exceptions */ 01323 sans=AcquireExceptionInfo(); 01324 status=QueryColorCompliance(arg1,AllCompliance,&color,sans); 01325 sans=DestroyExceptionInfo(sans); 01326 01327 if (IfMagickFalse(status)) 01328 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception); 01329 else 01330 _draw_info->stroke=color; 01331 break; 01332 } 01333 if (LocaleCompare("strokewidth",option+1) == 0) 01334 { 01335 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 01336 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01337 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01338 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"), 01339 (char **) NULL); 01340 break; 01341 } 01342 if (LocaleCompare("style",option+1) == 0) 01343 { 01344 arg1=ArgOption("undefined"); 01345 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1); 01346 if (parse < 0) 01347 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType", 01348 option,arg1); 01349 _draw_info->style=(StyleType) parse; 01350 break; 01351 } 01352 #if 0 01353 if (LocaleCompare("subimage-search",option+1) == 0) 01354 { 01355 /* FUTURE: this is only used by CompareImages() which is used 01356 only by the "compare" CLI program at this time. */ 01357 (void) SetImageOption(_image_info,option+1,ArgBooleanString); 01358 break; 01359 } 01360 #endif 01361 if (LocaleCompare("synchronize",option+1) == 0) 01362 { 01363 /* FUTURE: syncronize to storage - but what does that mean? */ 01364 _image_info->synchronize = ArgBoolean; 01365 break; 01366 } 01367 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01368 } 01369 case 't': 01370 { 01371 if (LocaleCompare("taint",option+1) == 0) 01372 { 01373 /* SyncImageSettings() used to set per-image attribute. */ 01374 (void) SetImageOption(_image_info,option+1,ArgBooleanString); 01375 break; 01376 } 01377 if (LocaleCompare("texture",option+1) == 0) 01378 { 01379 /* FUTURE: move _image_info string to option splay-tree 01380 Other than "montage" what uses "texture" ???? 01381 */ 01382 (void) CloneString(&_image_info->texture,ArgOption(NULL)); 01383 break; 01384 } 01385 if (LocaleCompare("tile",option+1) == 0) 01386 { 01387 _draw_info->fill_pattern=IfSetOption 01388 ?GetImageCache(_image_info,arg1,_exception) 01389 :DestroyImage(_draw_info->fill_pattern); 01390 break; 01391 } 01392 if (LocaleCompare("tile-offset",option+1) == 0) 01393 { 01394 /* SyncImageSettings() used to set per-image attribute. ??? */ 01395 arg1=ArgOption("0"); 01396 if (IfMagickFalse(IsGeometry(arg1))) 01397 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01398 (void) SetImageOption(_image_info,option+1,arg1); 01399 break; 01400 } 01401 if (LocaleCompare("transparent-color",option+1) == 0) 01402 { 01403 /* FUTURE: both _image_info attribute & ImageOption in use! 01404 _image_info only used for generating new images. 01405 SyncImageSettings() used to set per-image attribute. 01406 01407 Note that +transparent-color, means fall-back to image 01408 attribute so ImageOption is deleted, not set to a default. 01409 */ 01410 if (IfSetOption && IfMagickFalse(IsGeometry(arg1))) 01411 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01412 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01413 (void) QueryColorCompliance(ArgOption("none"),AllCompliance, 01414 &_image_info->transparent_color,_exception); 01415 break; 01416 } 01417 if (LocaleCompare("treedepth",option+1) == 0) 01418 { 01419 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01420 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0")); 01421 break; 01422 } 01423 if (LocaleCompare("type",option+1) == 0) 01424 { 01425 /* SyncImageSettings() used to set per-image attribute. */ 01426 parse=ParseCommandOption(MagickTypeOptions,MagickFalse, 01427 ArgOption("undefined")); 01428 if (parse < 0) 01429 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType", 01430 option,arg1); 01431 _image_info->type=(ImageType) parse; 01432 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01433 break; 01434 } 01435 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01436 } 01437 case 'u': 01438 { 01439 if (LocaleCompare("undercolor",option+1) == 0) 01440 { 01441 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01442 (void) QueryColorCompliance(ArgOption("none"),AllCompliance, 01443 &_draw_info->undercolor,_exception); 01444 break; 01445 } 01446 if (LocaleCompare("units",option+1) == 0) 01447 { 01448 /* SyncImageSettings() used to set per-image attribute. 01449 Should this effect _draw_info X and Y resolution? 01450 FUTURE: this probably should be part of the density setting 01451 */ 01452 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse, 01453 ArgOption("undefined")); 01454 if (parse < 0) 01455 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType", 01456 option,arg1); 01457 _image_info->units=(ResolutionType) parse; 01458 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01459 break; 01460 } 01461 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01462 } 01463 case 'v': 01464 { 01465 if (LocaleCompare("verbose",option+1) == 0) 01466 { 01467 /* FUTURE: Remember all options become image artifacts 01468 _image_info->verbose is only used by coders. 01469 */ 01470 (void) SetImageOption(_image_info,option+1,ArgBooleanString); 01471 _image_info->verbose= ArgBoolean; 01472 _image_info->ping=MagickFalse; /* verbose can't be a ping */ 01473 break; 01474 } 01475 if (LocaleCompare("view",option+1) == 0) 01476 { 01477 /* FUTURE: Convert from _image_info to ImageOption 01478 Only used by coder FPX 01479 And it only tests existance, not its content! 01480 */ 01481 (void) CloneString(&_image_info->view,ArgOption(NULL)); 01482 break; 01483 } 01484 if (LocaleCompare("virtual-pixel",option+1) == 0) 01485 { 01486 /* SyncImageSettings() used to set per-image attribute. 01487 This is VERY deep in the image caching structure. 01488 */ 01489 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse, 01490 ArgOption("undefined")); 01491 if (parse < 0) 01492 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod", 01493 option,arg1); 01494 (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); 01495 break; 01496 } 01497 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01498 } 01499 case 'w': 01500 { 01501 if (LocaleCompare("weight",option+1) == 0) 01502 { 01503 /* Just what does using a font 'weight' do ??? 01504 There is no "-list weight" output (reference manual says there is) 01505 */ 01506 arg1=ArgOption("all"); 01507 _draw_info->weight=StringToUnsignedLong(arg1); 01508 if (LocaleCompare(arg1,"all") == 0) 01509 _draw_info->weight=0; 01510 if (LocaleCompare(arg1,"bold") == 0) 01511 _draw_info->weight=700; 01512 if (LocaleCompare(arg1,"bolder") == 0) 01513 if (_draw_info->weight <= 800) 01514 _draw_info->weight+=100; 01515 if (LocaleCompare(arg1,"lighter") == 0) 01516 if (_draw_info->weight >= 100) 01517 _draw_info->weight-=100; 01518 if (LocaleCompare(arg1,"normal") == 0) 01519 _draw_info->weight=400; 01520 break; 01521 } 01522 if (LocaleCompare("white-point",option+1) == 0) 01523 { 01524 /* Used as a image chromaticity setting 01525 SyncImageSettings() used to set per-image attribute. 01526 */ 01527 arg1=ArgOption("0.0"); 01528 if (IfMagickFalse(IsGeometry(arg1))) 01529 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01530 (void) SetImageOption(_image_info,option+1,arg1); 01531 break; 01532 } 01533 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01534 } 01535 default: 01536 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01537 } 01538 01539 #undef _image_info 01540 #undef _exception 01541 #undef _draw_info 01542 #undef _quantize_info 01543 #undef IfSetOption 01544 #undef ArgBoolean 01545 #undef ArgBooleanNot 01546 #undef ArgBooleanString 01547 #undef ArgOption 01548 01549 return; 01550 } 01551 01552 /* 01553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01554 % % 01555 % % 01556 % % 01557 + C L I S i m p l e O p e r a t o r I m a g e s % 01558 % % 01559 % % 01560 % % 01561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01562 % 01563 % WandSimpleOperatorImages() applys one simple image operation given to all 01564 % the images in the CLI wand, with the settings that was previously saved in 01565 % the CLI wand. 01566 % 01567 % It is assumed that any per-image settings are up-to-date with respect to 01568 % extra settings that were already saved in the wand. 01569 % 01570 % The format of the WandSimpleOperatorImage method is: 01571 % 01572 % void CLISimpleOperatorImages(MagickCLI *cli_wand, 01573 % const char *option, const char *arg1, const char *arg2) 01574 % 01575 % A description of each parameter follows: 01576 % 01577 % o cli_wand: structure holding settings and images to be operated on 01578 % 01579 % o option: The option string for the operation 01580 % 01581 % o arg1, arg2: optional argument strings to the operation 01582 % 01583 */ 01584 01585 /* 01586 Internal subrountine to apply one simple image operation to the current 01587 image pointed to by the CLI wand. 01588 01589 The image in the list may be modified in three different ways... 01590 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw), 01591 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology) 01592 * one image replace by a list of images (-separate and -crop only!) 01593 01594 In each case the result replaces the single original image in the list, as 01595 well as the pointer to the modified image (last image added if replaced by a 01596 list of images) is returned. 01597 01598 As the image pointed to may be replaced, the first image in the list may 01599 also change. GetFirstImageInList() should be used by caller if they wish 01600 return the Image pointer to the first image in list. 01601 */ 01602 static void CLISimpleOperatorImage(MagickCLI *cli_wand, 01603 const char *option, const char *arg1n, const char *arg2n) 01604 { 01605 Image * 01606 new_image; 01607 01608 GeometryInfo 01609 geometry_info; 01610 01611 RectangleInfo 01612 geometry; 01613 01614 MagickStatusType 01615 flags; 01616 01617 ssize_t 01618 parse; 01619 01620 const char /* For percent escape interpretImageProperties() */ 01621 *arg1, 01622 *arg2; 01623 01624 #define _image_info (cli_wand->wand.image_info) 01625 #define _image (cli_wand->wand.images) 01626 #define _exception (cli_wand->wand.exception) 01627 #define _draw_info (cli_wand->draw_info) 01628 #define _quantize_info (cli_wand->quantize_info) 01629 #define _process_flags (cli_wand->process_flags) 01630 #define _option_type ((CommandOptionFlags) cli_wand->command->flags) 01631 #define IfNormalOp (*option=='-') 01632 #define IfPlusOp (*option!='-') 01633 #define normal_op IsMagickTrue(IfNormalOp) 01634 #define plus_alt_op IsMagickFalse(IfNormalOp) 01635 01636 assert(cli_wand != (MagickCLI *) NULL); 01637 assert(cli_wand->signature == WandSignature); 01638 assert(cli_wand->wand.signature == WandSignature); 01639 assert(_image != (Image *) NULL); /* an image must be present */ 01640 if (IfMagickTrue(cli_wand->wand.debug)) 01641 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); 01642 01643 /* Interpret Percent Escapes in Arguments - using first image */ 01644 arg1 = arg1n, 01645 arg2 = arg2n; 01646 if ( (((_process_flags & ProcessInterpretProperities) != 0 ) 01647 || ((_option_type & AlwaysInterpretArgsFlag) != 0) 01648 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) { 01649 /* Interpret Percent escapes in argument 1 */ 01650 if (arg1n != (char *) NULL) { 01651 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception); 01652 if (arg1 == (char *) NULL) { 01653 CLIWandException(OptionWarning,"InterpretPropertyFailure",option); 01654 arg1=arg1n; /* use the given argument as is */ 01655 } 01656 } 01657 if (arg2n != (char *) NULL) { 01658 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception); 01659 if (arg2 == (char *) NULL) { 01660 CLIWandException(OptionWarning,"InterpretPropertyFailure",option); 01661 arg2=arg2n; /* use the given argument as is */ 01662 } 01663 } 01664 } 01665 #undef _option_type 01666 01667 #if 0 01668 (void) FormatLocaleFile(stderr, 01669 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2); 01670 #endif 01671 01672 new_image = (Image *)NULL; /* the replacement image, if not null at end */ 01673 SetGeometryInfo(&geometry_info); 01674 01675 switch (*(option+1)) 01676 { 01677 case 'a': 01678 { 01679 if (LocaleCompare("adaptive-blur",option+1) == 0) 01680 { 01681 flags=ParseGeometry(arg1,&geometry_info); 01682 if ((flags & (RhoValue|SigmaValue)) == 0) 01683 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01684 if ((flags & SigmaValue) == 0) 01685 geometry_info.sigma=1.0; 01686 new_image=AdaptiveBlurImage(_image,geometry_info.rho, 01687 geometry_info.sigma,_exception); 01688 break; 01689 } 01690 if (LocaleCompare("adaptive-resize",option+1) == 0) 01691 { 01692 /* FUTURE: Roll into a resize special operator */ 01693 if (IfMagickFalse(IsGeometry(arg1))) 01694 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01695 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception); 01696 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height, 01697 _exception); 01698 break; 01699 } 01700 if (LocaleCompare("adaptive-sharpen",option+1) == 0) 01701 { 01702 flags=ParseGeometry(arg1,&geometry_info); 01703 if ((flags & (RhoValue|SigmaValue)) == 0) 01704 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01705 if ((flags & SigmaValue) == 0) 01706 geometry_info.sigma=1.0; 01707 new_image=AdaptiveSharpenImage(_image,geometry_info.rho, 01708 geometry_info.sigma,_exception); 01709 break; 01710 } 01711 if (LocaleCompare("alpha",option+1) == 0) 01712 { 01713 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1); 01714 if (parse < 0) 01715 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType", 01716 option,arg1); 01717 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse, 01718 _exception); 01719 break; 01720 } 01721 if (LocaleCompare("annotate",option+1) == 0) 01722 { 01723 char 01724 geometry[MaxTextExtent]; 01725 01726 SetGeometryInfo(&geometry_info); 01727 flags=ParseGeometry(arg1,&geometry_info); 01728 if ((flags & RhoValue) == 0) 01729 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01730 if ((flags & SigmaValue) == 0) 01731 geometry_info.sigma=geometry_info.rho; 01732 (void) CloneString(&_draw_info->text,arg2); 01733 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f", 01734 geometry_info.xi,geometry_info.psi); 01735 (void) CloneString(&_draw_info->geometry,geometry); 01736 _draw_info->affine.sx=cos(DegreesToRadians( 01737 fmod(geometry_info.rho,360.0))); 01738 _draw_info->affine.rx=sin(DegreesToRadians( 01739 fmod(geometry_info.rho,360.0))); 01740 _draw_info->affine.ry=(-sin(DegreesToRadians( 01741 fmod(geometry_info.sigma,360.0)))); 01742 _draw_info->affine.sy=cos(DegreesToRadians( 01743 fmod(geometry_info.sigma,360.0))); 01744 (void) AnnotateImage(_image,_draw_info,_exception); 01745 GetAffineMatrix(&_draw_info->affine); 01746 break; 01747 } 01748 if (LocaleCompare("auto-gamma",option+1) == 0) 01749 { 01750 (void) AutoGammaImage(_image,_exception); 01751 break; 01752 } 01753 if (LocaleCompare("auto-level",option+1) == 0) 01754 { 01755 (void) AutoLevelImage(_image,_exception); 01756 break; 01757 } 01758 if (LocaleCompare("auto-orient",option+1) == 0) 01759 { 01760 /* This should probably be a MagickCore function */ 01761 switch (_image->orientation) 01762 { 01763 case TopRightOrientation: 01764 { 01765 new_image=FlopImage(_image,_exception); 01766 break; 01767 } 01768 case BottomRightOrientation: 01769 { 01770 new_image=RotateImage(_image,180.0,_exception); 01771 break; 01772 } 01773 case BottomLeftOrientation: 01774 { 01775 new_image=FlipImage(_image,_exception); 01776 break; 01777 } 01778 case LeftTopOrientation: 01779 { 01780 new_image=TransposeImage(_image,_exception); 01781 break; 01782 } 01783 case RightTopOrientation: 01784 { 01785 new_image=RotateImage(_image,90.0,_exception); 01786 break; 01787 } 01788 case RightBottomOrientation: 01789 { 01790 new_image=TransverseImage(_image,_exception); 01791 break; 01792 } 01793 case LeftBottomOrientation: 01794 { 01795 new_image=RotateImage(_image,270.0,_exception); 01796 break; 01797 } 01798 default: 01799 break; 01800 } 01801 if (new_image != (Image *) NULL) 01802 new_image->orientation=TopLeftOrientation; 01803 break; 01804 } 01805 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01806 } 01807 case 'b': 01808 { 01809 if (LocaleCompare("black-threshold",option+1) == 0) 01810 { 01811 if (IfMagickFalse(IsGeometry(arg1))) 01812 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01813 (void) BlackThresholdImage(_image,arg1,_exception); 01814 break; 01815 } 01816 if (LocaleCompare("blue-shift",option+1) == 0) 01817 { 01818 geometry_info.rho=1.5; 01819 if (IfNormalOp) { 01820 flags=ParseGeometry(arg1,&geometry_info); 01821 if ((flags & RhoValue) == 0) 01822 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01823 } 01824 new_image=BlueShiftImage(_image,geometry_info.rho,_exception); 01825 break; 01826 } 01827 if (LocaleCompare("blur",option+1) == 0) 01828 { 01829 flags=ParseGeometry(arg1,&geometry_info); 01830 if ((flags & (RhoValue|SigmaValue)) == 0) 01831 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01832 if ((flags & SigmaValue) == 0) 01833 geometry_info.sigma=1.0; 01834 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma, 01835 _exception); 01836 break; 01837 } 01838 if (LocaleCompare("border",option+1) == 0) 01839 { 01840 CompositeOperator 01841 compose; 01842 01843 const char* 01844 value; 01845 01846 flags=ParsePageGeometry(_image,arg1,&geometry,_exception); 01847 if ((flags & RhoValue) == 0) 01848 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01849 if ((flags & SigmaValue) == 0) 01850 geometry.height=geometry.width; 01851 01852 value=GetImageOption(_image_info,"compose"); 01853 if (value != (const char *) NULL) 01854 compose=(CompositeOperator) ParseCommandOption( 01855 MagickComposeOptions,MagickFalse,value); 01856 else 01857 compose=OverCompositeOp; /* use Over not _image->compose */ 01858 01859 new_image=BorderImage(_image,&geometry,compose,_exception); 01860 break; 01861 } 01862 if (LocaleCompare("brightness-contrast",option+1) == 0) 01863 { 01864 double 01865 brightness, 01866 contrast; 01867 01868 GeometryInfo 01869 geometry_info; 01870 01871 MagickStatusType 01872 flags; 01873 01874 flags=ParseGeometry(arg1,&geometry_info); 01875 if ((flags & RhoValue) == 0) 01876 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01877 brightness=geometry_info.rho; 01878 contrast=0.0; 01879 if ((flags & SigmaValue) != 0) 01880 contrast=geometry_info.sigma; 01881 (void) BrightnessContrastImage(_image,brightness,contrast, 01882 _exception); 01883 break; 01884 } 01885 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 01886 } 01887 case 'c': 01888 { 01889 if (LocaleCompare("cdl",option+1) == 0) 01890 { 01891 char 01892 *color_correction_collection; 01893 01894 /* 01895 Color correct with a color decision list. 01896 */ 01897 color_correction_collection=FileToString(arg1,~0,_exception); 01898 if (color_correction_collection == (char *) NULL) 01899 break; 01900 (void) ColorDecisionListImage(_image,color_correction_collection, 01901 _exception); 01902 break; 01903 } 01904 if (LocaleCompare("charcoal",option+1) == 0) 01905 { 01906 flags=ParseGeometry(arg1,&geometry_info); 01907 if ((flags & (RhoValue|SigmaValue)) == 0) 01908 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01909 if ((flags & SigmaValue) == 0) 01910 geometry_info.sigma=1.0; 01911 if ((flags & XiValue) == 0) 01912 geometry_info.xi=1.0; 01913 new_image=CharcoalImage(_image,geometry_info.rho, 01914 geometry_info.sigma,_exception); 01915 break; 01916 } 01917 if (LocaleCompare("chop",option+1) == 0) 01918 { 01919 if (IfMagickFalse(IsGeometry(arg1))) 01920 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 01921 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception); 01922 new_image=ChopImage(_image,&geometry,_exception); 01923 break; 01924 } 01925 if (LocaleCompare("clamp",option+1) == 0) 01926 { 01927 (void) ClampImage(_image,_exception); 01928 break; 01929 } 01930 if (LocaleCompare("clip",option+1) == 0) 01931 { 01932 if (IfNormalOp) 01933 (void) ClipImage(_image,_exception); 01934 else /* "+mask" remove the write mask */ 01935 (void) SetImageMask(_image,(Image *) NULL,_exception); 01936 break; 01937 } 01938 if (LocaleCompare("clip-mask",option+1) == 0) 01939 { 01940 CacheView 01941 *mask_view; 01942 01943 Image 01944 *mask_image; 01945 01946 register Quantum 01947 *restrict q; 01948 01949 register ssize_t 01950 x; 01951 01952 ssize_t 01953 y; 01954 01955 if (IfPlusOp) { 01956 /* "+clip-mask" Remove the write mask */ 01957 (void) SetImageMask(_image,(Image *) NULL,_exception); 01958 break; 01959 } 01960 mask_image=GetImageCache(_image_info,arg1,_exception); 01961 if (mask_image == (Image *) NULL) 01962 break; 01963 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception))) 01964 break; 01965 /* Create a write mask from cli_wand mask image */ 01966 /* FUTURE: use Alpha operations instead and create a Grey Image */ 01967 mask_view=AcquireAuthenticCacheView(mask_image,_exception); 01968 for (y=0; y < (ssize_t) mask_image->rows; y++) 01969 { 01970 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1, 01971 _exception); 01972 if (q == (Quantum *) NULL) 01973 break; 01974 for (x=0; x < (ssize_t) mask_image->columns; x++) 01975 { 01976 if (IfMagickFalse(mask_image->matte)) 01977 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q); 01978 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q); 01979 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q); 01980 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q); 01981 q+=GetPixelChannels(mask_image); 01982 } 01983 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception))) 01984 break; 01985 } 01986 /* clean up and set the write mask */ 01987 mask_view=DestroyCacheView(mask_view); 01988 mask_image->matte=MagickTrue; 01989 (void) SetImageMask(_image,mask_image,_exception); 01990 mask_image=DestroyImage(mask_image); 01991 break; 01992 } 01993 if (LocaleCompare("clip-path",option+1) == 0) 01994 { 01995 (void) ClipImagePath(_image,arg1,normal_op,_exception); 01996 break; 01997 } 01998 if (LocaleCompare("colorize",option+1) == 0) 01999 { 02000 if (IfMagickFalse(IsGeometry(arg1))) 02001 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02002 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception); 02003 break; 02004 } 02005 if (LocaleCompare("color-matrix",option+1) == 0) 02006 { 02007 KernelInfo 02008 *kernel; 02009 02010 kernel=AcquireKernelInfo(arg1); 02011 if (kernel == (KernelInfo *) NULL) 02012 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02013 new_image=ColorMatrixImage(_image,kernel,_exception); 02014 kernel=DestroyKernelInfo(kernel); 02015 break; 02016 } 02017 if (LocaleCompare("colors",option+1) == 0) 02018 { 02019 /* Reduce the number of colors in the image. 02020 FUTURE: also provide 'plus version with image 'color counts' 02021 */ 02022 _quantize_info->number_colors=StringToUnsignedLong(arg1); 02023 if (_quantize_info->number_colors == 0) 02024 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02025 if ((_image->storage_class == DirectClass) || 02026 _image->colors > _quantize_info->number_colors) 02027 (void) QuantizeImage(_quantize_info,_image,_exception); 02028 else 02029 (void) CompressImageColormap(_image,_exception); 02030 break; 02031 } 02032 if (LocaleCompare("colorspace",option+1) == 0) 02033 { 02034 /* WARNING: this is both a image_info setting (already done) 02035 and a operator to change image colorspace. 02036 02037 FUTURE: default colorspace should be sRGB! 02038 Unless some type of 'linear colorspace' mode is set. 02039 02040 Note that +colorspace sets "undefined" or no effect on 02041 new images, but forces images already in memory back to RGB! 02042 That seems to be a little strange! 02043 */ 02044 (void) TransformImageColorspace(_image, 02045 IfNormalOp ? _image_info->colorspace : RGBColorspace, 02046 _exception); 02047 break; 02048 } 02049 if (LocaleCompare("contrast",option+1) == 0) 02050 { 02051 CLIWandWarnReplaced(normal_op?"-level":"+level"); 02052 (void) ContrastImage(_image,normal_op,_exception); 02053 break; 02054 } 02055 if (LocaleCompare("contrast-stretch",option+1) == 0) 02056 { 02057 double 02058 black_point, 02059 white_point; 02060 02061 MagickStatusType 02062 flags; 02063 02064 flags=ParseGeometry(arg1,&geometry_info); 02065 if ((flags & RhoValue) == 0) 02066 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02067 black_point=geometry_info.rho; 02068 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : 02069 black_point; 02070 if ((flags & PercentValue) != 0) { 02071 black_point*=(double) _image->columns*_image->rows/100.0; 02072 white_point*=(double) _image->columns*_image->rows/100.0; 02073 } 02074 white_point=(MagickRealType) _image->columns*_image->rows- 02075 white_point; 02076 (void) ContrastStretchImage(_image,black_point,white_point, 02077 _exception); 02078 break; 02079 } 02080 if (LocaleCompare("convolve",option+1) == 0) 02081 { 02082 KernelInfo 02083 *kernel_info; 02084 02085 kernel_info=AcquireKernelInfo(arg1); 02086 if (kernel_info == (KernelInfo *) NULL) 02087 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02088 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info, 02089 _exception); 02090 kernel_info=DestroyKernelInfo(kernel_info); 02091 break; 02092 } 02093 if (LocaleCompare("crop",option+1) == 0) 02094 { 02095 /* WARNING: This can generate multiple images! */ 02096 if (IfMagickFalse(IsGeometry(arg1))) 02097 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02098 new_image=CropImageToTiles(_image,arg1,_exception); 02099 break; 02100 } 02101 if (LocaleCompare("cycle",option+1) == 0) 02102 { 02103 if (IfMagickFalse(IsGeometry(arg1))) 02104 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02105 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1), 02106 _exception); 02107 break; 02108 } 02109 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02110 } 02111 case 'd': 02112 { 02113 if (LocaleCompare("decipher",option+1) == 0) 02114 { 02115 StringInfo 02116 *passkey; 02117 02118 passkey=FileToStringInfo(arg1,~0,_exception); 02119 if (passkey == (StringInfo *) NULL) 02120 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02121 02122 (void) PasskeyDecipherImage(_image,passkey,_exception); 02123 passkey=DestroyStringInfo(passkey); 02124 break; 02125 } 02126 if (LocaleCompare("depth",option+1) == 0) 02127 { 02128 /* The _image_info->depth setting has already been set 02129 We just need to apply it to all images in current sequence 02130 02131 WARNING: Depth from 8 to 16 causes 'quantum rounding to images! 02132 That is it really is an operation, not a setting! Arrgghhh 02133 02134 FUTURE: this should not be an operator!!! 02135 */ 02136 (void) SetImageDepth(_image,_image_info->depth,_exception); 02137 break; 02138 } 02139 if (LocaleCompare("deskew",option+1) == 0) 02140 { 02141 double 02142 threshold; 02143 02144 if (IfNormalOp) { 02145 if (IfMagickFalse(IsGeometry(arg1))) 02146 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02147 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0); 02148 } 02149 else 02150 threshold=40.0*QuantumRange/100.0; 02151 new_image=DeskewImage(_image,threshold,_exception); 02152 break; 02153 } 02154 if (LocaleCompare("despeckle",option+1) == 0) 02155 { 02156 new_image=DespeckleImage(_image,_exception); 02157 break; 02158 } 02159 if (LocaleCompare("distort",option+1) == 0) 02160 { 02161 double 02162 *args; 02163 02164 ssize_t 02165 count; 02166 02167 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1); 02168 if ( parse < 0 ) 02169 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod", 02170 option,arg1); 02171 if ((DistortImageMethod) parse == ResizeDistortion) 02172 { 02173 double 02174 resize_args[2]; 02175 /* Special Case - Argument is actually a resize geometry! 02176 ** Convert that to an appropriate distortion argument array. 02177 ** FUTURE: make a separate special resize operator 02178 Roll into a resize special operator */ 02179 if (IfMagickFalse(IsGeometry(arg2))) 02180 CLIWandExceptArgBreak(OptionError,"InvalidGeometry", 02181 option,arg2); 02182 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception); 02183 resize_args[0]=(double) geometry.width; 02184 resize_args[1]=(double) geometry.height; 02185 new_image=DistortImage(_image,(DistortImageMethod) parse, 02186 (size_t)2,resize_args,MagickTrue,_exception); 02187 break; 02188 } 02189 /* convert argument string into an array of doubles */ 02190 args = StringToArrayOfDoubles(arg2,&count,_exception); 02191 if (args == (double *)NULL ) 02192 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2); 02193 02194 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args, 02195 plus_alt_op,_exception); 02196 args=(double *) RelinquishMagickMemory(args); 02197 break; 02198 } 02199 if (LocaleCompare("draw",option+1) == 0) 02200 { 02201 (void) CloneString(&_draw_info->primitive,arg1); 02202 (void) DrawImage(_image,_draw_info,_exception); 02203 (void) CloneString(&_draw_info->primitive,(char *)NULL); 02204 break; 02205 } 02206 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02207 } 02208 case 'e': 02209 { 02210 if (LocaleCompare("edge",option+1) == 0) 02211 { 02212 flags=ParseGeometry(arg1,&geometry_info); 02213 if ((flags & (RhoValue|SigmaValue)) == 0) 02214 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02215 if ((flags & SigmaValue) == 0) 02216 geometry_info.sigma=1.0; 02217 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma, 02218 _exception); 02219 break; 02220 } 02221 if (LocaleCompare("emboss",option+1) == 0) 02222 { 02223 flags=ParseGeometry(arg1,&geometry_info); 02224 if ((flags & (RhoValue|SigmaValue)) == 0) 02225 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02226 if ((flags & SigmaValue) == 0) 02227 geometry_info.sigma=1.0; 02228 new_image=EmbossImage(_image,geometry_info.rho, 02229 geometry_info.sigma,_exception); 02230 break; 02231 } 02232 if (LocaleCompare("encipher",option+1) == 0) 02233 { 02234 StringInfo 02235 *passkey; 02236 02237 passkey=FileToStringInfo(arg1,~0,_exception); 02238 if (passkey != (StringInfo *) NULL) 02239 { 02240 (void) PasskeyEncipherImage(_image,passkey,_exception); 02241 passkey=DestroyStringInfo(passkey); 02242 } 02243 break; 02244 } 02245 if (LocaleCompare("enhance",option+1) == 0) 02246 { 02247 new_image=EnhanceImage(_image,_exception); 02248 break; 02249 } 02250 if (LocaleCompare("equalize",option+1) == 0) 02251 { 02252 (void) EqualizeImage(_image,_exception); 02253 break; 02254 } 02255 if (LocaleCompare("evaluate",option+1) == 0) 02256 { 02257 double 02258 constant; 02259 02260 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1); 02261 if ( parse < 0 ) 02262 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator", 02263 option,arg1); 02264 if (IfMagickFalse(IsGeometry(arg2))) 02265 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2); 02266 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0); 02267 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant, 02268 _exception); 02269 break; 02270 } 02271 if (LocaleCompare("extent",option+1) == 0) 02272 { 02273 if (IfMagickFalse(IsGeometry(arg1))) 02274 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02275 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception); 02276 if (geometry.width == 0) 02277 geometry.width=_image->columns; 02278 if (geometry.height == 0) 02279 geometry.height=_image->rows; 02280 new_image=ExtentImage(_image,&geometry,_exception); 02281 break; 02282 } 02283 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02284 } 02285 case 'f': 02286 { 02287 if (LocaleCompare("features",option+1) == 0) 02288 { 02289 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */ 02290 if (IfPlusOp) { 02291 (void) DeleteImageArtifact(_image,"identify:features"); 02292 break; 02293 } 02294 (void) SetImageArtifact(_image,"identify:features","true"); 02295 (void) SetImageArtifact(_image,"verbose","true"); 02296 break; 02297 } 02298 if (LocaleCompare("flip",option+1) == 0) 02299 { 02300 new_image=FlipImage(_image,_exception); 02301 break; 02302 } 02303 if (LocaleCompare("flop",option+1) == 0) 02304 { 02305 new_image=FlopImage(_image,_exception); 02306 break; 02307 } 02308 if (LocaleCompare("floodfill",option+1) == 0) 02309 { 02310 PixelInfo 02311 target; 02312 02313 if (IfMagickFalse(IsGeometry(arg1))) 02314 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02315 (void) ParsePageGeometry(_image,arg1,&geometry,_exception); 02316 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception); 02317 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x, 02318 geometry.y,plus_alt_op,_exception); 02319 break; 02320 } 02321 if (LocaleCompare("frame",option+1) == 0) 02322 { 02323 FrameInfo 02324 frame_info; 02325 02326 CompositeOperator 02327 compose; 02328 02329 const char* 02330 value; 02331 02332 value=GetImageOption(_image_info,"compose"); 02333 if (value != (const char *) NULL) 02334 compose=(CompositeOperator) ParseCommandOption( 02335 MagickComposeOptions,MagickFalse,value); 02336 else 02337 compose=OverCompositeOp; /* use Over not _image->compose */ 02338 02339 if (IfMagickFalse(IsGeometry(arg1))) 02340 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02341 flags=ParsePageGeometry(_image,arg1,&geometry,_exception); 02342 frame_info.width=geometry.width; 02343 frame_info.height=geometry.height; 02344 if ((flags & HeightValue) == 0) 02345 frame_info.height=geometry.width; 02346 frame_info.outer_bevel=geometry.x; 02347 frame_info.inner_bevel=geometry.y; 02348 frame_info.x=(ssize_t) frame_info.width; 02349 frame_info.y=(ssize_t) frame_info.height; 02350 frame_info.width=_image->columns+2*frame_info.width; 02351 frame_info.height=_image->rows+2*frame_info.height; 02352 new_image=FrameImage(_image,&frame_info,compose,_exception); 02353 break; 02354 } 02355 if (LocaleCompare("function",option+1) == 0) 02356 { 02357 double 02358 *args; 02359 02360 ssize_t 02361 count; 02362 02363 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1); 02364 if ( parse < 0 ) 02365 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction", 02366 option,arg1); 02367 /* convert argument string into an array of doubles */ 02368 args = StringToArrayOfDoubles(arg2,&count,_exception); 02369 if (args == (double *)NULL ) 02370 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2); 02371 02372 (void) FunctionImage(_image,(MagickFunction)parse,count,args, 02373 _exception); 02374 args=(double *) RelinquishMagickMemory(args); 02375 break; 02376 } 02377 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02378 } 02379 case 'g': 02380 { 02381 if (LocaleCompare("gamma",option+1) == 0) 02382 { 02383 if (IfMagickFalse(IsGeometry(arg1))) 02384 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02385 if (IfNormalOp) 02386 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL), 02387 _exception); 02388 else 02389 _image->gamma=StringToDouble(arg1,(char **) NULL); 02390 break; 02391 } 02392 if (LocaleCompare("gaussian-blur",option+1) == 0) 02393 { 02394 flags=ParseGeometry(arg1,&geometry_info); 02395 if ((flags & (RhoValue|SigmaValue)) == 0) 02396 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02397 if ((flags & SigmaValue) == 0) 02398 geometry_info.sigma=1.0; 02399 new_image=GaussianBlurImage(_image,geometry_info.rho, 02400 geometry_info.sigma,_exception); 02401 break; 02402 } 02403 if (LocaleCompare("gaussian",option+1) == 0) 02404 { 02405 CLIWandWarnReplaced("-gaussian-blur"); 02406 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL); 02407 } 02408 if (LocaleCompare("geometry",option+1) == 0) 02409 { 02410 /* 02411 Record Image offset for composition. (A Setting) 02412 Resize last _image. (ListOperator) -- DEPRECIATE 02413 FUTURE: Why if no 'offset' does this resize ALL images? 02414 Also why is the setting recorded in the IMAGE non-sense! 02415 */ 02416 if (IfPlusOp) 02417 { /* remove the previous composition geometry offset! */ 02418 if (_image->geometry != (char *) NULL) 02419 _image->geometry=DestroyString(_image->geometry); 02420 break; 02421 } 02422 if (IfMagickFalse(IsGeometry(arg1))) 02423 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02424 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception); 02425 if (((flags & XValue) != 0) || ((flags & YValue) != 0)) 02426 (void) CloneString(&_image->geometry,arg1); 02427 else 02428 new_image=ResizeImage(_image,geometry.width,geometry.height, 02429 _image->filter,_exception); 02430 break; 02431 } 02432 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02433 } 02434 case 'i': 02435 { 02436 if (LocaleCompare("identify",option+1) == 0) 02437 { 02438 const char 02439 *format, 02440 *text; 02441 02442 format=GetImageOption(_image_info,"format"); 02443 if (format == (char *) NULL) { 02444 (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception); 02445 break; 02446 } 02447 text=InterpretImageProperties(_image_info,_image,format,_exception); 02448 if (text == (char *) NULL) 02449 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure", 02450 option); 02451 (void) fputs(text,stdout); 02452 (void) fputc('\n',stdout); 02453 text=DestroyString((char *)text); 02454 break; 02455 } 02456 if (LocaleCompare("implode",option+1) == 0) 02457 { 02458 flags=ParseGeometry(arg1,&geometry_info); 02459 if ((flags & RhoValue) == 0) 02460 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02461 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate, 02462 _exception); 02463 break; 02464 } 02465 if (LocaleCompare("interpolative-resize",option+1) == 0) 02466 { 02467 /* FUTURE: New to IMv7 02468 Roll into a resize special operator */ 02469 if (IfMagickFalse(IsGeometry(arg1))) 02470 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02471 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception); 02472 new_image=InterpolativeResizeImage(_image,geometry.width, 02473 geometry.height,_image->interpolate,_exception); 02474 break; 02475 } 02476 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02477 } 02478 case 'l': 02479 { 02480 if (LocaleCompare("lat",option+1) == 0) 02481 { 02482 flags=ParseGeometry(arg1,&geometry_info); 02483 if ((flags & (RhoValue|SigmaValue)) == 0) 02484 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02485 if ((flags & PercentValue) != 0) 02486 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0; 02487 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho, 02488 (size_t) geometry_info.sigma,(double) geometry_info.xi, 02489 _exception); 02490 break; 02491 } 02492 if (LocaleCompare("level",option+1) == 0) 02493 { 02494 MagickRealType 02495 black_point, 02496 gamma, 02497 white_point; 02498 02499 MagickStatusType 02500 flags; 02501 02502 flags=ParseGeometry(arg1,&geometry_info); 02503 if ((flags & RhoValue) == 0) 02504 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02505 black_point=geometry_info.rho; 02506 white_point=(MagickRealType) QuantumRange; 02507 if ((flags & SigmaValue) != 0) 02508 white_point=geometry_info.sigma; 02509 gamma=1.0; 02510 if ((flags & XiValue) != 0) 02511 gamma=geometry_info.xi; 02512 if ((flags & PercentValue) != 0) 02513 { 02514 black_point*=(MagickRealType) (QuantumRange/100.0); 02515 white_point*=(MagickRealType) (QuantumRange/100.0); 02516 } 02517 if ((flags & SigmaValue) == 0) 02518 white_point=(MagickRealType) QuantumRange-black_point; 02519 if (IfPlusOp || ((flags & AspectValue) != 0)) 02520 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception); 02521 else 02522 (void) LevelImage(_image,black_point,white_point,gamma,_exception); 02523 break; 02524 } 02525 if (LocaleCompare("level-colors",option+1) == 0) 02526 { 02527 char 02528 token[MaxTextExtent]; 02529 02530 const char 02531 *p; 02532 02533 PixelInfo 02534 black_point, 02535 white_point; 02536 02537 p=(const char *) arg1; 02538 GetMagickToken(p,&p,token); /* get black point color */ 02539 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0)) 02540 (void) QueryColorCompliance(token,AllCompliance, 02541 &black_point,_exception); 02542 else 02543 (void) QueryColorCompliance("#000000",AllCompliance, 02544 &black_point,_exception); 02545 if (isalpha((int) token[0]) || (token[0] == '#')) 02546 GetMagickToken(p,&p,token); 02547 if (*token == '\0') 02548 white_point=black_point; /* set everything to that color */ 02549 else 02550 { 02551 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0)) 02552 GetMagickToken(p,&p,token); /* Get white point color. */ 02553 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0)) 02554 (void) QueryColorCompliance(token,AllCompliance, 02555 &white_point,_exception); 02556 else 02557 (void) QueryColorCompliance("#ffffff",AllCompliance, 02558 &white_point,_exception); 02559 } 02560 (void) LevelImageColors(_image,&black_point,&white_point, 02561 plus_alt_op,_exception); 02562 break; 02563 } 02564 if (LocaleCompare("linear-stretch",option+1) == 0) 02565 { 02566 double 02567 black_point, 02568 white_point; 02569 02570 MagickStatusType 02571 flags; 02572 02573 flags=ParseGeometry(arg1,&geometry_info); 02574 if ((flags & RhoValue) == 0) 02575 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02576 black_point=geometry_info.rho; 02577 white_point=(MagickRealType) _image->columns*_image->rows; 02578 if ((flags & SigmaValue) != 0) 02579 white_point=geometry_info.sigma; 02580 if ((flags & PercentValue) != 0) 02581 { 02582 black_point*=(double) _image->columns*_image->rows/100.0; 02583 white_point*=(double) _image->columns*_image->rows/100.0; 02584 } 02585 if ((flags & SigmaValue) == 0) 02586 white_point=(MagickRealType) _image->columns*_image->rows- 02587 black_point; 02588 (void) LinearStretchImage(_image,black_point,white_point,_exception); 02589 break; 02590 } 02591 if (LocaleCompare("liquid-rescale",option+1) == 0) 02592 { 02593 /* FUTURE: Roll into a resize special operator */ 02594 if (IfMagickFalse(IsGeometry(arg1))) 02595 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02596 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception); 02597 if ((flags & XValue) == 0) 02598 geometry.x=1; 02599 if ((flags & YValue) == 0) 02600 geometry.y=0; 02601 new_image=LiquidRescaleImage(_image,geometry.width, 02602 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception); 02603 break; 02604 } 02605 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02606 } 02607 case 'm': 02608 { 02609 if (LocaleCompare("map",option+1) == 0) 02610 { 02611 CLIWandWarnReplaced("-remap"); 02612 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL); 02613 break; 02614 } 02615 if (LocaleCompare("mask",option+1) == 0) 02616 { 02617 Image 02618 *mask; 02619 02620 if (IfPlusOp) 02621 { /* Remove a mask. */ 02622 (void) SetImageMask(_image,(Image *) NULL,_exception); 02623 break; 02624 } 02625 /* Set the image mask. */ 02626 mask=GetImageCache(_image_info,arg1,_exception); 02627 if (mask == (Image *) NULL) 02628 break; 02629 (void) SetImageMask(_image,mask,_exception); 02630 mask=DestroyImage(mask); 02631 break; 02632 } 02633 if (LocaleCompare("matte",option+1) == 0) 02634 { 02635 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off"); 02636 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel : 02637 DeactivateAlphaChannel, _exception); 02638 break; 02639 } 02640 if (LocaleCompare("median",option+1) == 0) 02641 { 02642 CLIWandWarnReplaced("-statistic Median"); 02643 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1); 02644 break; 02645 } 02646 if (LocaleCompare("mode",option+1) == 0) 02647 { 02648 /* FUTURE: note this is also a special "montage" option */ 02649 CLIWandWarnReplaced("-statistic Mode"); 02650 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1); 02651 break; 02652 } 02653 if (LocaleCompare("modulate",option+1) == 0) 02654 { 02655 if (IfMagickFalse(IsGeometry(arg1))) 02656 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02657 (void) ModulateImage(_image,arg1,_exception); 02658 break; 02659 } 02660 if (LocaleCompare("monitor",option+1) == 0) 02661 { 02662 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress : 02663 (MagickProgressMonitor) NULL,(void *) NULL); 02664 break; 02665 } 02666 if (LocaleCompare("monochrome",option+1) == 0) 02667 { 02668 (void) SetImageType(_image,BilevelType,_exception); 02669 break; 02670 } 02671 if (LocaleCompare("morphology",option+1) == 0) 02672 { 02673 char 02674 token[MaxTextExtent]; 02675 02676 const char 02677 *p; 02678 02679 KernelInfo 02680 *kernel; 02681 02682 ssize_t 02683 iterations; 02684 02685 p=arg1; 02686 GetMagickToken(p,&p,token); 02687 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token); 02688 if ( parse < 0 ) 02689 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction", 02690 option,arg1); 02691 iterations=1L; 02692 GetMagickToken(p,&p,token); 02693 if ((*p == ':') || (*p == ',')) 02694 GetMagickToken(p,&p,token); 02695 if ((*p != '\0')) 02696 iterations=(ssize_t) StringToLong(p); 02697 kernel=AcquireKernelInfo(arg2); 02698 if (kernel == (KernelInfo *) NULL) 02699 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel", 02700 option,arg2); 02701 new_image=MorphologyImage(_image,(MorphologyMethod)parse, 02702 iterations,kernel,_exception); 02703 kernel=DestroyKernelInfo(kernel); 02704 break; 02705 } 02706 if (LocaleCompare("motion-blur",option+1) == 0) 02707 { 02708 flags=ParseGeometry(arg1,&geometry_info); 02709 if ((flags & (RhoValue|SigmaValue)) == 0) 02710 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02711 if ((flags & SigmaValue) == 0) 02712 geometry_info.sigma=1.0; 02713 new_image=MotionBlurImage(_image,geometry_info.rho, 02714 geometry_info.sigma,geometry_info.xi,_exception); 02715 break; 02716 } 02717 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02718 } 02719 case 'n': 02720 { 02721 if (LocaleCompare("negate",option+1) == 0) 02722 { 02723 (void) NegateImage(_image, plus_alt_op, _exception); 02724 break; 02725 } 02726 if (LocaleCompare("noise",option+1) == 0) 02727 { 02728 double 02729 attenuate; 02730 02731 const char* 02732 value; 02733 02734 if (IfNormalOp) 02735 { 02736 CLIWandWarnReplaced("-statistic NonPeak"); 02737 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1); 02738 break; 02739 } 02740 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1); 02741 if ( parse < 0 ) 02742 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType", 02743 option,arg1); 02744 attenuate=1.0; 02745 value=GetImageOption(_image_info,"attenuate"); 02746 if (value != (const char *) NULL) 02747 attenuate=StringToDouble(value,(char **) NULL); 02748 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate, 02749 _exception); 02750 break; 02751 } 02752 if (LocaleCompare("normalize",option+1) == 0) 02753 { 02754 (void) NormalizeImage(_image,_exception); 02755 break; 02756 } 02757 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02758 } 02759 case 'o': 02760 { 02761 if (LocaleCompare("opaque",option+1) == 0) 02762 { 02763 PixelInfo 02764 target; 02765 02766 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception); 02767 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op, 02768 _exception); 02769 break; 02770 } 02771 if (LocaleCompare("ordered-dither",option+1) == 0) 02772 { 02773 (void) OrderedPosterizeImage(_image,arg1,_exception); 02774 break; 02775 } 02776 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02777 } 02778 case 'p': 02779 { 02780 if (LocaleCompare("paint",option+1) == 0) 02781 { 02782 flags=ParseGeometry(arg1,&geometry_info); 02783 if ((flags & (RhoValue|SigmaValue)) == 0) 02784 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02785 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma, 02786 _exception); 02787 break; 02788 } 02789 if (LocaleCompare("polaroid",option+1) == 0) 02790 { 02791 const char 02792 *caption; 02793 02794 double 02795 angle; 02796 02797 if (IfPlusOp) { 02798 RandomInfo 02799 *random_info; 02800 02801 random_info=AcquireRandomInfo(); 02802 angle=22.5*(GetPseudoRandomValue(random_info)-0.5); 02803 random_info=DestroyRandomInfo(random_info); 02804 } 02805 else { 02806 flags=ParseGeometry(arg1,&geometry_info); 02807 if ((flags & RhoValue) == 0) 02808 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02809 angle=geometry_info.rho; 02810 } 02811 caption=GetImageProperty(_image,"caption",_exception); 02812 new_image=PolaroidImage(_image,_draw_info,caption,angle, 02813 _image->interpolate,_exception); 02814 break; 02815 } 02816 if (LocaleCompare("posterize",option+1) == 0) 02817 { 02818 flags=ParseGeometry(arg1,&geometry_info); 02819 if ((flags & RhoValue) == 0) 02820 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02821 (void) PosterizeImage(_image,(size_t) geometry_info.rho, 02822 _quantize_info->dither,_exception); 02823 break; 02824 } 02825 if (LocaleCompare("preview",option+1) == 0) 02826 { 02827 /* FUTURE: should be a 'Genesis' option? 02828 Option however is also in WandSettingOptionInfo() 02829 Why??? 02830 */ 02831 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1); 02832 if ( parse < 0 ) 02833 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType", 02834 option,arg1); 02835 new_image=PreviewImage(_image,(PreviewType)parse,_exception); 02836 break; 02837 } 02838 if (LocaleCompare("profile",option+1) == 0) 02839 { 02840 const char 02841 *name; 02842 02843 const StringInfo 02844 *profile; 02845 02846 Image 02847 *profile_image; 02848 02849 ImageInfo 02850 *profile_info; 02851 02852 if (IfPlusOp) 02853 { /* Remove a profile from the _image. */ 02854 (void) ProfileImage(_image,arg1,(const unsigned char *) 02855 NULL,0,_exception); 02856 break; 02857 } 02858 /* Associate a profile with the _image. */ 02859 profile_info=CloneImageInfo(_image_info); 02860 profile=GetImageProfile(_image,"iptc"); 02861 if (profile != (StringInfo *) NULL) 02862 profile_info->profile=(void *) CloneStringInfo(profile); 02863 profile_image=GetImageCache(profile_info,arg1,_exception); 02864 profile_info=DestroyImageInfo(profile_info); 02865 if (profile_image == (Image *) NULL) 02866 { 02867 StringInfo 02868 *profile; 02869 02870 profile_info=CloneImageInfo(_image_info); 02871 (void) CopyMagickString(profile_info->filename,arg1, 02872 MaxTextExtent); 02873 profile=FileToStringInfo(profile_info->filename,~0UL,_exception); 02874 if (profile != (StringInfo *) NULL) 02875 { 02876 (void) ProfileImage(_image,profile_info->magick, 02877 GetStringInfoDatum(profile),(size_t) 02878 GetStringInfoLength(profile),_exception); 02879 profile=DestroyStringInfo(profile); 02880 } 02881 profile_info=DestroyImageInfo(profile_info); 02882 break; 02883 } 02884 ResetImageProfileIterator(profile_image); 02885 name=GetNextImageProfile(profile_image); 02886 while (name != (const char *) NULL) 02887 { 02888 profile=GetImageProfile(profile_image,name); 02889 if (profile != (StringInfo *) NULL) 02890 (void) ProfileImage(_image,name,GetStringInfoDatum(profile), 02891 (size_t) GetStringInfoLength(profile),_exception); 02892 name=GetNextImageProfile(profile_image); 02893 } 02894 profile_image=DestroyImage(profile_image); 02895 break; 02896 } 02897 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02898 } 02899 case 'r': 02900 { 02901 if (LocaleCompare("radial-blur",option+1) == 0) 02902 { 02903 flags=ParseGeometry(arg1,&geometry_info); 02904 if ((flags & RhoValue) == 0) 02905 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02906 new_image=RadialBlurImage(_image,geometry_info.rho,_exception); 02907 break; 02908 } 02909 if (LocaleCompare("raise",option+1) == 0) 02910 { 02911 if (IfMagickFalse(IsGeometry(arg1))) 02912 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02913 flags=ParsePageGeometry(_image,arg1,&geometry,_exception); 02914 if ((flags & SigmaValue) == 0) 02915 geometry.height=geometry.width; 02916 (void) RaiseImage(_image,&geometry,normal_op,_exception); 02917 break; 02918 } 02919 if (LocaleCompare("random-threshold",option+1) == 0) 02920 { 02921 if (IfMagickFalse(IsGeometry(arg1))) 02922 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02923 (void) RandomThresholdImage(_image,arg1,_exception); 02924 break; 02925 } 02926 if (LocaleCompare("recolor",option+1) == 0) 02927 { 02928 CLIWandWarnReplaced("-color-matrix"); 02929 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL); 02930 } 02931 if (LocaleCompare("remap",option+1) == 0) 02932 { 02933 Image 02934 *remap_image; 02935 02936 remap_image=GetImageCache(_image_info,arg1,_exception); 02937 if (remap_image == (Image *) NULL) 02938 break; 02939 (void) RemapImage(_quantize_info,_image,remap_image,_exception); 02940 remap_image=DestroyImage(remap_image); 02941 break; 02942 } 02943 if (LocaleCompare("repage",option+1) == 0) 02944 { 02945 if (IfNormalOp) 02946 { 02947 if (IfMagickFalse(IsGeometry(arg1))) 02948 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option, 02949 arg1); 02950 (void) ResetImagePage(_image,arg1); 02951 } 02952 else 02953 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page); 02954 break; 02955 } 02956 if (LocaleCompare("resample",option+1) == 0) 02957 { 02958 /* FUTURE: Roll into a resize special operation */ 02959 flags=ParseGeometry(arg1,&geometry_info); 02960 if ((flags & (RhoValue|SigmaValue)) == 0) 02961 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02962 if ((flags & SigmaValue) == 0) 02963 geometry_info.sigma=geometry_info.rho; 02964 new_image=ResampleImage(_image,geometry_info.rho, 02965 geometry_info.sigma,_image->filter,_exception); 02966 break; 02967 } 02968 if (LocaleCompare("resize",option+1) == 0) 02969 { 02970 if (IfMagickFalse(IsGeometry(arg1))) 02971 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02972 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception); 02973 new_image=ResizeImage(_image,geometry.width,geometry.height, 02974 _image->filter,_exception); 02975 break; 02976 } 02977 if (LocaleCompare("roll",option+1) == 0) 02978 { 02979 if (IfMagickFalse(IsGeometry(arg1))) 02980 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02981 (void) ParsePageGeometry(_image,arg1,&geometry,_exception); 02982 new_image=RollImage(_image,geometry.x,geometry.y,_exception); 02983 break; 02984 } 02985 if (LocaleCompare("rotate",option+1) == 0) 02986 { 02987 flags=ParseGeometry(arg1,&geometry_info); 02988 if ((flags & RhoValue) == 0) 02989 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 02990 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows)) 02991 break; 02992 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows)) 02993 break; 02994 new_image=RotateImage(_image,geometry_info.rho,_exception); 02995 break; 02996 } 02997 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 02998 } 02999 case 's': 03000 { 03001 if (LocaleCompare("sample",option+1) == 0) 03002 { 03003 /* FUTURE: Roll into a resize special operator */ 03004 if (IfMagickFalse(IsGeometry(arg1))) 03005 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03006 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception); 03007 new_image=SampleImage(_image,geometry.width,geometry.height, 03008 _exception); 03009 break; 03010 } 03011 if (LocaleCompare("scale",option+1) == 0) 03012 { 03013 /* FUTURE: Roll into a resize special operator */ 03014 if (IfMagickFalse(IsGeometry(arg1))) 03015 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03016 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception); 03017 new_image=ScaleImage(_image,geometry.width,geometry.height, 03018 _exception); 03019 break; 03020 } 03021 if (LocaleCompare("segment",option+1) == 0) 03022 { 03023 flags=ParseGeometry(arg1,&geometry_info); 03024 if ((flags & (RhoValue|SigmaValue)) == 0) 03025 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03026 if ((flags & SigmaValue) == 0) 03027 geometry_info.sigma=1.0; 03028 (void) SegmentImage(_image,_image->colorspace, 03029 _image_info->verbose,geometry_info.rho,geometry_info.sigma, 03030 _exception); 03031 break; 03032 } 03033 if (LocaleCompare("selective-blur",option+1) == 0) 03034 { 03035 flags=ParseGeometry(arg1,&geometry_info); 03036 if ((flags & (RhoValue|SigmaValue)) == 0) 03037 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03038 if ((flags & SigmaValue) == 0) 03039 geometry_info.sigma=1.0; 03040 if ((flags & PercentValue) != 0) 03041 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0; 03042 new_image=SelectiveBlurImage(_image,geometry_info.rho, 03043 geometry_info.sigma,geometry_info.xi,_exception); 03044 break; 03045 } 03046 if (LocaleCompare("separate",option+1) == 0) 03047 { 03048 /* WARNING: This can generate multiple images! */ 03049 /* FUTURE - this may be replaced by a "-channel" method */ 03050 new_image=SeparateImages(_image,_exception); 03051 break; 03052 } 03053 if (LocaleCompare("sepia-tone",option+1) == 0) 03054 { 03055 if (IfMagickFalse(IsGeometry(arg1))) 03056 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03057 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1, 03058 (double) QuantumRange+1.0),_exception); 03059 break; 03060 } 03061 if (LocaleCompare("set",option+1) == 0) 03062 { 03063 char 03064 *value; 03065 03066 if (IfPlusOp) { 03067 if (LocaleNCompare(arg1,"registry:",9) == 0) 03068 (void) DeleteImageRegistry(arg1+9); 03069 else 03070 if (LocaleNCompare(arg1,"option:",7) == 0) 03071 { 03072 (void) DeleteImageOption(_image_info,arg1+7); 03073 (void) DeleteImageArtifact(_image,arg1+7); 03074 } 03075 else 03076 (void) DeleteImageProperty(_image,arg1); 03077 break; 03078 } 03079 value=InterpretImageProperties(_image_info,_image,arg2,_exception); 03080 if (value == (char *) NULL) 03081 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure", 03082 option); 03083 if (LocaleNCompare(arg1,"registry:",9) == 0) 03084 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception); 03085 else 03086 if (LocaleNCompare(arg1,"option:",7) == 0) 03087 { 03088 (void) SetImageOption(_image_info,arg1+7,value); 03089 (void) SetImageArtifact(_image,arg1+7,value); 03090 } 03091 else 03092 (void) SetImageProperty(_image,arg1,value,_exception); 03093 value=DestroyString(value); 03094 break; 03095 } 03096 if (LocaleCompare("shade",option+1) == 0) 03097 { 03098 flags=ParseGeometry(arg1,&geometry_info); 03099 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0)) 03100 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03101 new_image=ShadeImage(_image,normal_op,geometry_info.rho, 03102 geometry_info.sigma,_exception); 03103 break; 03104 } 03105 if (LocaleCompare("shadow",option+1) == 0) 03106 { 03107 flags=ParseGeometry(arg1,&geometry_info); 03108 if ((flags & (RhoValue|SigmaValue)) == 0) 03109 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03110 if ((flags & SigmaValue) == 0) 03111 geometry_info.sigma=1.0; 03112 if ((flags & XiValue) == 0) 03113 geometry_info.xi=4.0; 03114 if ((flags & PsiValue) == 0) 03115 geometry_info.psi=4.0; 03116 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma, 03117 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) 03118 ceil(geometry_info.psi-0.5),_exception); 03119 break; 03120 } 03121 if (LocaleCompare("sharpen",option+1) == 0) 03122 { 03123 flags=ParseGeometry(arg1,&geometry_info); 03124 if ((flags & (RhoValue|SigmaValue)) == 0) 03125 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03126 if ((flags & SigmaValue) == 0) 03127 geometry_info.sigma=1.0; 03128 if ((flags & XiValue) == 0) 03129 geometry_info.xi=0.0; 03130 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma, 03131 _exception); 03132 break; 03133 } 03134 if (LocaleCompare("shave",option+1) == 0) 03135 { 03136 if (IfMagickFalse(IsGeometry(arg1))) 03137 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03138 flags=ParsePageGeometry(_image,arg1,&geometry,_exception); 03139 new_image=ShaveImage(_image,&geometry,_exception); 03140 break; 03141 } 03142 if (LocaleCompare("shear",option+1) == 0) 03143 { 03144 flags=ParseGeometry(arg1,&geometry_info); 03145 if ((flags & RhoValue) == 0) 03146 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03147 if ((flags & SigmaValue) == 0) 03148 geometry_info.sigma=geometry_info.rho; 03149 new_image=ShearImage(_image,geometry_info.rho, 03150 geometry_info.sigma,_exception); 03151 break; 03152 } 03153 if (LocaleCompare("sigmoidal-contrast",option+1) == 0) 03154 { 03155 flags=ParseGeometry(arg1,&geometry_info); 03156 if ((flags & RhoValue) == 0) 03157 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03158 if ((flags & SigmaValue) == 0) 03159 geometry_info.sigma=(double) QuantumRange/2.0; 03160 if ((flags & PercentValue) != 0) 03161 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/ 03162 100.0; 03163 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho, 03164 geometry_info.sigma,_exception); 03165 break; 03166 } 03167 if (LocaleCompare("sketch",option+1) == 0) 03168 { 03169 flags=ParseGeometry(arg1,&geometry_info); 03170 if ((flags & (RhoValue|SigmaValue)) == 0) 03171 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03172 if ((flags & SigmaValue) == 0) 03173 geometry_info.sigma=1.0; 03174 new_image=SketchImage(_image,geometry_info.rho, 03175 geometry_info.sigma,geometry_info.xi,_exception); 03176 break; 03177 } 03178 if (LocaleCompare("solarize",option+1) == 0) 03179 { 03180 if (IfMagickFalse(IsGeometry(arg1))) 03181 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03182 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double) 03183 QuantumRange+1.0),_exception); 03184 break; 03185 } 03186 if (LocaleCompare("sparse-color",option+1) == 0) 03187 { 03188 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1); 03189 if ( parse < 0 ) 03190 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod", 03191 option,arg1); 03192 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2, 03193 _exception); 03194 break; 03195 } 03196 if (LocaleCompare("splice",option+1) == 0) 03197 { 03198 if (IfMagickFalse(IsGeometry(arg1))) 03199 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03200 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception); 03201 new_image=SpliceImage(_image,&geometry,_exception); 03202 break; 03203 } 03204 if (LocaleCompare("spread",option+1) == 0) 03205 { 03206 flags=ParseGeometry(arg1,&geometry_info); 03207 if ((flags & RhoValue) == 0) 03208 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2); 03209 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate, 03210 _exception); 03211 break; 03212 } 03213 if (LocaleCompare("statistic",option+1) == 0) 03214 { 03215 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1); 03216 if ( parse < 0 ) 03217 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType", 03218 option,arg1); 03219 flags=ParseGeometry(arg2,&geometry_info); 03220 if ((flags & RhoValue) == 0) 03221 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2); 03222 if ((flags & SigmaValue) == 0) 03223 geometry_info.sigma=geometry_info.rho; 03224 new_image=StatisticImage(_image,(StatisticType)parse, 03225 (size_t) geometry_info.rho,(size_t) geometry_info.sigma, 03226 _exception); 03227 break; 03228 } 03229 if (LocaleCompare("strip",option+1) == 0) 03230 { 03231 (void) StripImage(_image,_exception); 03232 break; 03233 } 03234 if (LocaleCompare("swirl",option+1) == 0) 03235 { 03236 flags=ParseGeometry(arg2,&geometry_info); 03237 if ((flags & RhoValue) == 0) 03238 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2); 03239 new_image=SwirlImage(_image,geometry_info.rho, 03240 _image->interpolate,_exception); 03241 break; 03242 } 03243 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03244 } 03245 case 't': 03246 { 03247 if (LocaleCompare("threshold",option+1) == 0) 03248 { 03249 double 03250 threshold; 03251 03252 threshold=(double) QuantumRange/2; 03253 if (normal_op) { 03254 if (IfMagickFalse(IsGeometry(arg1))) 03255 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03256 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0); 03257 } 03258 (void) BilevelImage(_image,threshold,_exception); 03259 break; 03260 } 03261 if (LocaleCompare("thumbnail",option+1) == 0) 03262 { 03263 if (IfMagickFalse(IsGeometry(arg1))) 03264 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03265 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception); 03266 new_image=ThumbnailImage(_image,geometry.width,geometry.height, 03267 _exception); 03268 break; 03269 } 03270 if (LocaleCompare("tint",option+1) == 0) 03271 { 03272 if (IfMagickFalse(IsGeometry(arg1))) 03273 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03274 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception); 03275 break; 03276 } 03277 if (LocaleCompare("transform",option+1) == 0) 03278 { 03279 CLIWandWarnReplaced("+distort AffineProjection"); 03280 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception); 03281 break; 03282 } 03283 if (LocaleCompare("transparent",option+1) == 0) 03284 { 03285 PixelInfo 03286 target; 03287 03288 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception); 03289 (void) TransparentPaintImage(_image,&target,(Quantum) 03290 TransparentAlpha,plus_alt_op,_exception); 03291 break; 03292 } 03293 if (LocaleCompare("transpose",option+1) == 0) 03294 { 03295 new_image=TransposeImage(_image,_exception); 03296 break; 03297 } 03298 if (LocaleCompare("transverse",option+1) == 0) 03299 { 03300 new_image=TransverseImage(_image,_exception); 03301 break; 03302 } 03303 if (LocaleCompare("trim",option+1) == 0) 03304 { 03305 new_image=TrimImage(_image,_exception); 03306 break; 03307 } 03308 if (LocaleCompare("type",option+1) == 0) 03309 { 03310 /* Note that "type" setting should have already been defined */ 03311 (void) SetImageType(_image,_image_info->type,_exception); 03312 break; 03313 } 03314 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03315 } 03316 case 'u': 03317 { 03318 if (LocaleCompare("unique",option+1) == 0) 03319 { 03320 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? 03321 Option is not documented, bt appears to be for "identify". 03322 We may need a identify specific verbose! 03323 */ 03324 if (plus_alt_op) { 03325 (void) DeleteImageArtifact(_image,"identify:unique-colors"); 03326 break; 03327 } 03328 (void) SetImageArtifact(_image,"identify:unique-colors","true"); 03329 (void) SetImageArtifact(_image,"verbose","true"); 03330 break; 03331 } 03332 if (LocaleCompare("unique-colors",option+1) == 0) 03333 { 03334 new_image=UniqueImageColors(_image,_exception); 03335 break; 03336 } 03337 if (LocaleCompare("unsharp",option+1) == 0) 03338 { 03339 flags=ParseGeometry(arg1,&geometry_info); 03340 if ((flags & (RhoValue|SigmaValue)) == 0) 03341 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03342 if ((flags & SigmaValue) == 0) 03343 geometry_info.sigma=1.0; 03344 if ((flags & XiValue) == 0) 03345 geometry_info.xi=1.0; 03346 if ((flags & PsiValue) == 0) 03347 geometry_info.psi=0.05; 03348 new_image=UnsharpMaskImage(_image,geometry_info.rho, 03349 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception); 03350 break; 03351 } 03352 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03353 } 03354 case 'v': 03355 { 03356 if (LocaleCompare("verbose",option+1) == 0) 03357 { 03358 /* FUTURE: move to SyncImageSettings() and AcquireImage()??? 03359 three places! ImageArtifact ImageOption _image_info->verbose 03360 Some how new images also get this artifact! 03361 */ 03362 (void) SetImageArtifact(_image,option+1, 03363 IfNormalOp ? "true" : "false" ); 03364 break; 03365 } 03366 if (LocaleCompare("vignette",option+1) == 0) 03367 { 03368 flags=ParseGeometry(arg1,&geometry_info); 03369 if ((flags & (RhoValue|SigmaValue)) == 0) 03370 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03371 if ((flags & SigmaValue) == 0) 03372 geometry_info.sigma=1.0; 03373 if ((flags & XiValue) == 0) 03374 geometry_info.xi=0.1*_image->columns; 03375 if ((flags & PsiValue) == 0) 03376 geometry_info.psi=0.1*_image->rows; 03377 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma, 03378 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) 03379 ceil(geometry_info.psi-0.5),_exception); 03380 break; 03381 } 03382 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03383 } 03384 case 'w': 03385 { 03386 if (LocaleCompare("wave",option+1) == 0) 03387 { 03388 flags=ParseGeometry(arg1,&geometry_info); 03389 if ((flags & (RhoValue|SigmaValue)) == 0) 03390 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03391 if ((flags & SigmaValue) == 0) 03392 geometry_info.sigma=1.0; 03393 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma, 03394 _image->interpolate,_exception); 03395 break; 03396 } 03397 if (LocaleCompare("white-threshold",option+1) == 0) 03398 { 03399 if (IfMagickFalse(IsGeometry(arg1))) 03400 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03401 (void) WhiteThresholdImage(_image,arg1,_exception); 03402 break; 03403 } 03404 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03405 } 03406 default: 03407 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03408 } 03409 /* clean up percent escape interpreted strings */ 03410 if (arg1 != arg1n ) 03411 arg1=DestroyString((char *)arg1); 03412 if (arg2 != arg2n ) 03413 arg2=DestroyString((char *)arg2); 03414 03415 /* Replace current image with any image that was generated 03416 and set image point to last image (so image->next is correct) */ 03417 if (new_image != (Image *) NULL) 03418 ReplaceImageInListReturnLast(&_image,new_image); 03419 03420 return; 03421 #undef _image_info 03422 #undef _draw_info 03423 #undef _quantize_info 03424 #undef _image 03425 #undef _exception 03426 #undef IfNormalOp 03427 #undef IfPlusOp 03428 #undef normal_op 03429 #undef plus_alt_op 03430 } 03431 03432 WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand, 03433 const char *option, const char *arg1, const char *arg2) 03434 { 03435 size_t 03436 n, 03437 i; 03438 03439 assert(cli_wand != (MagickCLI *) NULL); 03440 assert(cli_wand->signature == WandSignature); 03441 assert(cli_wand->wand.signature == WandSignature); 03442 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */ 03443 if (IfMagickTrue(cli_wand->wand.debug)) 03444 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); 03445 03446 #if !USE_WAND_METHODS 03447 /* FUTURE add appropriate tracing */ 03448 i=0; 03449 n=GetImageListLength(cli_wand->wand.images); 03450 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images); 03451 while (1) { 03452 i++; 03453 CLISimpleOperatorImage(cli_wand, option, arg1, arg2); 03454 if ( cli_wand->wand.images->next == (Image *) NULL ) 03455 break; 03456 cli_wand->wand.images=cli_wand->wand.images->next; 03457 } 03458 assert( i == n ); 03459 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images); 03460 #else 03461 MagickResetIterator(&cli_wand->wand); 03462 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) ) 03463 CLISimpleOperatorImage(cli_wand, option, arg1, arg2); 03464 MagickResetIterator(&cli_wand->wand); 03465 #endif 03466 return; 03467 } 03468 03469 /* 03470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03471 % % 03472 % % 03473 % % 03474 + C L I L i s t O p e r a t o r I m a g e s % 03475 % % 03476 % % 03477 % % 03478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03479 % 03480 % CLIListOperatorImages() applies a single operation that is apply to the 03481 % entire image list as a whole. The result is often a complete replacment 03482 % of the image list with a completely new list, or just a single image. 03483 % 03484 % The format of the MogrifyImage method is: 03485 % 03486 % void CLIListOperatorImages(MagickCLI *cli_wand, 03487 % const char *option, const char *arg1, const char *arg2) 03488 % 03489 % A description of each parameter follows: 03490 % 03491 % o cli_wand: structure holding settings to be applied 03492 % 03493 % o option: The option string for the operation 03494 % 03495 % o arg1, arg2: optional argument strings to the operation 03496 % arg2 is currently not used 03497 % 03498 */ 03499 WandExport void CLIListOperatorImages(MagickCLI *cli_wand, 03500 const char *option,const char *arg1n, const char *arg2n) 03501 { 03502 ssize_t 03503 parse; 03504 03505 Image 03506 *new_images; 03507 03508 const char /* For percent escape interpretImageProperties() */ 03509 *arg1, 03510 *arg2; 03511 03512 #define _image_info (cli_wand->wand.image_info) 03513 #define _images (cli_wand->wand.images) 03514 #define _exception (cli_wand->wand.exception) 03515 #define _draw_info (cli_wand->draw_info) 03516 #define _quantize_info (cli_wand->quantize_info) 03517 #define _process_flags (cli_wand->process_flags) 03518 #define _option_type ((CommandOptionFlags) cli_wand->command->flags) 03519 #define IfNormalOp (*option=='-') 03520 #define IfPlusOp (*option!='-') 03521 #define normal_op IsMagickTrue(IfNormalOp) 03522 03523 assert(cli_wand != (MagickCLI *) NULL); 03524 assert(cli_wand->signature == WandSignature); 03525 assert(cli_wand->wand.signature == WandSignature); 03526 assert(_images != (Image *) NULL); /* _images must be present */ 03527 if (IfMagickTrue(cli_wand->wand.debug)) 03528 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); 03529 03530 /* Interpret Percent Escapes in Arguments - using first image */ 03531 arg1 = arg1n; 03532 arg2 = arg2n; 03533 if ( (((_process_flags & ProcessInterpretProperities) != 0 ) 03534 || ((_option_type & AlwaysInterpretArgsFlag) != 0) 03535 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) { 03536 /* Interpret Percent escapes in argument 1 */ 03537 if (arg1n != (char *) NULL) { 03538 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception); 03539 if (arg1 == (char *) NULL) { 03540 CLIWandException(OptionWarning,"InterpretPropertyFailure",option); 03541 arg1=arg1n; /* use the given argument as is */ 03542 } 03543 } 03544 if (arg2n != (char *) NULL) { 03545 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception); 03546 if (arg2 == (char *) NULL) { 03547 CLIWandException(OptionWarning,"InterpretPropertyFailure",option); 03548 arg2=arg2n; /* use the given argument as is */ 03549 } 03550 } 03551 } 03552 #undef _option_type 03553 03554 #if 0 03555 (void) FormatLocaleFile(stderr, 03556 "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2); 03557 #endif 03558 03559 03560 new_images=NewImageList(); 03561 03562 switch (*(option+1)) 03563 { 03564 case 'a': 03565 { 03566 if (LocaleCompare("append",option+1) == 0) 03567 { 03568 new_images=AppendImages(_images,normal_op,_exception); 03569 break; 03570 } 03571 if (LocaleCompare("average",option+1) == 0) 03572 { 03573 CLIWandWarnReplaced("-evaluate-sequence Mean"); 03574 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL); 03575 break; 03576 } 03577 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03578 } 03579 case 'c': 03580 { 03581 if (LocaleCompare("channel-fx",option+1) == 0) 03582 { 03583 new_images=ChannelFxImage(_images,arg1,_exception); 03584 break; 03585 } 03586 if (LocaleCompare("clut",option+1) == 0) 03587 { 03588 Image 03589 *clut_image; 03590 03591 /* FUTURE - make this a compose option, and thus can be used 03592 with layers compose or even compose last image over all other 03593 _images. 03594 */ 03595 new_images=RemoveFirstImageFromList(&_images); 03596 clut_image=RemoveLastImageFromList(&_images); 03597 /* FUTURE - produce Exception, rather than silent fail */ 03598 if (clut_image == (Image *) NULL) 03599 break; 03600 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception); 03601 clut_image=DestroyImage(clut_image); 03602 break; 03603 } 03604 if (LocaleCompare("coalesce",option+1) == 0) 03605 { 03606 new_images=CoalesceImages(_images,_exception); 03607 break; 03608 } 03609 if (LocaleCompare("combine",option+1) == 0) 03610 { 03611 /* FUTURE - this may be replaced by a 'channel' method */ 03612 new_images=CombineImages(_images,_exception); 03613 break; 03614 } 03615 if (LocaleCompare("composite",option+1) == 0) 03616 { 03617 CompositeOperator 03618 compose; 03619 03620 const char* 03621 value; 03622 03623 MagickBooleanType 03624 clip_to_self; 03625 03626 Image 03627 *mask_image, 03628 *source_image; 03629 03630 RectangleInfo 03631 geometry; 03632 03633 /* Compose value from "-compose" option only */ 03634 value=GetImageOption(_image_info,"compose"); 03635 if (value == (const char *) NULL) 03636 compose=OverCompositeOp; /* use Over not source_image->compose */ 03637 else 03638 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions, 03639 MagickFalse,value); 03640 03641 /* Get "clip-to-self" expert setting (false is normal) */ 03642 value=GetImageOption(_image_info,"compose:clip-to-self"); 03643 if (value == (const char *) NULL) 03644 clip_to_self=MagickTrue; 03645 else 03646 clip_to_self=IsStringTrue(GetImageOption(_image_info, 03647 "compose:clip-to-self")); /* if this is true */ 03648 value=GetImageOption(_image_info,"compose:outside-overlay"); 03649 if (value != (const char *) NULL) { /* or this false */ 03650 /* FUTURE: depreciate warning for "compose:outside-overlay"*/ 03651 clip_to_self= IsMagickFalse(IsStringNotFalse(value)); 03652 } 03653 03654 new_images=RemoveFirstImageFromList(&_images); 03655 source_image=RemoveFirstImageFromList(&_images); 03656 if (source_image == (Image *) NULL) 03657 break; /* FUTURE - produce Exception, rather than silent fail */ 03658 03659 /* FUTURE - this should not be here! - should be part of -geometry */ 03660 (void) TransformImage(&source_image,(char *) NULL, 03661 source_image->geometry,_exception); 03662 03663 SetGeometry(source_image,&geometry); 03664 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry); 03665 GravityAdjustGeometry(new_images->columns,new_images->rows, 03666 new_images->gravity, &geometry); 03667 03668 mask_image=RemoveFirstImageFromList(&_images); 03669 if (mask_image != (Image *) NULL) 03670 { /* handle a third write mask image */ 03671 if ((compose == DisplaceCompositeOp) || 03672 (compose == DistortCompositeOp)) { 03673 /* Merge Y displacement into X displace/distort map. */ 03674 (void) CompositeImage(source_image,mask_image, 03675 CopyGreenCompositeOp,MagickTrue,0,0,_exception); 03676 mask_image=DestroyImage(mask_image); 03677 } 03678 else { 03679 /* Set a blending mask for the composition. */ 03680 (void) NegateImage(mask_image,MagickFalse,_exception); 03681 (void) SetImageMask(source_image,mask_image,_exception); 03682 mask_image=DestroyImage(mask_image); 03683 } 03684 } 03685 (void) CompositeImage(new_images,source_image,compose,clip_to_self, 03686 geometry.x,geometry.y,_exception); 03687 (void) SetImageMask(new_images,(Image *) NULL,_exception); 03688 source_image=DestroyImage(source_image); 03689 break; 03690 } 03691 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03692 } 03693 case 'd': 03694 { 03695 if (LocaleCompare("deconstruct",option+1) == 0) 03696 { 03697 CLIWandWarnReplaced("-layer CompareAny"); 03698 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL); 03699 break; 03700 } 03701 if (LocaleCompare("delete",option+1) == 0) 03702 { 03703 if (IfNormalOp) 03704 DeleteImages(&_images,arg1,_exception); 03705 else 03706 DeleteImages(&_images,"-1",_exception); 03707 break; 03708 } 03709 if (LocaleCompare("duplicate",option+1) == 0) 03710 { 03711 if (IfNormalOp) 03712 { 03713 const char 03714 *p; 03715 03716 size_t 03717 number_duplicates; 03718 03719 if (IfMagickFalse(IsGeometry(arg1))) 03720 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option, 03721 arg1); 03722 number_duplicates=(size_t) StringToLong(arg1); 03723 p=strchr(arg1,','); 03724 if (p == (const char *) NULL) 03725 new_images=DuplicateImages(_images,number_duplicates,"-1", 03726 _exception); 03727 else 03728 new_images=DuplicateImages(_images,number_duplicates,p, 03729 _exception); 03730 } 03731 else 03732 new_images=DuplicateImages(_images,1,"-1",_exception); 03733 AppendImageToList(&_images, new_images); 03734 new_images=(Image *)NULL; 03735 break; 03736 } 03737 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03738 } 03739 case 'e': 03740 { 03741 if (LocaleCompare("evaluate-sequence",option+1) == 0) 03742 { 03743 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1); 03744 if ( parse < 0 ) 03745 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator", 03746 option,arg1); 03747 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse, 03748 _exception); 03749 break; 03750 } 03751 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03752 } 03753 case 'f': 03754 { 03755 if (LocaleCompare("fft",option+1) == 0) 03756 { 03757 new_images=ForwardFourierTransformImage(_images,normal_op,_exception); 03758 break; 03759 } 03760 if (LocaleCompare("flatten",option+1) == 0) 03761 { 03762 /* REDIRECTED to use -layers flatten instead */ 03763 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL); 03764 break; 03765 } 03766 if (LocaleCompare("fx",option+1) == 0) 03767 { 03768 new_images=FxImage(_images,arg1,_exception); 03769 break; 03770 } 03771 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03772 } 03773 case 'h': 03774 { 03775 if (LocaleCompare("hald-clut",option+1) == 0) 03776 { 03777 /* FUTURE - make this a compose option (and thus layers compose ) 03778 or perhaps compose last image over all other _images. 03779 */ 03780 Image 03781 *hald_image; 03782 03783 new_images=RemoveFirstImageFromList(&_images); 03784 hald_image=RemoveLastImageFromList(&_images); 03785 if (hald_image == (Image *) NULL) 03786 break; 03787 (void) HaldClutImage(new_images,hald_image,_exception); 03788 hald_image=DestroyImage(hald_image); 03789 break; 03790 } 03791 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03792 } 03793 case 'i': 03794 { 03795 if (LocaleCompare("ift",option+1) == 0) 03796 { 03797 Image 03798 *magnitude_image, 03799 *phase_image; 03800 03801 magnitude_image=RemoveFirstImageFromList(&_images); 03802 phase_image=RemoveFirstImageFromList(&_images); 03803 /* FUTURE - produce Exception, rather than silent fail */ 03804 if (phase_image == (Image *) NULL) 03805 break; 03806 new_images=InverseFourierTransformImage(magnitude_image,phase_image, 03807 normal_op,_exception); 03808 magnitude_image=DestroyImage(magnitude_image); 03809 phase_image=DestroyImage(phase_image); 03810 break; 03811 } 03812 if (LocaleCompare("insert",option+1) == 0) 03813 { 03814 Image 03815 *insert_image, 03816 *index_image; 03817 03818 ssize_t 03819 index; 03820 03821 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1))) 03822 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 03823 index=0; 03824 insert_image=RemoveLastImageFromList(&_images); 03825 if (IfNormalOp) 03826 index=(ssize_t) StringToLong(arg1); 03827 index_image=insert_image; 03828 if (index == 0) 03829 PrependImageToList(&_images,insert_image); 03830 else if (index == (ssize_t) GetImageListLength(_images)) 03831 AppendImageToList(&_images,insert_image); 03832 else 03833 { 03834 index_image=GetImageFromList(_images,index-1); 03835 if (index_image == (Image *) NULL) 03836 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1); 03837 InsertImageInList(&index_image,insert_image); 03838 } 03839 _images=GetFirstImageInList(index_image); 03840 break; 03841 } 03842 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03843 } 03844 case 'l': 03845 { 03846 if (LocaleCompare("layers",option+1) == 0) 03847 { 03848 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1); 03849 if ( parse < 0 ) 03850 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod", 03851 option,arg1); 03852 switch ((ImageLayerMethod) parse) 03853 { 03854 case CoalesceLayer: 03855 { 03856 new_images=CoalesceImages(_images,_exception); 03857 break; 03858 } 03859 case CompareAnyLayer: 03860 case CompareClearLayer: 03861 case CompareOverlayLayer: 03862 default: 03863 { 03864 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse, 03865 _exception); 03866 break; 03867 } 03868 case MergeLayer: 03869 case FlattenLayer: 03870 case MosaicLayer: 03871 case TrimBoundsLayer: 03872 { 03873 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse, 03874 _exception); 03875 break; 03876 } 03877 case DisposeLayer: 03878 { 03879 new_images=DisposeImages(_images,_exception); 03880 break; 03881 } 03882 case OptimizeImageLayer: 03883 { 03884 new_images=OptimizeImageLayers(_images,_exception); 03885 break; 03886 } 03887 case OptimizePlusLayer: 03888 { 03889 new_images=OptimizePlusImageLayers(_images,_exception); 03890 break; 03891 } 03892 case OptimizeTransLayer: 03893 { 03894 OptimizeImageTransparency(_images,_exception); 03895 break; 03896 } 03897 case RemoveDupsLayer: 03898 { 03899 RemoveDuplicateLayers(&_images,_exception); 03900 break; 03901 } 03902 case RemoveZeroLayer: 03903 { 03904 RemoveZeroDelayLayers(&_images,_exception); 03905 break; 03906 } 03907 case OptimizeLayer: 03908 { /* General Purpose, GIF Animation Optimizer. */ 03909 new_images=CoalesceImages(_images,_exception); 03910 if (new_images == (Image *) NULL) 03911 break; 03912 _images=DestroyImageList(_images); 03913 _images=OptimizeImageLayers(new_images,_exception); 03914 if (_images == (Image *) NULL) 03915 break; 03916 new_images=DestroyImageList(new_images); 03917 OptimizeImageTransparency(_images,_exception); 03918 (void) RemapImages(_quantize_info,_images,(Image *) NULL, 03919 _exception); 03920 break; 03921 } 03922 case CompositeLayer: 03923 { 03924 Image 03925 *source; 03926 03927 RectangleInfo 03928 geometry; 03929 03930 CompositeOperator 03931 compose; 03932 03933 const char* 03934 value; 03935 03936 value=GetImageOption(_image_info,"compose"); 03937 compose=OverCompositeOp; /* Default to Over */ 03938 if (value != (const char *) NULL) 03939 compose=(CompositeOperator) ParseCommandOption( 03940 MagickComposeOptions,MagickFalse,value); 03941 03942 /* Split image sequence at the first 'NULL:' image. */ 03943 source=_images; 03944 while (source != (Image *) NULL) 03945 { 03946 source=GetNextImageInList(source); 03947 if ((source != (Image *) NULL) && 03948 (LocaleCompare(source->magick,"NULL") == 0)) 03949 break; 03950 } 03951 if (source != (Image *) NULL) 03952 { 03953 if ((GetPreviousImageInList(source) == (Image *) NULL) || 03954 (GetNextImageInList(source) == (Image *) NULL)) 03955 source=(Image *) NULL; 03956 else 03957 { /* Separate the two lists, junk the null: image. */ 03958 source=SplitImageList(source->previous); 03959 DeleteImageFromList(&source); 03960 } 03961 } 03962 if (source == (Image *) NULL) 03963 { 03964 (void) ThrowMagickException(_exception,GetMagickModule(), 03965 OptionError,"MissingNullSeparator","layers Composite"); 03966 break; 03967 } 03968 /* Adjust offset with gravity and virtual canvas. */ 03969 SetGeometry(_images,&geometry); 03970 (void) ParseAbsoluteGeometry(_images->geometry,&geometry); 03971 geometry.width=source->page.width != 0 ? 03972 source->page.width : source->columns; 03973 geometry.height=source->page.height != 0 ? 03974 source->page.height : source->rows; 03975 GravityAdjustGeometry(_images->page.width != 0 ? 03976 _images->page.width : _images->columns, 03977 _images->page.height != 0 ? _images->page.height : 03978 _images->rows,_images->gravity,&geometry); 03979 03980 /* Compose the two image sequences together */ 03981 CompositeLayers(_images,compose,source,geometry.x,geometry.y, 03982 _exception); 03983 source=DestroyImageList(source); 03984 break; 03985 } 03986 } 03987 break; 03988 } 03989 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 03990 } 03991 case 'm': 03992 { 03993 if (LocaleCompare("map",option+1) == 0) 03994 { 03995 CLIWandWarnReplaced("+remap"); 03996 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception); 03997 break; 03998 } 03999 if (LocaleCompare("morph",option+1) == 0) 04000 { 04001 Image 04002 *morph_image; 04003 04004 if (IfMagickFalse(IsGeometry(arg1))) 04005 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 04006 morph_image=MorphImages(_images,StringToUnsignedLong(arg1), 04007 _exception); 04008 if (morph_image == (Image *) NULL) 04009 break; 04010 _images=DestroyImageList(_images); 04011 _images=morph_image; 04012 break; 04013 } 04014 if (LocaleCompare("mosaic",option+1) == 0) 04015 { 04016 /* REDIRECTED to use -layers mosaic instead */ 04017 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL); 04018 break; 04019 } 04020 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 04021 } 04022 case 'p': 04023 { 04024 if (LocaleCompare("print",option+1) == 0) 04025 { 04026 (void) FormatLocaleFile(stdout,"%s",arg1); 04027 break; 04028 } 04029 if (LocaleCompare("process",option+1) == 0) 04030 { 04031 /* FUTURE: better parsing using ScriptToken() from string ??? */ 04032 char 04033 **arguments; 04034 04035 int 04036 j, 04037 number_arguments; 04038 04039 arguments=StringToArgv(arg1,&number_arguments); 04040 if (arguments == (char **) NULL) 04041 break; 04042 if (strchr(arguments[1],'=') != (char *) NULL) 04043 { 04044 char 04045 breaker, 04046 quote, 04047 *token; 04048 04049 const char 04050 *arguments; 04051 04052 int 04053 next, 04054 status; 04055 04056 size_t 04057 length; 04058 04059 TokenInfo 04060 *token_info; 04061 04062 /* 04063 Support old style syntax, filter="-option arg1". 04064 */ 04065 length=strlen(arg1); 04066 token=(char *) NULL; 04067 if (~length >= (MaxTextExtent-1)) 04068 token=(char *) AcquireQuantumMemory(length+MaxTextExtent, 04069 sizeof(*token)); 04070 if (token == (char *) NULL) 04071 break; 04072 next=0; 04073 arguments=arg1; 04074 token_info=AcquireTokenInfo(); 04075 status=Tokenizer(token_info,0,token,length,arguments,"","=", 04076 "\"",'\0',&breaker,&next,"e); 04077 token_info=DestroyTokenInfo(token_info); 04078 if (status == 0) 04079 { 04080 const char 04081 *argv; 04082 04083 argv=(&(arguments[next])); 04084 (void) InvokeDynamicImageFilter(token,&_images,1,&argv, 04085 _exception); 04086 } 04087 token=DestroyString(token); 04088 break; 04089 } 04090 (void) SubstituteString(&arguments[1],"-",""); 04091 (void) InvokeDynamicImageFilter(arguments[1],&_images, 04092 number_arguments-2,(const char **) arguments+2,_exception); 04093 for (j=0; j < number_arguments; j++) 04094 arguments[j]=DestroyString(arguments[j]); 04095 arguments=(char **) RelinquishMagickMemory(arguments); 04096 break; 04097 } 04098 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 04099 } 04100 case 'r': 04101 { 04102 if (LocaleCompare("remap",option+1) == 0) 04103 { 04104 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception); 04105 break; 04106 } 04107 if (LocaleCompare("reverse",option+1) == 0) 04108 { 04109 ReverseImageList(&_images); 04110 break; 04111 } 04112 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 04113 } 04114 case 's': 04115 { 04116 if (LocaleCompare("smush",option+1) == 0) 04117 { 04118 /* FUTURE: this option needs more work to make better */ 04119 ssize_t 04120 offset; 04121 04122 if (IfMagickFalse(IsGeometry(arg1))) 04123 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 04124 offset=(ssize_t) StringToLong(arg1); 04125 new_images=SmushImages(_images,normal_op,offset,_exception); 04126 break; 04127 } 04128 if (LocaleCompare("subimage",option+1) == 0) 04129 { 04130 Image 04131 *base_image, 04132 *compare_image; 04133 04134 const char * 04135 value; 04136 04137 MetricType 04138 metric; 04139 04140 double 04141 similarity; 04142 04143 RectangleInfo 04144 offset; 04145 04146 base_image=GetImageFromList(_images,0); 04147 compare_image=GetImageFromList(_images,1); 04148 04149 /* Comparision Metric */ 04150 metric=UndefinedMetric; 04151 value=GetImageOption(_image_info,"metric"); 04152 if (value != (const char *) NULL) 04153 metric=(MetricType) ParseCommandOption(MagickMetricOptions, 04154 MagickFalse,value); 04155 04156 new_images=SimilarityImage(base_image,compare_image,metric, 04157 &offset,&similarity,_exception); 04158 04159 if ( new_images != (Image *)NULL ) { 04160 char 04161 result[MaxTextExtent]; 04162 04163 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity); 04164 (void) SetImageProperty(new_images,"subimage:similarity",result, 04165 _exception); 04166 (void) FormatLocaleString(result,MaxTextExtent,"%+ld", 04167 (long) offset.x); 04168 (void) SetImageProperty(new_images,"subimage:x",result, 04169 _exception); 04170 (void) FormatLocaleString(result,MaxTextExtent,"%+ld", 04171 (long) offset.y); 04172 (void) SetImageProperty(new_images,"subimage:y",result, 04173 _exception); 04174 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld", 04175 (unsigned long) offset.width,(unsigned long) offset.height, 04176 (long) offset.x,(long) offset.y); 04177 (void) SetImageProperty(new_images,"subimage:offset",result, 04178 _exception); 04179 } 04180 break; 04181 } 04182 if (LocaleCompare("swap",option+1) == 0) { 04183 Image 04184 *p, 04185 *q, 04186 *swap; 04187 04188 ssize_t 04189 index, 04190 swap_index; 04191 04192 index=-1; 04193 swap_index=-2; 04194 if (IfNormalOp) { 04195 GeometryInfo 04196 geometry_info; 04197 04198 MagickStatusType 04199 flags; 04200 04201 swap_index=(-1); 04202 flags=ParseGeometry(arg1,&geometry_info); 04203 if ((flags & RhoValue) != 0) 04204 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); 04205 index=(ssize_t) geometry_info.rho; 04206 if ((flags & SigmaValue) != 0) 04207 swap_index=(ssize_t) geometry_info.sigma; 04208 } 04209 p=GetImageFromList(_images,index); 04210 q=GetImageFromList(_images,swap_index); 04211 if ((p == (Image *) NULL) || (q == (Image *) NULL)) { 04212 if (IfNormalOp) 04213 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1) 04214 else 04215 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option); 04216 } 04217 if (p == q) 04218 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1); 04219 swap=CloneImage(p,0,0,MagickTrue,_exception); 04220 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception)); 04221 ReplaceImageInList(&q,swap); 04222 _images=GetFirstImageInList(q); 04223 break; 04224 } 04225 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 04226 } 04227 default: 04228 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); 04229 } 04230 04231 /* clean up percent escape interpreted strings */ 04232 if (arg1 != arg1n ) 04233 arg1=DestroyString((char *)arg1); 04234 if (arg2 != arg2n ) 04235 arg2=DestroyString((char *)arg2); 04236 04237 /* if new image list generated, replace existing image list */ 04238 if (new_images == (Image *) NULL) 04239 return; 04240 _images=DestroyImageList(_images); 04241 _images=GetFirstImageInList(new_images); 04242 return; 04243 04244 #undef _image_info 04245 #undef _images 04246 #undef _exception 04247 #undef _draw_info 04248 #undef _quantize_info 04249 #undef IfNormalOp 04250 #undef IfPlusOp 04251 #undef normal_op 04252 } 04253 04254 /* 04255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 04256 % % 04257 % % 04258 % % 04259 + C L I N o I m a g e O p e r a t i o n s % 04260 % % 04261 % % 04262 % % 04263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 04264 % 04265 % CLINoImageOperator() Applies operations that may not actually need images 04266 % in an image list. 04267 % 04268 % The classic operators of this type is -read, which actually creates images 04269 % even when no images are present. Or image stack operators, which can be 04270 % applied (push or pop) to an empty image list. 04271 % 04272 % Note: unlike other Operators, these may involve other special 'option' 04273 % characters other than '-' or '+', namely parenthesis and braces. 04274 % 04275 % The format of the CLINoImageOption method is: 04276 % 04277 % void CLINoImageOption(MagickCLI *cli_wand,const char *option, 04278 % const char *arg1, const char *arg2) 04279 % 04280 % A description of each parameter follows: 04281 % 04282 % o cli_wand: the main CLI Wand to use. 04283 % 04284 % o option: The special option (with any switch char) to process 04285 % 04286 % o arg1 & arg2: Argument for option, if required 04287 % Currently arg2 is not used. 04288 % 04289 */ 04290 WandExport void CLINoImageOperator(MagickCLI *cli_wand, 04291 const char *option, const char *arg1, const char *magick_unused(arg2)) 04292 { 04293 #define _image_info (cli_wand->wand.image_info) 04294 #define _images (cli_wand->wand.images) 04295 #define _exception (cli_wand->wand.exception) 04296 #define IfNormalOp (*option=='-') 04297 #define IfPlusOp (*option!='-') 04298 04299 assert(cli_wand != (MagickCLI *) NULL); 04300 assert(cli_wand->signature == WandSignature); 04301 assert(cli_wand->wand.signature == WandSignature); 04302 if (IfMagickTrue(cli_wand->wand.debug)) 04303 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); 04304 04305 /* 04306 No-op options (ignore these) 04307 */ 04308 if (LocaleCompare("noop",option+1) == 0) /* no argument */ 04309 return; 04310 if (LocaleCompare("sans",option+1) == 0) /* one argument */ 04311 return; 04312 if (LocaleCompare("sans0",option+1) == 0) /* no argument */ 04313 return; 04314 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */ 04315 return; 04316 /* 04317 Image Reading 04318 */ 04319 if ( ( LocaleCompare("read",option+1) == 0 ) || 04320 ( LocaleCompare("--",option) == 0 ) ) { 04321 #if 0 04322 /* Directly read 'arg1' without filename expansion handling (see below). 04323 */ 04324 # if !USE_WAND_METHODS 04325 Image *new_images; 04326 04327 if (IfMagickTrue(_image_info->ping)) 04328 new_images=PingImages(_image_info,arg1,_exception); 04329 else 04330 new_images=ReadImages(_image_info,arg1,_exception); 04331 AppendImageToList(&_images, new_images); 04332 # else 04333 /* read images using MagickWand method - no ping */ 04334 /* This is not working! - it locks up in a CPU loop! */ 04335 MagickSetLastIterator(&cli_wand->wand); 04336 MagickReadImage(&cli_wand->wand,arg1); 04337 MagickSetFirstIterator(&cli_wand->wand); 04338 # endif 04339 #else 04340 /* Do Filename Expansion for 'arg1' then read all images. 04341 * 04342 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring 04343 * (but attaching to generated argument list) any [...] read modifiers 04344 * that may be present. 04345 * 04346 * For example: correctly expand '*.gif[20x20]' into a list such as 04347 * 'abc.gif[20x20', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]' 04348 * 04349 * NOTE: In IMv6 this was done globally across all images. This 04350 * meant you could include IM options in '@filename' lists, but you 04351 * could not include comments. Doing it only for image read makes 04352 * it far more secure. 04353 */ 04354 int argc; 04355 char **argv; 04356 ssize_t i; 04357 04358 argc = 1; 04359 argv = (char **) &arg1; 04360 04361 /* Expand 'glob' expressions in the given filename. 04362 Expansion handles any 'coder:' prefix, or read modifiers attached 04363 to the filename, including them in the resulting expanded list. 04364 */ 04365 if (IfMagickFalse( ExpandFilenames(&argc,&argv) )) 04366 CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed", 04367 option,GetExceptionMessage(errno)); 04368 04369 /* loop over expanded filename list, and read then all in */ 04370 for (i=0; i<argc; i++) { 04371 Image * 04372 new_images; 04373 #if 0 04374 fprintf(stderr, "DEBUG: Reading image: \"%s\"\n", argv[i]); 04375 #endif 04376 if (IfMagickTrue(_image_info->ping)) 04377 new_images=PingImages(_image_info,argv[i],_exception); 04378 else 04379 new_images=ReadImages(_image_info,argv[i],_exception); 04380 AppendImageToList(&_images, new_images); 04381 } 04382 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */ 04383 #endif 04384 return; 04385 } 04386 /* 04387 Image Writing 04388 Note: Writing a empty image list is valid in specific cases 04389 */ 04390 if (LocaleCompare("write",option+1) == 0) { 04391 char 04392 key[MaxTextExtent]; 04393 04394 Image 04395 *write_images; 04396 04397 ImageInfo 04398 *write_info; 04399 04400 /* Need images, unless a "null:" output coder is used */ 04401 if ( cli_wand->wand.images == (Image *) NULL ) { 04402 if ( LocaleCompare(arg1,"null:") == 0 ) 04403 return; 04404 CLIWandExceptArgReturn(OptionError,"NoImagesForWrite",option,arg1); 04405 } 04406 04407 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1); 04408 (void) DeleteImageRegistry(key); 04409 write_images=_images; 04410 if (IfPlusOp) 04411 write_images=CloneImageList(_images,_exception); 04412 write_info=CloneImageInfo(_image_info); 04413 (void) WriteImages(write_info,write_images,arg1,_exception); 04414 write_info=DestroyImageInfo(write_info); 04415 if (IfPlusOp) 04416 write_images=DestroyImageList(write_images); 04417 return; 04418 } 04419 /* 04420 Parenthesis and Brace operations 04421 */ 04422 if (LocaleCompare("(",option) == 0) { 04423 /* stack 'push' images */ 04424 Stack 04425 *node; 04426 04427 size_t 04428 size; 04429 04430 size=0; 04431 node=cli_wand->image_list_stack; 04432 for ( ; node != (Stack *)NULL; node=node->next) 04433 size++; 04434 if ( size >= MAX_STACK_DEPTH ) 04435 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option); 04436 node=(Stack *) AcquireMagickMemory(sizeof(*node)); 04437 if (node == (Stack *) NULL) 04438 CLIWandExceptionReturn(ResourceLimitFatalError, 04439 "MemoryAllocationFailed",option); 04440 node->data = (void *)cli_wand->wand.images; 04441 cli_wand->wand.images = NewImageList(); 04442 node->next = cli_wand->image_list_stack; 04443 cli_wand->image_list_stack = node; 04444 04445 /* handle respect-parenthesis */ 04446 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info, 04447 "respect-parenthesis")))) 04448 option="{"; /* fall-thru so as to push image settings too */ 04449 else 04450 return; 04451 } 04452 if (LocaleCompare("{",option) == 0) { 04453 /* stack 'push' of image_info settings */ 04454 Stack 04455 *node; 04456 04457 size_t 04458 size; 04459 04460 size=0; 04461 node=cli_wand->image_info_stack; 04462 for ( ; node != (Stack *)NULL; node=node->next) 04463 size++; 04464 if ( size >= MAX_STACK_DEPTH ) 04465 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option); 04466 node=(Stack *) AcquireMagickMemory(sizeof(*node)); 04467 if (node == (Stack *) NULL) 04468 CLIWandExceptionReturn(ResourceLimitFatalError, 04469 "MemoryAllocationFailed",option); 04470 04471 node->data = (void *)cli_wand->wand.image_info; 04472 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info); 04473 if (cli_wand->wand.image_info == (ImageInfo *)NULL) { 04474 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed", 04475 option); 04476 cli_wand->wand.image_info = (ImageInfo *)node->data; 04477 node = (Stack *)RelinquishMagickMemory(node); 04478 return; 04479 } 04480 04481 node->next = cli_wand->image_info_stack; 04482 cli_wand->image_info_stack = node; 04483 04484 return; 04485 } 04486 if (LocaleCompare(")",option) == 0) { 04487 /* pop images from stack */ 04488 Stack 04489 *node; 04490 04491 node = (Stack *)cli_wand->image_list_stack; 04492 if ( node == (Stack *)NULL) 04493 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option); 04494 cli_wand->image_list_stack = node->next; 04495 04496 AppendImageToList((Image **)&node->data,cli_wand->wand.images); 04497 cli_wand->wand.images= (Image *)node->data; 04498 node = (Stack *)RelinquishMagickMemory(node); 04499 04500 /* handle respect-parenthesis - of the previous 'pushed' settings */ 04501 node = cli_wand->image_info_stack; 04502 if ( node != (Stack *)NULL) 04503 { 04504 if (IfMagickTrue(IsStringTrue(GetImageOption( 04505 cli_wand->wand.image_info,"respect-parenthesis")))) 04506 option="}"; /* fall-thru so as to pop image settings too */ 04507 else 04508 return; 04509 } 04510 else 04511 return; 04512 } 04513 if (LocaleCompare("}",option) == 0) { 04514 /* pop image_info settings from stack */ 04515 Stack 04516 *node; 04517 04518 node = (Stack *)cli_wand->image_info_stack; 04519 if ( node == (Stack *)NULL) 04520 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option); 04521 cli_wand->image_info_stack = node->next; 04522 04523 (void) DestroyImageInfo(cli_wand->wand.image_info); 04524 cli_wand->wand.image_info = (ImageInfo *)node->data; 04525 node = (Stack *)RelinquishMagickMemory(node); 04526 04527 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info); 04528 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info); 04529 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info); 04530 04531 return; 04532 } 04533 if (LocaleCompare("clone",option+1) == 0) { 04534 Image 04535 *new_images; 04536 04537 if (*option == '+') 04538 arg1="-1"; 04539 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse))) 04540 CLIWandExceptionReturn(OptionError,"InvalidArgument",option); 04541 if ( cli_wand->image_list_stack == (Stack *)NULL) 04542 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option); 04543 new_images = (Image *)cli_wand->image_list_stack->data; 04544 if (new_images == (Image *) NULL) 04545 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option); 04546 new_images=CloneImages(new_images,arg1,_exception); 04547 if (new_images == (Image *) NULL) 04548 CLIWandExceptionReturn(OptionError,"NoSuchImage",option); 04549 AppendImageToList(&_images,new_images); 04550 return; 04551 } 04552 /* 04553 Informational Operations 04554 */ 04555 if (LocaleCompare("version",option+1) == 0) { 04556 (void) FormatLocaleFile(stdout,"Version: %s\n", 04557 GetMagickVersion((size_t *) NULL)); 04558 (void) FormatLocaleFile(stdout,"Copyright: %s\n", 04559 GetMagickCopyright()); 04560 (void) FormatLocaleFile(stdout,"Features: %s\n\n", 04561 GetMagickFeatures()); 04562 return; 04563 } 04564 if (LocaleCompare("list",option+1) == 0) { 04565 /* FUTURE: This should really be built into the MagickCore 04566 It does not actually require a cli-wand or and images! 04567 */ 04568 ssize_t 04569 list; 04570 04571 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1); 04572 if ( list < 0 ) { 04573 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1); 04574 return; 04575 } 04576 switch (list) 04577 { 04578 case MagickCoderOptions: 04579 { 04580 (void) ListCoderInfo((FILE *) NULL,_exception); 04581 break; 04582 } 04583 case MagickColorOptions: 04584 { 04585 (void) ListColorInfo((FILE *) NULL,_exception); 04586 break; 04587 } 04588 case MagickConfigureOptions: 04589 { 04590 (void) ListConfigureInfo((FILE *) NULL,_exception); 04591 break; 04592 } 04593 case MagickDelegateOptions: 04594 { 04595 (void) ListDelegateInfo((FILE *) NULL,_exception); 04596 break; 04597 } 04598 case MagickFontOptions: 04599 { 04600 (void) ListTypeInfo((FILE *) NULL,_exception); 04601 break; 04602 } 04603 case MagickFormatOptions: 04604 (void) ListMagickInfo((FILE *) NULL,_exception); 04605 break; 04606 case MagickLocaleOptions: 04607 (void) ListLocaleInfo((FILE *) NULL,_exception); 04608 break; 04609 case MagickLogOptions: 04610 (void) ListLogInfo((FILE *) NULL,_exception); 04611 break; 04612 case MagickMagicOptions: 04613 (void) ListMagicInfo((FILE *) NULL,_exception); 04614 break; 04615 case MagickMimeOptions: 04616 (void) ListMimeInfo((FILE *) NULL,_exception); 04617 break; 04618 case MagickModuleOptions: 04619 (void) ListModuleInfo((FILE *) NULL,_exception); 04620 break; 04621 case MagickPolicyOptions: 04622 (void) ListPolicyInfo((FILE *) NULL,_exception); 04623 break; 04624 case MagickResourceOptions: 04625 (void) ListMagickResourceInfo((FILE *) NULL,_exception); 04626 break; 04627 case MagickThresholdOptions: 04628 (void) ListThresholdMaps((FILE *) NULL,_exception); 04629 break; 04630 default: 04631 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list, 04632 _exception); 04633 break; 04634 } 04635 return; 04636 } 04637 04638 #if 0 04639 // Other 'special' options this should handle 04640 // "region" "reset" "arg" 04641 if ( ( process_flags & ProcessUnknownOptionError ) != 0 ) 04642 #endif 04643 CLIWandException(OptionError,"UnrecognizedOption",option); 04644 04645 #undef _image_info 04646 #undef _images 04647 #undef _exception 04648 #undef IfNormalOp 04649 #undef IfPlusOp 04650 } 04651 04652 /* 04653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 04654 % % 04655 % % 04656 % % 04657 + C L I O p t i o n % 04658 % % 04659 % % 04660 % % 04661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 04662 % 04663 % CLIOption() Processes the given option using the given CLI Magick Wand. 04664 % The option arguments can be variable in number, though at this time no more 04665 % that two is actually used by any option (this may change). Excess options 04666 % are simply ignored. 04667 % 04668 % If the cli_wand->command pointer is non-null, then it is assumed that the 04669 % option has already been search for up from the CommandOptions[] table in 04670 % "MagickCore/options.c" using GetCommandOptionInfo(). If not set this 04671 % routine will do the lookup instead. The pointer is reset afterward. 04672 % 04673 % This action allows the caller to lookup and pre-handle any 'special' 04674 % options, (such as implicit reads) before calling this general option 04675 % handler to deal with 'standard' command line options. 04676 % 04677 % The format of the CLIOption method is: 04678 % 04679 % void CLIOption(MagickCLI *cli_wand,const char *option, ...) 04680 % 04681 % A description of each parameter follows: 04682 % 04683 % o cli_wand: the main CLI Wand to use. 04684 % 04685 % o option: The special option (with any switch char) to process 04686 % 04687 % o args: any required arguments for an option (variable number) 04688 % 04689 % Example Usage... 04690 % 04691 % CLIoption(cli_wand,"-read","rose:"); 04692 % CLIoption(cli_wand,"-virtual-pixel","transparent"); 04693 % CLIoption(cli_wand,"-distort","SRT:","30"); 04694 % CLIoption(cli_wand,"-write","rotated_rose.png"); 04695 % 04696 */ 04697 WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...) 04698 { 04699 const char 04700 *arg1, 04701 *arg2; 04702 04703 CommandOptionFlags 04704 option_type; 04705 04706 assert(cli_wand != (MagickCLI *) NULL); 04707 assert(cli_wand->signature == WandSignature); 04708 assert(cli_wand->wand.signature == WandSignature); 04709 if (IfMagickTrue(cli_wand->wand.debug)) 04710 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); 04711 04712 do { /* Break Code Block for error handling */ 04713 04714 /* get information about option */ 04715 if ( cli_wand->command == (const OptionInfo *) NULL ) 04716 cli_wand->command = GetCommandOptionInfo(option); 04717 #if 0 04718 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n", 04719 option, cli_wand->command->mnemonic ); 04720 #endif 04721 option_type=(CommandOptionFlags) cli_wand->command->flags; 04722 04723 if ( option_type == UndefinedOptionFlag ) 04724 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option); 04725 04726 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 ); 04727 04728 /* depreciated options */ 04729 if ( (option_type & DeprecateOptionFlag) != 0 ) 04730 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option); 04731 04732 /* options that this module does not handle */ 04733 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 ) 04734 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option); 04735 04736 /* Get argument strings from VarArgs 04737 How can you determine arguments is enough was supplied? */ 04738 { size_t 04739 count = cli_wand->command->type; 04740 04741 va_list 04742 operands; 04743 04744 va_start(operands,option); 04745 04746 arg1=arg2=NULL; 04747 if ( count >= 1 ) 04748 arg1=(const char *) va_arg(operands, const char *); 04749 if ( count >= 2 ) 04750 arg2=(const char *) va_arg(operands, const char *); 04751 04752 va_end(operands); 04753 04754 #if 0 04755 (void) FormatLocaleFile(stderr, 04756 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n", 04757 option,(long) count,option_type,arg1,arg2); 04758 #endif 04759 } 04760 04761 /* 04762 Call the appropriate option handler 04763 */ 04764 04765 /* FUTURE: this is temporary - get 'settings' to handle distribution of 04766 settings to images attributes,proprieties,artifacts */ 04767 if ( cli_wand->wand.images != (Image *)NULL ) 04768 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images, 04769 cli_wand->wand.exception); 04770 04771 if ( (option_type & SettingOptionFlags) != 0 ) { 04772 CLISettingOptionInfo(cli_wand, option, arg1, arg2); 04773 // FUTURE: Sync Specific Settings into Image Properities (not global) 04774 } 04775 04776 /* Operators that do not need images - read, write, stack, clone */ 04777 if ( (option_type & NoImageOperatorFlag) != 0) 04778 CLINoImageOperator(cli_wand, option, arg1, arg2); 04779 04780 /* FUTURE: The not a setting part below is a temporary hack due to 04781 * some options being both a Setting and a Simple operator. 04782 * Specifically -monitor, -depth, and -colorspace */ 04783 if ( cli_wand->wand.images == (Image *)NULL ) 04784 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) && 04785 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */ 04786 CLIWandExceptionBreak(OptionError,"NoImagesFound",option); 04787 04788 /* Operators work on single images, and needs a loop over the images */ 04789 if ( (option_type & SimpleOperatorFlag) != 0) 04790 CLISimpleOperatorImages(cli_wand, option, arg1, arg2); 04791 04792 /* Operators that work on the image list as a whole */ 04793 if ( (option_type & ListOperatorFlag) != 0 ) 04794 CLIListOperatorImages(cli_wand, option, arg1, arg2); 04795 04796 } while (0); /* end Break code block */ 04797 04798 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */ 04799 }