1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % CCCC OOO N N JJJJJ U U RRRR EEEEE % 7 % C O O NN N J U U R R E % 8 % C O O N N N J U U RRRR EEE % 9 % C O O N NN J J U U R R E % 10 % CCCC OOO N N JJJ UUU R R EEEEE % 11 % % 12 % % 13 % Interpret Magick Scripting Language. % 14 % % 15 % Software Design % 16 % Cristy % 17 % December 2001 % 18 % % 19 % % 20 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % 21 % dedicated to making software imaging solutions freely available. % 22 % % 23 % You may not use this file except in compliance with the License. You may % 24 % obtain a copy of the License at % 25 % % 26 % https://imagemagick.org/script/license.php % 27 % % 28 % Unless required by applicable law or agreed to in writing, software % 29 % distributed under the License is distributed on an "AS IS" BASIS, % 30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31 % See the License for the specific language governing permissions and % 32 % limitations under the License. % 33 % % 34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 % 36 % The conjure program gives you the ability to perform custom image processing 37 % tasks from a script written in the Magick Scripting Language (MSL). MSL is 38 % XML-based and consists of action statements with attributes. Actions include 39 % reading an image, processing an image, getting attributes from an image, 40 % writing an image, and more. An attribute is a key/value pair that modifies 41 % the behavior of an action. 42 % 43 */ 44 45 /* 47 Include declarations. 48 */ 49 #include "MagickWand/studio.h" 50 #include "MagickWand/MagickWand.h" 51 #include "MagickWand/mogrify-private.h" 52 53 /* 55 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 % % 57 % % 58 % % 59 + C o n j u r e I m a g e C o m m a n d % 60 % % 61 % % 62 % % 63 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 64 % 65 % ConjureImageCommand() describes the format and characteristics of one or 66 % more image files. It will also report if an image is incomplete or corrupt. 67 % The information displayed includes the scene number, the file name, the 68 % width and height of the image, whether the image is colormapped or not, 69 % the number of colors in the image, the number of bytes in the image, the 70 % format of the image (JPEG, PNM, etc.), and finally the number of seconds 71 % it took to read and process the image. 72 % 73 % The format of the ConjureImageCommand method is: 74 % 75 % MagickBooleanType ConjureImageCommand(ImageInfo *image_info,int argc, 76 % char **argv,char **metadata,ExceptionInfo *exception) 77 % 78 % A description of each parameter follows: 79 % 80 % o image_info: the image info. 81 % 82 % o argc: the number of elements in the argument vector. 83 % 84 % o argv: A text array containing the command line arguments. 85 % 86 % o metadata: any metadata is returned here. 87 % 88 % o exception: return any errors or warnings in this structure. 89 % 90 */ 91 92 static MagickBooleanType ConjureUsage(void) 93 { 94 const char 95 **p; 96 97 static const char 98 *miscellaneous[]= 99 { 100 "-debug events display copious debugging information", 101 "-help print program options", 102 "-list type print a list of supported option arguments", 103 "-log format format of debugging information", 104 "-version print version information", 105 (char *) NULL 106 }, 107 *settings[]= 108 { 109 "-monitor monitor progress", 110 "-quiet suppress all warning messages", 111 "-regard-warnings pay attention to warning messages", 112 "-seed value seed a new sequence of pseudo-random numbers", 113 "-verbose print detailed information about the image", 114 (char *) NULL 115 }; 116 117 ListMagickVersion(stdout); 118 (void) printf("Usage: %s [options ...] file [ [options ...] file ...]\n", 119 GetClientName()); 120 (void) printf("\nImage Settings:\n"); 121 for (p=settings; *p != (char *) NULL; p++) 122 (void) printf(" %s\n",*p); 123 (void) printf("\nMiscellaneous Options:\n"); 124 for (p=miscellaneous; *p != (char *) NULL; p++) 125 (void) printf(" %s\n",*p); 126 (void) printf("\nIn addition, define any key value pairs required by " 127 "your script. For\nexample,\n\n"); 128 (void) printf(" conjure -size 100x100 -color blue -foo bar script.msl\n"); 129 return(MagickFalse); 130 } 131 132 WandExport MagickBooleanType ConjureImageCommand(ImageInfo *image_info, 133 int argc,char **argv,char **wand_unused(metadata),ExceptionInfo *exception) 134 { 135 #define DestroyConjure() \ 136 { \ 137 image=DestroyImageList(image); \ 138 for (i=0; i < (ssize_t) argc; i++) \ 139 argv[i]=DestroyString(argv[i]); \ 140 argv=(char **) RelinquishMagickMemory(argv); \ 141 } 142 #define ThrowConjureException(asperity,tag,option) \ 143 { \ 144 (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \ 145 option); \ 146 DestroyConjure(); \ 147 return(MagickFalse); \ 148 } 149 #define ThrowConjureInvalidArgumentException(option,argument) \ 150 { \ 151 (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \ 152 "InvalidArgument","'%s': %s",option,argument); \ 153 DestroyConjure(); \ 154 return(MagickFalse); \ 155 } 156 157 char 158 filename[MagickPathExtent], 159 *option; 160 161 Image 162 *image; 163 164 MagickStatusType 165 status; 166 167 register ssize_t 168 i; 169 170 ssize_t 171 number_images; 172 173 wand_unreferenced(metadata); 174 175 /* 176 Set defaults. 177 */ 178 assert(image_info != (ImageInfo *) NULL); 179 assert(image_info->signature == MagickCoreSignature); 180 if (image_info->debug != MagickFalse) 181 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 182 assert(exception != (ExceptionInfo *) NULL); 183 if (argc < 2) 184 return(ConjureUsage()); 185 image=NewImageList(); 186 number_images=0; 187 option=(char *) NULL; 188 /* 189 Conjure an image. 190 */ 191 ReadCommandlLine(argc,&argv); 192 status=ExpandFilenames(&argc,&argv); 193 if (status == MagickFalse) 194 ThrowConjureException(ResourceLimitError,"MemoryAllocationFailed", 195 GetExceptionMessage(errno)); 196 for (i=1; i < (ssize_t) argc; i++) 197 { 198 option=argv[i]; 199 if (IsCommandOption(option) != MagickFalse) 200 { 201 if (LocaleCompare("concurrent",option+1) == 0) 202 break; 203 if (LocaleCompare("debug",option+1) == 0) 204 { 205 ssize_t 206 event; 207 208 if (*option == '+') 209 break; 210 i++; 211 if (i == (ssize_t) argc) 212 ThrowConjureException(OptionError,"MissingArgument",option); 213 event=ParseCommandOption(MagickLogEventOptions,MagickFalse,argv[i]); 214 if (event < 0) 215 ThrowConjureException(OptionError,"UnrecognizedEventType", 216 argv[i]); 217 (void) SetLogEventMask(argv[i]); 218 continue; 219 } 220 if (LocaleCompare("duration",option+1) == 0) 221 { 222 if (*option == '+') 223 break; 224 i++; 225 if (i == (ssize_t) argc) 226 ThrowConjureException(OptionError,"MissingArgument",option); 227 if (IsGeometry(argv[i]) == MagickFalse) 228 ThrowConjureInvalidArgumentException(option,argv[i]); 229 continue; 230 } 231 if ((LocaleCompare("help",option+1) == 0) || 232 (LocaleCompare("-help",option+1) == 0)) 233 { 234 if (*option == '-') 235 return(ConjureUsage()); 236 continue; 237 } 238 if (LocaleCompare("log",option+1) == 0) 239 { 240 if (*option == '-') 241 { 242 i++; 243 if (i == (ssize_t) argc) 244 ThrowConjureException(OptionError,"MissingLogFormat",option); 245 (void) SetLogFormat(argv[i]); 246 } 247 continue; 248 } 249 if (LocaleCompare("monitor",option+1) == 0) 250 continue; 251 if (LocaleCompare("quiet",option+1) == 0) 252 continue; 253 if (LocaleCompare("regard-warnings",option+1) == 0) 254 break; 255 if (LocaleCompare("seed",option+1) == 0) 256 { 257 if (*option == '+') 258 break; 259 i++; 260 if (i == (ssize_t) argc) 261 ThrowConjureException(OptionError,"MissingArgument",option); 262 if (IsGeometry(argv[i]) == MagickFalse) 263 ThrowConjureInvalidArgumentException(option,argv[i]); 264 break; 265 } 266 if (LocaleCompare("verbose",option+1) == 0) 267 { 268 image_info->verbose=(*option == '-') ? MagickTrue : MagickFalse; 269 continue; 270 } 271 if ((LocaleCompare("version",option+1) == 0) || 272 (LocaleCompare("-version",option+1) == 0)) 273 { 274 ListMagickVersion(stdout); 275 return(MagickTrue); 276 } 277 /* 278 Persist key/value pair. 279 */ 280 (void) DeleteImageOption(image_info,option+1); 281 status=SetImageOption(image_info,option+1,argv[i+1]); 282 if (status == MagickFalse) 283 ThrowConjureException(ImageError,"UnableToPersistKey",option); 284 i++; 285 continue; 286 } 287 /* 288 Interpret MSL script. 289 */ 290 (void) DeleteImageOption(image_info,"filename"); 291 status=SetImageOption(image_info,"filename",argv[i]); 292 if (status == MagickFalse) 293 ThrowConjureException(ImageError,"UnableToPersistKey",argv[i]); 294 (void) FormatLocaleString(filename,MagickPathExtent,"%s",argv[i]); 295 image=ReadImages(image_info,filename,exception); 296 CatchException(exception); 297 if (image != (Image *) NULL) 298 image=DestroyImageList(image); 299 status=image != (Image *) NULL ? MagickTrue : MagickFalse; 300 number_images++; 301 } 302 if (i != (ssize_t) argc) 303 ThrowConjureException(OptionError,"MissingAnImageFilename",argv[i]); 304 if (number_images == 0) 305 ThrowConjureException(OptionError,"MissingAnImageFilename",argv[argc-1]); 306 if (image != (Image *) NULL) 307 image=DestroyImageList(image); 308 for (i=0; i < (ssize_t) argc; i++) 309 argv[i]=DestroyString(argv[i]); 310 argv=(char **) RelinquishMagickMemory(argv); 311 return(status != 0 ? MagickTrue : MagickFalse); 312 } 313