Coverage Report

Created: 2025-06-16 07:00

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