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-2021 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 %
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 */
CloneImageArtifacts(Image * image,const Image * clone_image)102 MagickExport 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 */
DefineImageArtifact(Image * image,const char * artifact)151 MagickExport MagickBooleanType DefineImageArtifact(Image *image,
152   const char *artifact)
153 {
154   char
155     key[MagickPathExtent],
156     value[MagickPathExtent];
157 
158   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 */
DeleteImageArtifact(Image * image,const char * artifact)198 MagickExport 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 */
DestroyImageArtifacts(Image * image)233 MagickExport 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 */
GetImageArtifact(const Image * image,const char * artifact)273 MagickExport const char *GetImageArtifact(const Image *image,
274   const char *artifact)
275 {
276   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 (image->artifacts != (void *) NULL)
285     {
286       if (artifact == (const char *) NULL)
287         return((const char *) GetRootValueFromSplayTree((SplayTreeInfo *)
288           image->artifacts));
289       p=(const char *) GetValueFromSplayTree((SplayTreeInfo *) image->artifacts,
290         artifact);
291       if (p != (const char *) NULL)
292         return(p);
293     }
294   if ((image->image_info != (ImageInfo *) NULL) &&
295       (image->image_info->options != (void *) NULL))
296     p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
297       image->image_info->options,artifact);
298   return(p);
299 }
300 
301 /*
302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 %                                                                             %
304 %                                                                             %
305 %                                                                             %
306 %   G e t N e x t I m a g e A r t i f a c t                                   %
307 %                                                                             %
308 %                                                                             %
309 %                                                                             %
310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311 %
312 %  GetNextImageArtifact() gets the next image artifact value.
313 %
314 %  The format of the GetNextImageArtifact method is:
315 %
316 %      char *GetNextImageArtifact(const Image *image)
317 %
318 %  A description of each parameter follows:
319 %
320 %    o image: the image.
321 %
322 */
GetNextImageArtifact(const Image * image)323 MagickExport const char *GetNextImageArtifact(const Image *image)
324 {
325   assert(image != (Image *) NULL);
326   assert(image->signature == MagickCoreSignature);
327   if (image->debug != MagickFalse)
328     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
329   if (image->artifacts == (void *) NULL)
330     return((const char *) NULL);
331   return((const char *) GetNextKeyInSplayTree(
332    (SplayTreeInfo *) image->artifacts));
333 }
334 
335 /*
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %                                                                             %
338 %                                                                             %
339 %                                                                             %
340 %   R e m o v e I m a g e A r t i f a c t                                     %
341 %                                                                             %
342 %                                                                             %
343 %                                                                             %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 %
346 %  RemoveImageArtifact() removes an artifact from the image and returns its
347 %  value.
348 %
349 %  In this case the ConstantString() value returned should be freed by the
350 %  caller when finished.
351 %
352 %  The format of the RemoveImageArtifact method is:
353 %
354 %      char *RemoveImageArtifact(Image *image,const char *artifact)
355 %
356 %  A description of each parameter follows:
357 %
358 %    o image: the image.
359 %
360 %    o artifact: the image artifact.
361 %
362 */
RemoveImageArtifact(Image * image,const char * artifact)363 MagickExport char *RemoveImageArtifact(Image *image,const char *artifact)
364 {
365   char
366     *value;
367 
368   assert(image != (Image *) NULL);
369   assert(image->signature == MagickCoreSignature);
370   if (image->debug != MagickFalse)
371     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
372   if (image->artifacts == (void *) NULL)
373     return((char *) NULL);
374   value=(char *) RemoveNodeFromSplayTree((SplayTreeInfo *) image->artifacts,
375     artifact);
376   return(value);
377 }
378 
379 /*
380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381 %                                                                             %
382 %                                                                             %
383 %                                                                             %
384 %   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                       %
385 %                                                                             %
386 %                                                                             %
387 %                                                                             %
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 %
390 %  ResetImageArtifactIterator() resets the image artifact iterator.  Use it
391 %  in conjunction with GetNextImageArtifact() to iterate over all the values
392 %  associated with an image artifact.
393 %
394 %  Alternatively you can use GetImageArtifact() with a NULL artifact field to
395 %  reset the iterator and return the first artifact.
396 %
397 %  The format of the ResetImageArtifactIterator method is:
398 %
399 %      ResetImageArtifactIterator(Image *image)
400 %
401 %  A description of each parameter follows:
402 %
403 %    o image: the image.
404 %
405 */
ResetImageArtifactIterator(const Image * image)406 MagickExport void ResetImageArtifactIterator(const Image *image)
407 {
408   assert(image != (Image *) NULL);
409   assert(image->signature == MagickCoreSignature);
410   if (image->debug != MagickFalse)
411     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
412   if (image->artifacts == (void *) NULL)
413     return;
414   ResetSplayTreeIterator((SplayTreeInfo *) image->artifacts);
415 }
416 
417 /*
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 %                                                                             %
420 %                                                                             %
421 %                                                                             %
422 %   S e t I m a g e A r t i f a c t                                           %
423 %                                                                             %
424 %                                                                             %
425 %                                                                             %
426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427 %
428 %  SetImageArtifact() sets a key-value pair in the image artifact namespace.
429 %  Artifacts differ from properties.  Properties are public and are generally
430 %  exported to an external image format if the format supports it.  Artifacts
431 %  are private and are utilized by the internal ImageMagick API to modify the
432 %  behavior of certain algorithms.
433 %
434 %  The format of the SetImageArtifact method is:
435 %
436 %      MagickBooleanType SetImageArtifact(Image *image,const char *artifact,
437 %        const char *value)
438 %
439 %  A description of each parameter follows:
440 %
441 %    o image: the image.
442 %
443 %    o artifact: the image artifact key.
444 %
445 %    o value: the image artifact value.
446 %
447 */
SetImageArtifact(Image * image,const char * artifact,const char * value)448 MagickExport MagickBooleanType SetImageArtifact(Image *image,
449   const char *artifact,const char *value)
450 {
451   MagickBooleanType
452     status;
453 
454   assert(image != (Image *) NULL);
455   assert(image->signature == MagickCoreSignature);
456   if (image->debug != MagickFalse)
457     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
458   /*
459     Create tree if needed - specify how key,values are to be freed.
460   */
461   if (image->artifacts == (void *) NULL)
462     image->artifacts=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
463       RelinquishMagickMemory);
464   /*
465     Delete artifact if NULL --  empty string values are valid!,
466   */
467   if (value == (const char *) NULL)
468     return(DeleteImageArtifact(image,artifact));
469   /*
470     Add artifact to splay-tree.
471   */
472   status=AddValueToSplayTree((SplayTreeInfo *) image->artifacts,
473     ConstantString(artifact),ConstantString(value));
474   return(status);
475 }
476