Coverage Report

Created: 2025-10-12 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/MagickCore/artifact.c
Line
Count
Source
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 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 receive the cloned artifacts.
98
%
99
%    o clone_image: the source image for artifacts to clone.
100
%
101
*/
102
103
typedef char
104
  *(*CloneKeyFunc)(const char *),
105
  *(*CloneValueFunc)(const char *);
106
107
static inline void *CloneArtifactKey(void *key)
108
266k
{
109
266k
  return((void *) ((CloneKeyFunc) ConstantString)((const char *) key));
110
266k
}
111
112
static inline void *CloneArtifactValue(void *value)
113
266k
{
114
266k
  return((void *) ((CloneValueFunc) ConstantString)((const char *) value));
115
266k
}
116
117
MagickExport MagickBooleanType CloneImageArtifacts(Image *image,
118
  const Image *clone_image)
119
545k
{
120
545k
  assert(image != (Image *) NULL);
121
545k
  assert(image->signature == MagickCoreSignature);
122
545k
  assert(clone_image != (const Image *) NULL);
123
545k
  assert(clone_image->signature == MagickCoreSignature);
124
545k
  if (IsEventLogging() != MagickFalse)
125
0
    {
126
0
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
127
0
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
128
0
        clone_image->filename);
129
0
    }
130
545k
  if (clone_image->artifacts != (void *) NULL)
131
236k
    {
132
236k
      if (image->artifacts != (void *) NULL)
133
0
        DestroyImageArtifacts(image);
134
236k
      image->artifacts=CloneSplayTree((SplayTreeInfo *) clone_image->artifacts,
135
236k
        CloneArtifactKey,CloneArtifactValue);
136
236k
    }
137
545k
  return(MagickTrue);
138
545k
}
139

140
/*
141
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142
%                                                                             %
143
%                                                                             %
144
%                                                                             %
145
%   D e f i n e I m a g e A r t i f a c t                                     %
146
%                                                                             %
147
%                                                                             %
148
%                                                                             %
149
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150
%
151
%  DefineImageArtifact() associates an assignment string of the form
152
%  "key=value" with per-image artifact. It is equivalent to
153
%  SetImageArtifact().
154
%
155
%  The format of the DefineImageArtifact method is:
156
%
157
%      MagickBooleanType DefineImageArtifact(Image *image,
158
%        const char *artifact)
159
%
160
%  A description of each parameter follows:
161
%
162
%    o image: the image.
163
%
164
%    o artifact: the image artifact.
165
%
166
*/
167
MagickExport MagickBooleanType DefineImageArtifact(Image *image,
168
  const char *artifact)
169
0
{
170
0
  char
171
0
    key[MagickPathExtent],
172
0
    value[MagickPathExtent];
173
174
0
  char
175
0
    *p;
176
177
0
  assert(image != (Image *) NULL);
178
0
  assert(artifact != (const char *) NULL);
179
0
  (void) CopyMagickString(key,artifact,MagickPathExtent-1);
180
0
  for (p=key; *p != '\0'; p++)
181
0
    if (*p == '=')
182
0
      break;
183
0
  *value='\0';
184
0
  if (*p == '=')
185
0
    (void) CopyMagickString(value,p+1,MagickPathExtent);
186
0
  *p='\0';
187
0
  return(SetImageArtifact(image,key,value));
188
0
}
189

190
/*
191
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192
%                                                                             %
193
%                                                                             %
194
%                                                                             %
195
%   D e l e t e I m a g e A r t i f a c t                                     %
196
%                                                                             %
197
%                                                                             %
198
%                                                                             %
199
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200
%
201
%  DeleteImageArtifact() deletes an image artifact.
202
%
203
%  The format of the DeleteImageArtifact method is:
204
%
205
%      MagickBooleanType DeleteImageArtifact(Image *image,const char *artifact)
206
%
207
%  A description of each parameter follows:
208
%
209
%    o image: the image.
210
%
211
%    o artifact: the image artifact.
212
%
213
*/
214
MagickExport MagickBooleanType DeleteImageArtifact(Image *image,
215
  const char *artifact)
216
100k
{
217
100k
  assert(image != (Image *) NULL);
218
100k
  assert(image->signature == MagickCoreSignature);
219
100k
  if (IsEventLogging() != MagickFalse)
220
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
221
100k
  if (image->artifacts == (void *) NULL)
222
81.7k
    return(MagickFalse);
223
19.1k
  return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->artifacts,artifact));
224
100k
}
225

