MagickWand  7.1.2-29
Convert, Edit, Or Compose Bitmap Images
wandcli.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % W W AA N N DDD CCC L III %
7 % W W A A NN N D D C L I %
8 % W W W AAAA N N N D D C L I %
9 % W W W A A N NN D D C L I %
10 % W W A A N N DDD CCC LLLL III %
11 % %
12 % WandCLI Structure Methods %
13 % %
14 % Dragon Computing %
15 % Anthony Thyssen %
16 % April 2011 %
17 % %
18 % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
19 % dedicated to making software imaging solutions freely available. %
20 % %
21 % You may not use this file except in compliance with the License. You may %
22 % obtain a copy of the License at %
23 % %
24 % https://imagemagick.org/license/ %
25 % %
26 % Unless required by applicable law or agreed to in writing, software %
27 % distributed under the License is distributed on an "AS IS" BASIS, %
28 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
29 % See the License for the specific language governing permissions and %
30 % limitations under the License. %
31 % %
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 %
34 % General methods for handling the WandCLI structure used for Command Line.
35 %
36 % Anthony Thyssen, April 2011
37 */
38 ␌
39 /*
40  Include declarations.
41 */
42 #include "MagickWand/studio.h"
43 #include "MagickWand/MagickWand.h"
44 #include "MagickWand/wand.h"
45 #include "MagickWand/magick-wand-private.h"
46 #include "MagickWand/wandcli.h"
47 #include "MagickWand/wandcli-private.h"
48 #include "MagickCore/exception.h"
49 ␌
50 /*
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 % %
53 % %
54 % %
55 + A c q u i r e W a n d C L I %
56 % %
57 % %
58 % %
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60 %
61 % AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
62 % Wand). The given image_info and exception is included as is if provided.
63 %
64 % Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
65 % needed.
66 %
67 % The format of the NewMagickWand method is:
68 %
69 % MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
70 % ExceptionInfo *exception)
71 %
72 */
73 WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
74  ExceptionInfo *exception)
75 {
76  MagickCLI
77  *cli_wand;
78 
79  CheckMagickCoreCompatibility();
80  cli_wand=(MagickCLI *) AcquireCriticalMemory(sizeof(*cli_wand));
81  cli_wand->wand.id=AcquireWandId();
82  (void) FormatLocaleString(cli_wand->wand.name,MagickPathExtent,
83  "%s-%.17g","MagickWandCLI", (double) cli_wand->wand.id);
84  cli_wand->wand.images=NewImageList();
85  if ( image_info == (ImageInfo *) NULL)
86  cli_wand->wand.image_info=AcquireImageInfo();
87  else
88  cli_wand->wand.image_info=image_info;
89  if ( exception == (ExceptionInfo *) NULL)
90  cli_wand->wand.exception=AcquireExceptionInfo();
91  else
92  cli_wand->wand.exception=exception;
93  cli_wand->wand.debug=IsEventLogging();
94  cli_wand->wand.signature=MagickWandSignature;
95  /* Initialize CLI Part of MagickCLI */
96  cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,
97  (DrawInfo *) NULL);
98  if (cli_wand->draw_info->image_info != (ImageInfo *) NULL)
99  cli_wand->draw_info->image_info =
100  DestroyImageInfo(cli_wand->draw_info->image_info);
101  cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
102  cli_wand->process_flags=MagickCommandOptionFlags; /* assume "magick" CLI */
103  cli_wand->command=(const OptionInfo *) NULL; /* no option at this time */
104  cli_wand->image_list_stack=(CLIStack *) NULL;
105  cli_wand->image_info_stack=(CLIStack *) NULL;
106  /* default exception location...
107  EG: sprintf(location, filename, line, column);
108  */
109  cli_wand->location="from \"%s\""; /* location format using arguments: */
110  /* filename, line, column */
111  cli_wand->filename="unknown"; /* script filename, unknown source */
112  cli_wand->line=0; /* line from script OR CLI argument */
113  cli_wand->column=0; /* column from script */
114  cli_wand->signature=MagickWandSignature;
115  if (cli_wand->wand.debug != MagickFalse)
116  (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
117  return(cli_wand);
118 }
119 ␌
120 /*
121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122 % %
123 % %
124 % %
125 + D e s t r o y W a n d C L I %
126 % %
127 % %
128 % %
129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130 %
131 % DestroyMagickCLI() destroys everything in a CLI wand, including image_info
132 % and any exceptions, if still present in the wand.
133 %
134 % The format of the NewMagickWand method is:
135 %
136 % MagickWand *DestroyMagickCLI()
137 % Exception *exception)
138 %
139 */
140 WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
141 {
142  CLIStack
143  *node;
144 
145  assert(cli_wand != (MagickCLI *) NULL);
146  assert(cli_wand->signature == MagickWandSignature);
147  assert(cli_wand->wand.signature == MagickWandSignature);
148  if (cli_wand->wand.debug != MagickFalse)
149  (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
150 
151  /* Destroy CLI part of MagickCLI */
152  if (cli_wand->draw_info != (DrawInfo *) NULL )
153  cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
154  if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
155  cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
156  while(cli_wand->image_list_stack != (CLIStack *) NULL)
157  {
158  node=cli_wand->image_list_stack;
159  cli_wand->image_list_stack=node->next;
160  (void) DestroyImageList((Image *)node->data);
161  (void) RelinquishMagickMemory(node);
162  }
163  while(cli_wand->image_info_stack != (CLIStack *) NULL)
164  {
165  node=cli_wand->image_info_stack;
166  cli_wand->image_info_stack=node->next;
167  (void) DestroyImageInfo((ImageInfo *)node->data);
168  (void) RelinquishMagickMemory(node);
169  }
170  cli_wand->signature=(~MagickWandSignature);
171 
172  /* Destroy Wand part MagickCLI */
173  cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
174  if (cli_wand->wand.image_info != (ImageInfo *) NULL )
175  cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
176  if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
177  cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
178  RelinquishWandId(cli_wand->wand.id);
179  cli_wand->wand.signature=(~MagickWandSignature);
180  cli_wand=(MagickCLI *) RelinquishMagickMemory(cli_wand);
181  return((MagickCLI *) NULL);
182 }
183 ␌
184 /*
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186 % %
187 % %
188 % %
189 + C L I C a t c h E x c e p t i o n %
190 % %
191 % %
192 % %
193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 %
195 % CLICatchException() will report exceptions, either just non-fatal warnings
196 % only, or all errors, according to 'all_exceptions' boolean argument.
197 %
198 % The function returns true if errors are fatal, in which case the caller
199 % should abort and re-call with an 'all_exceptions' argument of true before
200 % quitting.
201 %
202 % The cut-off level between fatal and non-fatal may be controlled by options
203 % (FUTURE), but defaults to 'Error' exceptions.
204 %
205 % The format of the CLICatchException method is:
206 %
207 % MagickBooleanType CLICatchException(MagickCLI *cli_wand,
208 % const MagickBooleanType all_exceptions );
209 %
210 % Arguments are
211 %
212 % o cli_wand: The Wand CLI that holds the exception Information
213 %
214 % o all_exceptions: Report all exceptions, including the fatal one
215 %
216 */
217 WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
218  const MagickBooleanType all_exceptions)
219 {
220  MagickBooleanType
221  status;
222 
223  assert(cli_wand != (MagickCLI *) NULL);
224  assert(cli_wand->signature == MagickWandSignature);
225  assert(cli_wand->wand.signature == MagickWandSignature);
226  if (cli_wand->wand.debug != MagickFalse)
227  (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
228 
229  /*
230  FUTURE: '-regard_warning' should make this more sensitive.
231  Note pipelined options may like more control over this level
232  */
233 
234  status=cli_wand->wand.exception->severity > ErrorException ? MagickTrue :
235  MagickFalse;
236 
237  if ((status == MagickFalse) || (all_exceptions != MagickFalse))
238  CatchException(cli_wand->wand.exception); /* output and clear exceptions */
239 
240  return(status);
241 }
242 ␌
243 /*
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245 % %
246 % %
247 % %
248 + C L I L o g E v e n t %
249 % %
250 % %
251 % %
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 %
254 % CLILogEvent() is a wrapper around LogMagickEvent(), adding to it the
255 % location of the option that is (about) to be executed.
256 %
257 */
258 WandExport MagickBooleanType CLILogEvent(MagickCLI *cli_wand,
259  const LogEventType type,const char *magick_module,const char *function,
260  const size_t line,const char *format,...)
261 {
262  char
263  new_format[MagickPathExtent];
264 
265  MagickBooleanType
266  status;
267 
268  va_list
269  operands;
270 
271  if (IsEventLogging() == MagickFalse)
272  return(MagickFalse);
273 
274  /* HACK - prepend the CLI location to format string.
275  The better way would be add more arguments to the 'va' operands
276  list, but that does not appear to be possible! So we do some
277  pre-formatting of the location info here.
278  */
279  (void) FormatLocaleString(new_format,MagickPathExtent,cli_wand->location,
280  cli_wand->filename, cli_wand->line, cli_wand->column);
281  (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
282  (void) ConcatenateMagickString(new_format,format,MagickPathExtent);
283 
284  va_start(operands,format);
285  status=LogMagickEventList(type,magick_module,function,line,new_format,
286  operands);
287  va_end(operands);
288 
289  return(status);
290 }
291 ␌
292 /*
293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294 % %
295 % %
296 % %
297 + C L I T h r o w E x c e p t i o n %
298 % %
299 % %
300 % %
301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 %
303 % CLIThrowException() is a wrapper around ThrowMagickException(), adding to
304 % it the location of the option that caused the exception to occur.
305 */
306 WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand,
307  const char *magick_module,const char *function,const size_t line,
308  const ExceptionType severity,const char *tag,const char *format,...)
309 {
310  char
311  new_format[MagickPathExtent];
312 
313  size_t
314  len;
315 
316  MagickBooleanType
317  status;
318 
319  va_list
320  operands;
321 
322  /* HACK - append location to format string.
323  The better way would be add more arguments to the 'va' operands
324  list, but that does not appear to be possible! So we do some
325  pre-formatting of the location info here.
326  */
327  (void) CopyMagickString(new_format,format,MagickPathExtent);
328  (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
329 
330  len=strlen(new_format);
331  (void) FormatLocaleString(new_format+len,MagickPathExtent-len,
332  cli_wand->location,cli_wand->filename,cli_wand->line,cli_wand->column);
333 
334  va_start(operands,format);
335  status=ThrowMagickExceptionList(cli_wand->wand.exception,magick_module,
336  function,line,severity,tag,new_format,operands);
337  va_end(operands);
338  return(status);
339 }