1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%            AAA   RRRR   TTTTT  IIIII  FFFFF   AAA    CCCC  TTTTT            %
7%           A   A  R   R    T      I    F      A   A  C        T              %
8%           AAAAA  RRRRR    T      I    FFF    AAAAA  C        T              %
9%           A   A  R R      T      I    F      A   A  C        T              %
10%           A   A  R  R     T    IIIII  F      A   A  CCCCC    T              %
11%                                                                             %
12%                                                                             %
13%                         MagickCore Artifact Methods                         %
14%                                                                             %
15%                              Software Design                                %
16%                                   Cristy                                    %
17%                                 March 2000                                  %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2016 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%    http://www.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%
37%
38*/
39
40/*
41  Include declarations.
42*/
43#include "MagickCore/studio.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/cache.h"
46#include "MagickCore/color.h"
47#include "MagickCore/compare.h"
48#include "MagickCore/constitute.h"
49#include "MagickCore/draw.h"
50#include "MagickCore/effect.h"
51#include "MagickCore/exception.h"
52#include "MagickCore/exception-private.h"
53#include "MagickCore/fx.h"
54#include "MagickCore/fx-private.h"
55#include "MagickCore/gem.h"
56#include "MagickCore/geometry.h"
57#include "MagickCore/image.h"
58#include "MagickCore/layer.h"
59#include "MagickCore/list.h"
60#include "MagickCore/memory_.h"
61#include "MagickCore/monitor.h"
62#include "MagickCore/montage.h"
63#include "MagickCore/option.h"
64#include "MagickCore/profile.h"
65#include "MagickCore/quantum.h"
66#include "MagickCore/resource_.h"
67#include "MagickCore/splay-tree.h"
68#include "MagickCore/signature-private.h"
69#include "MagickCore/statistic.h"
70#include "MagickCore/string_.h"
71#include "MagickCore/token.h"
72#include "MagickCore/utility.h"
73#include "MagickCore/xml-tree.h"
74
75/*
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77%                                                                             %
78%                                                                             %
79%                                                                             %
80%   C l o n e I m a g e A r t i f a c t s                                     %
81%                                                                             %
82%                                                                             %
83%                                                                             %
84%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85%
86%  CloneImageArtifacts() clones all image artifacts to another image.
87%
88%  This will not delete any existing artifacts that may be present!
89%
90%  The format of the CloneImageArtifacts method is:
91%
92%      MagickBooleanType CloneImageArtifacts(Image *image,
93%        const Image *clone_image)
94%
95%  A description of each parameter follows:
96%
97%    o image: the image, to recieve the cloned artifacts.
98%
99%    o clone_image: the source image for artifacts to clone.
100%
101*/
102MagickExport MagickBooleanType CloneImageArtifacts(Image *image,
103  const Image *clone_image)
104{
105  assert(image != (Image *) NULL);
106  assert(image->signature == MagickCoreSignature);
107  if (image->debug != MagickFalse)
108    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
109  assert(clone_image != (const Image *) NULL);
110  assert(clone_image->signature == MagickCoreSignature);
111  if (clone_image->debug != MagickFalse)
112    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
113      clone_image->filename);
114  if (clone_image->artifacts != (void *) NULL)
115    {
116      if (image->artifacts != (void *) NULL)
117        DestroyImageArtifacts(image);
118      image->artifacts=CloneSplayTree((SplayTreeInfo *) clone_image->artifacts,
119        (void *(*)(void *)) ConstantString,(void *(*)(void *)) ConstantString);
120    }
121  return(MagickTrue);
122}
123
124/*
125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126%                                                                             %
127%                                                                             %
128%                                                                             %
129%   D e f i n e I m a g e A r t i f a c t                                     %
130%                                                                             %
131%                                                                             %
132%                                                                             %
133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134%
135%  DefineImageArtifact() associates an assignment string of the form
136%  "key=value" with per-image artifact. It is equivelent to
137%  SetImageArtifact().
138%
139%  The format of the DefineImageArtifact method is:
140%
141%      MagickBooleanType DefineImageArtifact(Image *image,
142%        const char *artifact)
143%
144%  A description of each parameter follows:
145%
146%    o image: the image.
147%
148%    o artifact: the image artifact.
149%
150*/
151MagickExport MagickBooleanType DefineImageArtifact(Image *image,
152  const char *artifact)
153{
154  char
155    key[MagickPathExtent],
156    value[MagickPathExtent];
157
158  register char
159    *p;
160
161  assert(image != (Image *) NULL);
162  assert(artifact != (const char *) NULL);
163  (void) CopyMagickString(key,artifact,MagickPathExtent-1);
164  for (p=key; *p != '\0'; p++)
165    if (*p == '=')
166      break;
167  *value='\0';
168  if (*p == '=')
169    (void) CopyMagickString(value,p+1,MagickPathExtent);
170  *p='\0';
171  return(SetImageArtifact(image,key,value));
172}
173
174/*
175%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
176%                                                                             %
177%                                                                             %
178%                                                                             %
179%   D e l e t e I m a g e A r t i f a c t                                     %
180%                                                                             %
181%                                                                             %
182%                                                                             %
183%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184%
185%  DeleteImageArtifact() deletes an image artifact.
186%
187%  The format of the DeleteImageArtifact method is:
188%
189%      MagickBooleanType DeleteImageArtifact(Image *image,const char *artifact)
190%
191%  A description of each parameter follows:
192%
193%    o image: the image.
194%
195%    o artifact: the image artifact.
196%
197*/
198MagickExport MagickBooleanType DeleteImageArtifact(Image *image,
199  const char *artifact)
200{
201  assert(image != (Image *) NULL);
202  assert(image->signature == MagickCoreSignature);
203  if (image->debug != MagickFalse)
204    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
205  if (image->artifacts == (void *) NULL)
206    return(MagickFalse);
207  return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->artifacts,artifact));
208}
209
210/*
211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212%                                                                             %
213%                                                                             %
214%                                                                             %
215%   D e s t r o y I m a g e A r t i f a c t s                                 %
216%                                                                             %
217%                                                                             %
218%                                                                             %
219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220%
221%  DestroyImageArtifacts() destroys all artifacts and associated memory
222%  attached to the given image.
223%
224%  The format of the DestroyImageArtifacts method is:
225%
226%      void DestroyImageArtifacts(Image *image)
227%
228%  A description of each parameter follows:
229%
230%    o image: the image.
231%
232*/
233MagickExport void DestroyImageArtifacts(Image *image)
234{
235  assert(image != (Image *) NULL);
236  assert(image->signature == MagickCoreSignature);
237  if (image->debug != MagickFalse)
238    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
239  if (image->artifacts != (void *) NULL)
240    image->artifacts=(void *) DestroySplayTree((SplayTreeInfo *)
241      image->artifacts);
242}
243
244/*
245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246%                                                                             %
247%                                                                             %
248%                                                                             %
249%   G e t I m a g e A r t i f a c t                                           %
250%                                                                             %
251%                                                                             %
252%                                                                             %
253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254%
255%  GetImageArtifact() gets a value associated with an image artifact.
256%  If the requested artifact is NULL return the first artifact, to
257%  prepare to iterate over all artifacts.
258%
259%  The returned string is a constant string in the tree and should NOT be
260%  freed by the caller.
261%
262%  The format of the GetImageArtifact method is:
263%
264%      const char *GetImageArtifact(const Image *image,const char *key)
265%
266%  A description of each parameter follows:
267%
268%    o image: the image.
269%
270%    o key: the key.
271%
272*/
273MagickExport const char *GetImageArtifact(const Image *image,
274  const char *artifact)
275{
276  register const char
277    *p;
278
279  assert(image != (Image *) NULL);
280  assert(image->signature == MagickCoreSignature);
281  if (image->debug != MagickFalse)
282    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
283  p=(const char *) NULL;
284  if (artifact == (const char *) NULL)
285    {
286      ResetSplayTreeIterator((SplayTreeInfo *) image->artifacts);
287      p=(const char *) GetNextValueInSplayTree((SplayTreeInfo *)
288        image->artifacts);
289      return(p);
290    }
291  if (image->artifacts != (void *) NULL)
292    {
293      p=(const char *) GetValueFromSplayTree((SplayTreeInfo *) image->artifacts,
294        artifact);
295      if (p != (const char *) NULL)
296        return(p);
297    }
298  if ((image->image_info != (ImageInfo *) NULL) &&
299      (image->image_info->options != (void *) NULL))
300    p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
301      image->image_info->options,artifact);
302  return(p);
303}
304
305/*
306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307%                                                                             %
308%                                                                             %
309%                                                                             %
310%   G e t N e x t I m a g e A r t i f a c t                                   %
311%                                                                             %
312%                                                                             %
313%                                                                             %
314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315%
316%  GetNextImageArtifact() gets the next image artifact value.
317%
318%  The format of the GetNextImageArtifact method is:
319%
320%      char *GetNextImageArtifact(const Image *image)
321%
322%  A description of each parameter follows:
323%
324%    o image: the image.
325%
326*/
327MagickExport const char *GetNextImageArtifact(const Image *image)
328{
329  assert(image != (Image *) NULL);
330  assert(image->signature == MagickCoreSignature);
331  if (image->debug != MagickFalse)
332    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
333  if (image->artifacts == (void *) NULL)
334    return((const char *) NULL);
335  return((const char *) GetNextKeyInSplayTree(
336   (SplayTreeInfo *) image->artifacts));
337}
338
339/*
340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341%                                                                             %
342%                                                                             %
343%                                                                             %
344%   R e m o v e I m a g e A r t i f a c t                                     %
345%                                                                             %
346%                                                                             %
347%                                                                             %
348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349%
350%  RemoveImageArtifact() removes an artifact from the image and returns its
351%  value.
352%
353%  In this case the ConstantString() value returned should be freed by the
354%  caller when finished.
355%
356%  The format of the RemoveImageArtifact method is:
357%
358%      char *RemoveImageArtifact(Image *image,const char *artifact)
359%
360%  A description of each parameter follows:
361%
362%    o image: the image.
363%
364%    o artifact: the image artifact.
365%
366*/
367MagickExport char *RemoveImageArtifact(Image *image,const char *artifact)
368{
369  char
370    *value;
371
372  assert(image != (Image *) NULL);
373  assert(image->signature == MagickCoreSignature);
374  if (image->debug != MagickFalse)
375    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
376  if (image->artifacts == (void *) NULL)
377    return((char *) NULL);
378  value=(char *) RemoveNodeFromSplayTree((SplayTreeInfo *) image->artifacts,
379    artifact);
380  return(value);
381}
382
383/*
384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385%                                                                             %
386%                                                                             %
387%                                                                             %
388%   R e s e t I m a g e A r t i f a c t I t e r a t o r                       %
389%                                                                             %
390%                                                                             %
391%                                                                             %
392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393%
394%  ResetImageArtifactIterator() resets the image artifact iterator.  Use it
395%  in conjunction with GetNextImageArtifact() to iterate over all the values
396%  associated with an image artifact.
397%
398%  Alternatively you can use GetImageArtifact() with a NULL artifact field to
399%  reset the iterator and return the first artifact.
400%
401%  The format of the ResetImageArtifactIterator method is:
402%
403%      ResetImageArtifactIterator(Image *image)
404%
405%  A description of each parameter follows:
406%
407%    o image: the image.
408%
409*/
410MagickExport void ResetImageArtifactIterator(const Image *image)
411{
412  assert(image != (Image *) NULL);
413  assert(image->signature == MagickCoreSignature);
414  if (image->debug != MagickFalse)
415    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
416  if (image->artifacts == (void *) NULL)
417    return;
418  ResetSplayTreeIterator((SplayTreeInfo *) image->artifacts);
419}
420
421/*
422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423%                                                                             %
424%                                                                             %
425%                                                                             %
426%   S e t I m a g e A r t i f a c t                                           %
427%                                                                             %
428%                                                                             %
429%                                                                             %
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431%
432%  SetImageArtifact() associates makes a copy of the given string arguments
433%  and inserts it into the artifact tree of the given image.
434%
435%  The format of the SetImageArtifact method is:
436%
437%      MagickBooleanType SetImageArtifact(Image *image,const char *artifact,
438%        const char *value)
439%
440%  A description of each parameter follows:
441%
442%    o image: the image.
443%
444%    o artifact: the image artifact key.
445%
446%    o value: the image artifact value.
447%
448*/
449MagickExport MagickBooleanType SetImageArtifact(Image *image,
450  const char *artifact,const char *value)
451{
452  MagickBooleanType
453    status;
454
455  assert(image != (Image *) NULL);
456  assert(image->signature == MagickCoreSignature);
457  if (image->debug != MagickFalse)
458    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
459  /*
460    Create tree if needed - specify how key,values are to be freed.
461  */
462  if (image->artifacts == (void *) NULL)
463    image->artifacts=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
464      RelinquishMagickMemory);
465  /*
466    Delete artifact if NULL --  empty string values are valid!,
467  */
468  if (value == (const char *) NULL)
469    return(DeleteImageArtifact(image,artifact));
470  /*
471    Add artifact to splay-tree.
472  */
473  status=AddValueToSplayTree((SplayTreeInfo *) image->artifacts,
474    ConstantString(artifact),ConstantString(value));
475  return(status);
476}
477