226
/*
227
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228
%                                                                             %
229
%                                                                             %
230
%                                                                             %
231
%   D e s t r o y I m a g e A r t i f a c t s                                 %
232
%                                                                             %
233
%                                                                             %
234
%                                                                             %
235
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236
%
237
%  DestroyImageArtifacts() destroys all artifacts and associated memory
238
%  attached to the given image.
239
%
240
%  The format of the DestroyImageArtifacts method is:
241
%
242
%      void DestroyImageArtifacts(Image *image)
243
%
244
%  A description of each parameter follows:
245
%
246
%    o image: the image.
247
%
248
*/
249
MagickExport void DestroyImageArtifacts(Image *image)
250
3.60M
{
251
3.60M
  assert(image != (Image *) NULL);
252
3.60M
  assert(image->signature == MagickCoreSignature);
253
3.60M
  if (IsEventLogging() != MagickFalse)
254
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
255
3.60M
  if (image->artifacts != (void *) NULL)
256
467k
    image->artifacts=(void *) DestroySplayTree((SplayTreeInfo *)
257
467k
      image->artifacts);
258
3.60M
}
259

260
/*
261
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262
%                                                                             %
263
%                                                                             %
264
%                                                                             %
265
%   G e t I m a g e A r t i f a c t                                           %
266
%                                                                             %
267
%                                                                             %
268
%                                                                             %
269
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270
%
271
%  GetImageArtifact() gets a value associated with an image artifact.
272
%  If the requested artifact is NULL return the first artifact, to
273
%  prepare to iterate over all artifacts.
274
%
275
%  The returned string is a constant string in the tree and should NOT be
276
%  freed by the caller.
277
%
278
%  The format of the GetImageArtifact method is:
279
%
280
%      const char *GetImageArtifact(const Image *image,const char *key)
281
%
282
%  A description of each parameter follows:
283
%
284
%    o image: the image.
285
%
286
%    o key: the key.
287
%
288
*/
289
MagickExport const char *GetImageArtifact(const Image *image,
290
  const char *artifact)
291
1.96M
{
292
1.96M
  const char
293
1.96M
    *p;
294
295
1.96M
  assert(image != (Image *) NULL);
296
1.96M
  assert(image->signature == MagickCoreSignature);
297
1.96M
  if (IsEventLogging() != MagickFalse)
298
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
299
1.96M
  p=(const char *) NULL;
300
1.96M
  if (image->artifacts != (void *) NULL)
301
1.07M
    {
302
1.07M
      if (artifact == (const char *) NULL)
303
0
        return((const char *) GetRootValueFromSplayTree((SplayTreeInfo *)
304
0
          image->artifacts));
305
1.07M
      p=(const char *) GetValueFromSplayTree((SplayTreeInfo *) image->artifacts,
306
1.07M
        artifact);
307
1.07M
      if (p != (const char *) NULL)
308
138k
        return(p);
309
1.07M
    }
310
1.82M
  if ((image->image_info != (ImageInfo *) NULL) &&
311
1.74M
      (image->image_info->options != (void *) NULL))
312
0
    p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
313
0
      image->image_info->options,artifact);
314
1.82M
  return(p);
315
1.96M
}
316

317
/*
318
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319
%                                                                             %
320
%                                                                             %
321
%                                                                             %
322
%   G e t N e x t I m a g e A r t i f a c t                                   %
323
%                                                                             %
324
%                                                                             %
325
%                                                                             %
326
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327
%
328
%  GetNextImageArtifact() gets the next image artifact value.
329
%
330
%  The format of the GetNextImageArtifact method is:
331
%
332
%      char *GetNextImageArtifact(const Image *image)
333
%
334
%  A description of each parameter follows:
335
%
336
%    o image: the image.
337
%
338
*/
339
MagickExport const char *GetNextImageArtifact(const Image *image)
340
69
{
341
69
  assert(image != (Image *) NULL);
342
69
  assert(image->signature == MagickCoreSignature);
343
69
  if (IsEventLogging() != MagickFalse)
344
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
345
69
  if (image->artifacts == (void *) NULL)
346
10
    return((const char *) NULL);
347
59
  return((const char *) GetNextKeyInSplayTree(
348
59
   (SplayTreeInfo *) image->artifacts));
349
69
}
350

