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