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 "magick/studio.h"
44 #include "magick/artifact.h"
45 #include "magick/cache.h"
46 #include "magick/color.h"
47 #include "magick/compare.h"
48 #include "magick/constitute.h"
49 #include "magick/draw.h"
50 #include "magick/effect.h"
51 #include "magick/exception.h"
52 #include "magick/exception-private.h"
53 #include "magick/fx.h"
54 #include "magick/fx-private.h"
55 #include "magick/gem.h"
56 #include "magick/geometry.h"
57 #include "magick/image.h"
58 #include "magick/layer.h"
59 #include "magick/list.h"
60 #include "magick/memory_.h"
61 #include "magick/monitor.h"
62 #include "magick/montage.h"
63 #include "magick/option.h"
64 #include "magick/profile.h"
65 #include "magick/quantum.h"
66 #include "magick/resource_.h"
67 #include "magick/splay-tree.h"
68 #include "magick/signature-private.h"
69 #include "magick/statistic.h"
70 #include "magick/string_.h"
71 #include "magick/token.h"
72 #include "magick/utility.h"
73 #include "magick/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 one or more image artifacts.
87 %
88 %  The format of the CloneImageArtifacts method is:
89 %
90 %      MagickBooleanType CloneImageArtifacts(Image *image,
91 %        const Image *clone_image)
92 %
93 %  A description of each parameter follows:
94 %
95 %    o image: the image.
96 %
97 %    o clone_image: the clone image.
98 %
99 */
CloneImageArtifacts(Image * image,const Image * clone_image)100 MagickExport MagickBooleanType CloneImageArtifacts(Image *image,
101   const Image *clone_image)
102 {
103   assert(image != (Image *) NULL);
104   assert(image->signature == MagickCoreSignature);
105   if (image->debug != MagickFalse)
106     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
107   assert(clone_image != (const Image *) NULL);
108   assert(clone_image->signature == MagickCoreSignature);
109   if (clone_image->debug != MagickFalse)
110     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
111       clone_image->filename);
112   if (clone_image->artifacts != (void *) NULL)
113     {
114       if (image->artifacts != (void *) NULL)
115         DestroyImageArtifacts(image);
116       image->artifacts=CloneSplayTree((SplayTreeInfo *) clone_image->artifacts,
117         (void *(*)(void *)) ConstantString,(void *(*)(void *)) ConstantString);
118     }
119   return(MagickTrue);
120 }
121 
122 /*
123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124 %                                                                             %
125 %                                                                             %
126 %                                                                             %
127 %   D e f i n e I m a g e A r t i f a c t                                     %
128 %                                                                             %
129 %                                                                             %
130 %                                                                             %
131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132 %
133 %  DefineImageArtifact() associates a key/value pair with an image artifact.
134 %
135 %  The format of the DefineImageArtifact method is:
136 %
137 %      MagickBooleanType DefineImageArtifact(Image *image,
138 %        const char *artifact)
139 %
140 %  A description of each parameter follows:
141 %
142 %    o image: the image.
143 %
144 %    o artifact: the image artifact.
145 %
146 */
DefineImageArtifact(Image * image,const char * artifact)147 MagickExport MagickBooleanType DefineImageArtifact(Image *image,
148   const char *artifact)
149 {
150   char
151     key[MaxTextExtent],
152     value[MaxTextExtent];
153 
154   char
155     *p;
156 
157   assert(image != (Image *) NULL);
158   assert(artifact != (const char *) NULL);
159   (void) CopyMagickString(key,artifact,MaxTextExtent-1);
160   for (p=key; *p != '\0'; p++)
161     if (*p == '=')
162       break;
163   *value='\0';
164   if (*p == '=')
165     (void) CopyMagickString(value,p+1,MaxTextExtent);
166   *p='\0';
167   return(SetImageArtifact(image,key,value));
168 }
169 
170 /*
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 %                                                                             %
173 %                                                                             %
174 %                                                                             %
175 %   D e l e t e I m a g e A r t i f a c t                                     %
176 %                                                                             %
177 %                                                                             %
178 %                                                                             %
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 %
181 %  DeleteImageArtifact() deletes an image artifact.
182 %
183 %  The format of the DeleteImageArtifact method is:
184 %
185 %      MagickBooleanType DeleteImageArtifact(Image *image,const char *artifact)
186 %
187 %  A description of each parameter follows:
188 %
189 %    o image: the image.
190 %
191 %    o artifact: the image artifact.
192 %
193 */
DeleteImageArtifact(Image * image,const char * artifact)194 MagickExport MagickBooleanType DeleteImageArtifact(Image *image,
195   const char *artifact)
196 {
197   assert(image != (Image *) NULL);
198   assert(image->signature == MagickCoreSignature);
199   if (image->debug != MagickFalse)
200     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
201   if (image->artifacts == (void *) NULL)
202     return(MagickFalse);
203   return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->artifacts,artifact));
204 }
205 
206 /*
207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208 %                                                                             %
209 %                                                                             %
210 %                                                                             %
211 %   D e s t r o y I m a g e A r t i f a c t s                                 %
212 %                                                                             %
213 %                                                                             %
214 %                                                                             %
215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216 %
217 %  DestroyImageArtifacts() releases memory associated with image artifact
218 %  values.
219 %
220 %  The format of the DestroyDefines method is:
221 %
222 %      void DestroyImageArtifacts(Image *image)
223 %
224 %  A description of each parameter follows:
225 %
226 %    o image: the image.
227 %
228 */
DestroyImageArtifacts(Image * image)229 MagickExport void DestroyImageArtifacts(Image *image)
230 {
231   assert(image != (Image *) NULL);
232   assert(image->signature == MagickCoreSignature);
233   if (image->debug != MagickFalse)
234     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
235   if (image->artifacts != (void *) NULL)
236     image->artifacts=(void *) DestroySplayTree((SplayTreeInfo *)
237       image->artifacts);
238 }
239 
240 /*
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %   G e t I m a g e A r t i f a c t                                           %
246 %                                                                             %
247 %                                                                             %
248 %                                                                             %
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 %
251 %  GetImageArtifact() gets a value associated with an image artifact.
252 %
253 %  Note, the artifact is a constant.  Do not attempt to free it.
254 %
255 %  The format of the GetImageArtifact method is:
256 %
257 %      const char *GetImageArtifact(const Image *image,const char *key)
258 %
259 %  A description of each parameter follows:
260 %
261 %    o image: the image.
262 %
263 %    o key: the key.
264 %
265 */
GetImageArtifact(const Image * image,const char * artifact)266 MagickExport const char *GetImageArtifact(const Image *image,
267   const char *artifact)
268 {
269   const char
270     *p;
271 
272   assert(image != (Image *) NULL);
273   assert(image->signature == MagickCoreSignature);
274   if (image->debug != MagickFalse)
275     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
276   p=(const char *) NULL;
277   if (artifact == (const char *) NULL)
278     {
279       ResetSplayTreeIterator((SplayTreeInfo *) image->artifacts);
280       p=(const char *) GetNextValueInSplayTree((SplayTreeInfo *)
281         image->artifacts);
282       return(p);
283     }
284   if (image->artifacts != (void *) NULL)
285     {
286       p=(const char *) GetValueFromSplayTree((SplayTreeInfo *) image->artifacts,
287         artifact);
288       if (p != (const char *) NULL)
289         return(p);
290     }
291   return(p);
292 }
293 
294 /*
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 %                                                                             %
297 %                                                                             %
298 %                                                                             %
299 %   G e t N e x t I m a g e A r t i f a c t                                   %
300 %                                                                             %
301 %                                                                             %
302 %                                                                             %
303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304 %
305 %  GetNextImageArtifact() gets the next image artifact value.
306 %
307 %  The format of the GetNextImageArtifact method is:
308 %
309 %      char *GetNextImageArtifact(const Image *image)
310 %
311 %  A description of each parameter follows:
312 %
313 %    o image: the image.
314 %
315 */
GetNextImageArtifact(const Image * image)316 MagickExport char *GetNextImageArtifact(const Image *image)
317 {
318   assert(image != (Image *) NULL);
319   assert(image->signature == MagickCoreSignature);
320   if (image->debug != MagickFalse)
321     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
322   if (image->artifacts == (void *) NULL)
323     return((char *) NULL);
324   return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->artifacts));
325 }
326 
327 /*
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 %                                                                             %
330 %                                                                             %
331 %                                                                             %
332 %   R e m o v e I m a g e A r t i f a c t                                     %
333 %                                                                             %
334 %                                                                             %
335 %                                                                             %
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %
338 %  RemoveImageArtifact() removes an artifact from the image and returns its
339 %  value.
340 %
341 %  The format of the RemoveImageArtifact method is:
342 %
343 %      char *RemoveImageArtifact(Image *image,const char *artifact)
344 %
345 %  A description of each parameter follows:
346 %
347 %    o image: the image.
348 %
349 %    o artifact: the image artifact.
350 %
351 */
RemoveImageArtifact(Image * image,const char * artifact)352 MagickExport char *RemoveImageArtifact(Image *image,const char *artifact)
353 {
354   char
355     *value;
356 
357   assert(image != (Image *) NULL);
358   assert(image->signature == MagickCoreSignature);
359   if (image->debug != MagickFalse)
360     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
361   if (image->artifacts == (void *) NULL)
362     return((char *) NULL);
363   value=(char *) RemoveNodeFromSplayTree((SplayTreeInfo *) image->artifacts,
364     artifact);
365   return(value);
366 }
367 
368 /*
369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 %                                                                             %
371 %                                                                             %
372 %                                                                             %
373 %   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                       %
374 %                                                                             %
375 %                                                                             %
376 %                                                                             %
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378 %
379 %  ResetImageArtifactIterator() resets the image artifact iterator.  Use it
380 %  in conjunction with GetNextImageArtifact() to iterate over all the values
381 %  associated with an image artifact.
382 %
383 %  The format of the ResetImageArtifactIterator method is:
384 %
385 %      ResetImageArtifactIterator(Image *image)
386 %
387 %  A description of each parameter follows:
388 %
389 %    o image: the image.
390 %
391 */
ResetImageArtifactIterator(const Image * image)392 MagickExport void ResetImageArtifactIterator(const Image *image)
393 {
394   assert(image != (Image *) NULL);
395   assert(image->signature == MagickCoreSignature);
396   if (image->debug != MagickFalse)
397     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
398   if (image->artifacts == (void *) NULL)
399     return;
400   ResetSplayTreeIterator((SplayTreeInfo *) image->artifacts);
401 }
402 
403 /*
404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405 %                                                                             %
406 %                                                                             %
407 %                                                                             %
408 %   S e t I m a g e A r t i f a c t                                           %
409 %                                                                             %
410 %                                                                             %
411 %                                                                             %
412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413 %
414 %  SetImageArtifact() sets a key-value pair in the image artifact namespace.
415 %  Artifacts differ from properties.  Properties are public and are generally
416 %  exported to an external image format if the format supports it.  Artifacts
417 %  are private and are utilized by the internal ImageMagick API to modify the
418 %  behavior of certain algorithms.
419 %
420 %  The format of the SetImageArtifact method is:
421 %
422 %      MagickBooleanType SetImageArtifact(Image *image,const char *artifact,
423 %        const char *value)
424 %
425 %  A description of each parameter follows:
426 %
427 %    o image: the image.
428 %
429 %    o artifact: the image artifact key.
430 %
431 %    o value: the image artifact value.
432 %
433 */
SetImageArtifact(Image * image,const char * artifact,const char * value)434 MagickExport MagickBooleanType SetImageArtifact(Image *image,
435   const char *artifact,const char *value)
436 {
437   MagickBooleanType
438     status;
439 
440   assert(image != (Image *) NULL);
441   assert(image->signature == MagickCoreSignature);
442   if (image->debug != MagickFalse)
443     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
444   /*
445     Create tree if needed.
446   */
447   if (image->artifacts == (void *) NULL)
448     image->artifacts=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
449       RelinquishMagickMemory);
450   /*
451     Delete artifact if NULL --  empty string values are valid!
452   */
453   if (value == (const char *) NULL)
454     return(DeleteImageArtifact(image,artifact));
455   /*
456     Add artifact to tree.
457   */
458   status=AddValueToSplayTree((SplayTreeInfo *) image->artifacts,
459     ConstantString(artifact),ConstantString(value));
460   return(status);
461 }
462