351
/*
352
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353
%                                                                             %
354
%                                                                             %
355
%                                                                             %
356
%   R e m o v e I m a g e A r t i f a c t                                     %
357
%                                                                             %
358
%                                                                             %
359
%                                                                             %
360
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361
%
362
%  RemoveImageArtifact() removes an artifact from the image and returns its
363
%  value.
364
%
365
%  In this case the ConstantString() value returned should be freed by the
366
%  caller when finished.
367
%
368
%  The format of the RemoveImageArtifact method is:
369
%
370
%      char *RemoveImageArtifact(Image *image,const char *artifact)
371
%
372
%  A description of each parameter follows:
373
%
374
%    o image: the image.
375
%
376
%    o artifact: the image artifact.
377
%
378
*/
379
MagickExport char *RemoveImageArtifact(Image *image,const char *artifact)
380
0
{
381
0
  char
382
0
    *value;
383
384
0
  assert(image != (Image *) NULL);
385
0
  assert(image->signature == MagickCoreSignature);
386
0
  if (IsEventLogging() != MagickFalse)
387
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
388
0
  if (image->artifacts == (void *) NULL)
389
0
    return((char *) NULL);
390
0
  value=(char *) RemoveNodeFromSplayTree((SplayTreeInfo *) image->artifacts,
391
0
    artifact);
392
0
  return(value);
393
0
}
394

395
/*
396
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397
%                                                                             %
398
%                                                                             %
399
%                                                                             %
400
%   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                       %
401
%                                                                             %
402
%                                                                             %
403
%                                                                             %
404
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405
%
406
%  ResetImageArtifactIterator() resets the image artifact iterator.  Use it
407
%  in conjunction with GetNextImageArtifact() to iterate over all the values
408
%  associated with an image artifact.
409
%
410
%  Alternatively you can use GetImageArtifact() with a NULL artifact field to
411
%  reset the iterator and return the first artifact.
412
%
413
%  The format of the ResetImageArtifactIterator method is:
414
%
415
%      ResetImageArtifactIterator(Image *image)
416
%
417
%  A description of each parameter follows:
418
%
419
%    o image: the image.
420
%
421
*/
422
MagickExport void ResetImageArtifactIterator(const Image *image)
423
45
{
424
45
  assert(image != (Image *) NULL);
425
45
  assert(image->signature == MagickCoreSignature);
426
45
  if (IsEventLogging() != MagickFalse)
427
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
428
45
  if (image->artifacts == (void *) NULL)
429
10
    return;
430
35
  ResetSplayTreeIterator((SplayTreeInfo *) image->artifacts);
431
35
}
432

433
/*
434
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435
%                                                                             %
436
%                                                                             %
437
%                                                                             %
438
%   S e t I m a g e A r t i f a c t                                           %
439
%                                                                             %
440
%                                                                             %
441
%                                                                             %
442
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443
%
444
%  SetImageArtifact() sets a key-value pair in the image artifact namespace.
445
%  Artifacts differ from properties.  Properties are public and are generally
446
%  exported to an external image format if the format supports it.  Artifacts
447
%  are private and are utilized by the internal ImageMagick API to modify the
448
%  behavior of certain algorithms.
449
%
450
%  The format of the SetImageArtifact method is:
451
%
452
%      MagickBooleanType SetImageArtifact(Image *image,const char *artifact,
453
%        const char *value)
454
%
455
%  A description of each parameter follows:
456
%
457
%    o image: the image.
458
%
459
%    o artifact: the image artifact key.
460
%
461
%    o value: the image artifact value.
462
%
463
*/
464
MagickExport MagickBooleanType SetImageArtifact(Image *image,
465
  const char *artifact,const char *value)
466
340k
{
467
340k
  MagickBooleanType
468
340k
    status;
469
470
340k
  assert(image != (Image *) NULL);
471
340k
  assert(image->signature == MagickCoreSignature);
472
340k
  if (IsEventLogging() != MagickFalse)
473
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
474
  /*
475
    Create tree if needed - specify how key,values are to be freed.
476
  */
477
340k
  if (image->artifacts == (void *) NULL)
478
230k
    image->artifacts=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
479
230k
      RelinquishMagickMemory);
480
  /*
481
    Delete artifact if NULL --  empty string values are valid!,
482
  */
483
340k
  if (value == (const char *) NULL)
484
0
    return(DeleteImageArtifact(image,artifact));
485
  /*
486
    Add artifact to splay-tree.
487
  */
488
340k
  status=AddValueToSplayTree((SplayTreeInfo *) image->artifacts,
489
340k
    ConstantString(artifact),ConstantString(value));
490
340k
  return(status);
491
340k
}