Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/magick/describe.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2026 GraphicsMagick Group
3
% Copyright (C) 2003 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
% SPDX-License-Identifier: MIT
6
%
7
% This program is covered by multiple licenses, which are described in
8
% Copyright.txt. You should have received a copy of Copyright.txt with this
9
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
10
%
11
% GraphicsMagick Describe Methods.
12
%
13
*/
14

15
/*
16
  Include declarations.
17
*/
18
#include "magick/studio.h"
19
#include "magick/analyze.h"
20
#include "magick/attribute.h"
21
#include "magick/blob.h"
22
#include "magick/channel.h"
23
#include "magick/color.h"
24
#include "magick/color_lookup.h"
25
#include "magick/constitute.h"
26
#include "magick/describe.h"
27
#include "magick/enum_strings.h"
28
#include "magick/magick.h"
29
#include "magick/pixel_cache.h"
30
#include "magick/profile.h"
31
#include "magick/signature.h"
32
#include "magick/statistics.h"
33
#include "magick/utility.h"
34

35
/*
36
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37
%                                                                             %
38
%                                                                             %
39
%                                                                             %
40
%   D e s c r i b e I m a g e                                                 %
41
%                                                                             %
42
%                                                                             %
43
%                                                                             %
44
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45
%
46
%  DescribeImage() describes an image by printing its attributes to the file.
47
%  Attributes include the image width, height, size, and others.
48
%
49
%  The format of the DescribeImage method is:
50
%
51
%      void DescribeImage(Image *image,FILE *file,const MagickBool verbose)
52
%
53
%  A description of each parameter follows:
54
%
55
%    o image: The image.
56
%
57
%    o file: The file, typically stdout.
58
%
59
%    o verbose: A value other than zero prints more detailed information
60
%      about the image. Values greater than one enable counting the number of
61
%      colors in the image.
62
%
63
%
64
*/
65
MagickExport MagickPassFail DescribeImage(Image *image,FILE *file,
66
                                          const MagickBool verbose)
67
0
{
68
0
  char
69
0
    color[MaxTextExtent],
70
0
    format[MaxTextExtent];
71
72
0
  const unsigned char
73
0
    *profile;
74
75
0
  size_t
76
0
    profile_length;
77
78
0
  const ImageAttribute
79
0
    *attribute;
80
81
0
  const MagickInfo
82
0
    *magick_info;
83
84
0
  double
85
0
    elapsed_time,
86
0
    user_time;
87
88
0
  unsigned long
89
0
    columns,
90
0
    rows;
91
92
0
  magick_int64_t
93
0
    pixels_per_second;
94
95
0
  Image
96
0
    *p;
97
98
0
  unsigned long
99
0
    y;
100
101
0
  register size_t
102
0
    i;
103
104
0
  register unsigned long
105
0
    x;
106
107
0
  unsigned long
108
0
    count;
109
110
0
  assert(image != (Image *) NULL);
111
0
  assert(image->signature == MagickSignature);
112
0
  assert(file != (FILE *) NULL);
113
0
  elapsed_time=GetElapsedTime(&image->timer);
114
0
  user_time=GetUserTime(&image->timer);
115
0
  GetTimerInfo(&image->timer);
116
0
  if (!verbose)
117
0
    {
118
      /*
119
        Display summary info about the image.
120
      */
121
0
      if (*image->magick_filename != '\0')
122
0
        if (LocaleCompare(image->magick_filename,image->filename) != 0)
123
0
          (void) fprintf(file,"%.1024s=>",image->magick_filename);
124
0
      if ((image->previous == (Image *) NULL) &&
125
0
          (image->next == (Image *) NULL) && (image->scene == 0))
126
0
        (void) fprintf(file,"%.1024s ",image->filename);
127
0
      else
128
0
        (void) fprintf(file,"%.1024s[%lu] ",image->filename,image->scene);
129
0
      (void) fprintf(file,"%.1024s ",image->magick);
130
0
      columns=image->columns;
131
0
      rows=image->rows;
132
0
      if ((image->magick_columns != 0) || (image->magick_rows != 0))
133
0
        if ((image->magick_columns != image->columns) ||
134
0
            (image->magick_rows != image->rows))
135
0
          {
136
0
            columns=image->magick_columns;
137
0
            rows=image->magick_rows;
138
0
            (void) fprintf(file,"%lux%lu=>",image->magick_columns,
139
0
                           image->magick_rows);
140
0
          }
141
0
      (void) fprintf(file,"%lux%lu%+ld%+ld ",image->columns,image->rows,
142
0
                     image->page.x,image->page.y);
143
0
      if (image->storage_class == DirectClass)
144
0
        {
145
0
          (void) fprintf(file,"DirectClass ");
146
0
          if (image->total_colors != 0)
147
0
            {
148
0
              FormatSize(image->total_colors,format);
149
0
              (void) fprintf(file,"%.1024s ",format);
150
0
            }
151
0
        }
152
0
      else
153
0
        if (image->total_colors <= image->colors)
154
0
          (void) fprintf(file,"PseudoClass %uc ",image->colors);
155
0
        else
156
0
          {
157
0
            (void) fprintf(file,"PseudoClass %lu=>%uc ",image->total_colors,
158
0
                           image->colors);
159
0
            (void) fprintf(file,"%ld/%.6f/%.6fe ",
160
0
                           (long) image->error.mean_error_per_pixel,
161
0
                           image->error.normalized_mean_error,
162
0
                           image->error.normalized_maximum_error);
163
0
          }
164
0
      if(image->matte==MagickTrue)
165
0
          (void) fputs("+opacity ",file);
166
0
      (void) fprintf(file,"%u-bit ",image->depth);
167
0
      if (GetBlobSize(image) != 0)
168
0
        {
169
0
          FormatSize(GetBlobSize(image),format);
170
0
          (void) fprintf(file,"%.1024s ",format);
171
0
        }
172
0
      (void) fprintf(file,"%0.3fu %ldm:%.6fs",
173
0
                     user_time,
174
0
                     (long) (elapsed_time/60.0),
175
0
                     fmod(elapsed_time,60.0));
176
      /*
177
        Only display pixel read rate if the time accumulated is at
178
        least six times the timer's resolution (typically 0.01 on
179
        Unix).
180
      */
181
0
      if (!(image->ping) && (elapsed_time > 0.001) &&
182
0
          (elapsed_time >= GetTimerResolution()*6))
183
0
        {
184
0
          pixels_per_second=(magick_int64_t) ((double) rows*columns/
185
0
                                              elapsed_time);
186
0
          FormatSize(pixels_per_second,format);
187
0
          (void) fprintf(file," (%s pixels/s)",format);
188
0
        }
189
0
      (void) fprintf(file,"\n");
190
191
0
      return (ferror(file) ? MagickFail : MagickPass);
192
0
    }
193
  /*
194
    Display verbose info about the image.
195
  */
196
0
  (void) SignatureImage(image);
197
0
  if (verbose > 1)
198
0
    image->total_colors=GetNumberColors(image,(FILE *) NULL,&image->exception);
199
0
  (void) fprintf(file,"Image: %.1024s\n",image->filename);
200
0
  magick_info=GetMagickInfo(image->magick,&image->exception);
201
0
  if ((magick_info == (const MagickInfo *) NULL) ||
202
0
      (*magick_info->description == '\0'))
203
0
    (void) fprintf(file,"  Format: %.1024s\n",image->magick);
204
0
  else
205
0
    (void) fprintf(file,"  Format: %.1024s (%.1024s)\n",image->magick,
206
0
                   magick_info->description);
207
0
  (void) fprintf(file,"  Geometry: %lux%lu\n",image->columns,image->rows);
208
0
  if (image->storage_class == DirectClass)
209
0
    (void) fprintf(file,"  Class: DirectClass\n");
210
0
  else
211
0
    (void) fprintf(file,"  Class: PseudoClass\n");
212
0
  if ((image->magick_columns != 0) || (image->magick_rows != 0))
213
0
    if ((image->magick_columns != image->columns) ||
214
0
        (image->magick_rows != image->rows))
215
0
      (void) fprintf(file,"  Base geometry: %lux%lu\n",image->magick_columns,
216
0
                     image->magick_rows);
217
0
  (void) fprintf(file,"  Type: ");
218
0
  switch (GetImageType(image,&image->exception))
219
0
    {
220
0
    case BilevelType: (void) fprintf(file,"bilevel"); break;
221
0
    case GrayscaleType: (void) fprintf(file,"grayscale"); break;
222
0
    case GrayscaleMatteType:
223
0
      (void) fprintf(file,"grayscale with transparency"); break;
224
0
    case PaletteType: (void) fprintf(file,"palette"); break;
225
0
    case PaletteMatteType:
226
0
      (void) fprintf(file,"palette with transparency"); break;
227
0
    case TrueColorType: (void) fprintf(file,"true color"); break;
228
0
    case TrueColorMatteType:
229
0
      (void) fprintf(file,"true color with transparency"); break;
230
0
    case ColorSeparationType: (void) fprintf(file,"color separated"); break;
231
0
    case ColorSeparationMatteType:
232
0
      (void) fprintf(file,"color separated with transparency"); break;
233
0
    default: (void) fprintf(file,"undefined"); break;
234
0
    }
235
0
  (void) fprintf(file,"\n");
236
0
  (void) fprintf(file,"  Depth: %lu bits-per-pixel component\n",
237
0
                 GetImageDepth(image,&image->exception));
238
0
  (void) fprintf(file,"  Channel Depths:\n");
239
0
  if (image->colorspace == CMYKColorspace)
240
0
    {
241
0
      (void) fprintf(file,"    Cyan:     %u bits\n",
242
0
                     GetImageChannelDepth(image,CyanChannel,
243
0
                                          &image->exception));
244
0
      (void) fprintf(file,"    Magenta:  %u bits\n",
245
0
                     GetImageChannelDepth(image,MagentaChannel,
246
0
                                          &image->exception));
247
0
      (void) fprintf(file,"    Yellow:   %u bits\n",
248
0
                     GetImageChannelDepth(image,YellowChannel,
249
0
                                          &image->exception));
250
0
      (void) fprintf(file,"    Black:    %u bits\n",
251
0
                     GetImageChannelDepth(image,BlackChannel,
252
0
                                          &image->exception));
253
0
    }
254
0
  else if ((IsGrayColorspace(image->colorspace)) ||
255
0
           (image->is_grayscale == True))
256
0
    {
257
0
      (void) fprintf(file,"    Gray:     %u bits\n",
258
0
                     GetImageChannelDepth(image,RedChannel,
259
0
                                          &image->exception));
260
0
    }
261
0
  else
262
0
    {
263
0
      (void) fprintf(file,"    Red:      %u bits\n",
264
0
                     GetImageChannelDepth(image,RedChannel,
265
0
                                          &image->exception));
266
0
      (void) fprintf(file,"    Green:    %u bits\n",
267
0
                     GetImageChannelDepth(image,GreenChannel,
268
0
                                          &image->exception));
269
0
      (void) fprintf(file,"    Blue:     %u bits\n",
270
0
                     GetImageChannelDepth(image,BlueChannel,
271
0
                                          &image->exception));
272
0
    }
273
0
  if (image->matte)
274
0
    (void) fprintf(file,"    Opacity:  %u bits\n",
275
0
                   GetImageChannelDepth(image,OpacityChannel,
276
0
                                        &image->exception));
277
0
  (void) fprintf(file,"  Channel Statistics:\n");
278
0
  {
279
0
    ImageStatistics
280
0
      statistics;
281
282
0
    (void) GetImageStatistics(image,&statistics,&image->exception);
283
284
0
    if (image->colorspace == CMYKColorspace)
285
0
      {
286
0
        (void) fprintf(file,"    Cyan:\n");
287
0
        (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
288
0
                       MaxRGB*statistics.red.minimum,
289
0
                       statistics.red.minimum);
290
0
        (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
291
0
                       MaxRGB*statistics.red.maximum,
292
0
                       statistics.red.maximum);
293
0
        (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
294
0
                       MaxRGB*statistics.red.mean,
295
0
                       statistics.red.mean);
296
0
        (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
297
0
                       MaxRGB*statistics.red.standard_deviation,
298
0
                       statistics.red.standard_deviation);
299
0
        (void) fprintf(file,"    Magenta:\n");
300
0
        (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
301
0
                       MaxRGB*statistics.green.minimum,
302
0
                       statistics.green.minimum);
303
0
        (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
304
0
                       MaxRGB*statistics.green.maximum,
305
0
                       statistics.green.maximum);
306
0
        (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
307
0
                       MaxRGB*statistics.green.mean,
308
0
                       statistics.green.mean);
309
0
        (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
310
0
                       MaxRGB*statistics.green.standard_deviation,
311
0
                       statistics.green.standard_deviation);
312
0
        (void) fprintf(file,"    Yellow:\n");
313
0
        (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
314
0
                       MaxRGB*statistics.blue.minimum,
315
0
                       statistics.blue.minimum);
316
0
        (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
317
0
                       MaxRGB*statistics.blue.maximum,
318
0
                       statistics.blue.maximum);
319
0
        (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
320
0
                       MaxRGB*statistics.blue.mean,
321
0
                       statistics.blue.mean);
322
0
        (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
323
0
                       MaxRGB*statistics.blue.standard_deviation,
324
0
                       statistics.blue.standard_deviation);
325
0
        (void) fprintf(file,"    Black:\n");
326
0
        (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
327
0
                       MaxRGB*statistics.opacity.minimum,
328
0
                       statistics.opacity.minimum);
329
0
        (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
330
0
                       MaxRGB*statistics.opacity.maximum,
331
0
                       statistics.opacity.maximum);
332
0
        (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
333
0
                       MaxRGB*statistics.opacity.mean,
334
0
                       statistics.opacity.mean);
335
0
        (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
336
0
                       MaxRGB*statistics.opacity.standard_deviation,
337
0
                       statistics.opacity.standard_deviation);
338
        /*
339
          if (image->matte)
340
          (void) fprintf(file,"    Opacity:\n");
341
        */
342
0
      }
343
0
    else if ((IsGrayColorspace(image->colorspace)) ||
344
0
             (image->is_grayscale == MagickTrue))
345
0
      {
346
0
        (void) fprintf(file,"    Gray:\n");
347
0
        (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
348
0
                       MaxRGB*statistics.red.minimum,
349
0
                       statistics.red.minimum);
350
0
        (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
351
0
                       MaxRGB*statistics.red.maximum,
352
0
                       statistics.red.maximum);
353
0
        (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
354
0
                       MaxRGB*statistics.red.mean,
355
0
                       statistics.red.mean);
356
0
        (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
357
0
                       MaxRGB*statistics.red.standard_deviation,
358
0
                       statistics.red.standard_deviation);
359
0
        if (image->matte)
360
0
          {
361
0
            (void) fprintf(file,"    Opacity:\n");
362
0
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
363
0
                           MaxRGB*statistics.opacity.minimum,
364
0
                           statistics.opacity.minimum);
365
0
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
366
0
                           MaxRGB*statistics.opacity.maximum,
367
0
                           statistics.opacity.maximum);
368
0
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
369
0
                           MaxRGB*statistics.opacity.mean,
370
0
                           statistics.opacity.mean);
371
0
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
372
0
                           MaxRGB*statistics.opacity.standard_deviation,
373
0
                           statistics.opacity.standard_deviation);
374
0
          }
375
0
      }
376
0
    else
377
0
      {
378
0
        (void) fprintf(file,"    Red:\n");
379
0
        (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
380
0
                       MaxRGB*statistics.red.minimum,
381
0
                       statistics.red.minimum);
382
0
        (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
383
0
                       MaxRGB*statistics.red.maximum,
384
0
                       statistics.red.maximum);
385
0
        (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
386
0
                       MaxRGB*statistics.red.mean,
387
0
                       statistics.red.mean);
388
0
        (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
389
0
                       MaxRGB*statistics.red.standard_deviation,
390
0
                       statistics.red.standard_deviation);
391
0
        (void) fprintf(file,"    Green:\n");
392
0
        (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
393
0
                       MaxRGB*statistics.green.minimum,
394
0
                       statistics.green.minimum);
395
0
        (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
396
0
                       MaxRGB*statistics.green.maximum,
397
0
                       statistics.green.maximum);
398
0
        (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
399
0
                       MaxRGB*statistics.green.mean,
400
0
                       statistics.green.mean);
401
0
        (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
402
0
                       MaxRGB*statistics.green.standard_deviation,
403
0
                       statistics.green.standard_deviation);
404
0
        (void) fprintf(file,"    Blue:\n");
405
0
        (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
406
0
                       MaxRGB*statistics.blue.minimum,
407
0
                       statistics.blue.minimum);
408
0
        (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
409
0
                       MaxRGB*statistics.blue.maximum,
410
0
                       statistics.blue.maximum);
411
0
        (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
412
0
                       MaxRGB*statistics.blue.mean,
413
0
                       statistics.blue.mean);
414
0
        (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
415
0
                       MaxRGB*statistics.blue.standard_deviation,
416
0
                       statistics.blue.standard_deviation);
417
0
        if (image->matte)
418
0
          {
419
0
            (void) fprintf(file,"    Opacity:\n");
420
0
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
421
0
                           MaxRGB*statistics.opacity.minimum,
422
0
                           statistics.opacity.minimum);
423
0
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
424
0
                           MaxRGB*statistics.opacity.maximum,
425
0
                           statistics.opacity.maximum);
426
0
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
427
0
                           MaxRGB*statistics.opacity.mean,
428
0
                           statistics.opacity.mean);
429
0
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
430
0
                           MaxRGB*statistics.opacity.standard_deviation,
431
0
                           statistics.opacity.standard_deviation);
432
0
          }
433
0
      }
434
0
  }
435
0
  x=0;
436
0
  p=(Image *) NULL;
437
0
  if ((image->matte && (strcmp(image->magick,"GIF") != 0)) || image->taint)
438
0
    {
439
0
      char
440
0
        tuple[MaxTextExtent];
441
442
0
      MagickBool
443
0
        found_transparency;
444
445
0
      register const PixelPacket
446
0
        *p;
447
448
0
      p=(PixelPacket *) NULL;
449
0
      found_transparency = MagickFalse;
450
0
      for (y=0; y < image->rows; y++)
451
0
        {
452
0
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
453
0
          if (p == (const PixelPacket *) NULL)
454
0
            break;
455
0
          for (x=0; x < image->columns; x++)
456
0
            {
457
0
              if (p->opacity == TransparentOpacity)
458
0
                {
459
0
                  found_transparency=MagickTrue;
460
0
                  break;
461
0
                }
462
0
              p++;
463
0
            }
464
0
          if (x < image->columns)
465
0
            break;
466
0
        }
467
0
      if (found_transparency)
468
0
        {
469
0
          GetColorTuple(p,image->depth,image->matte,False,tuple);
470
0
          (void) fprintf(file,"  Opacity: %.1024s\t",tuple);
471
0
          GetColorTuple(p,image->depth,image->matte,True,tuple);
472
0
          (void) fprintf(file,"  %.1024s\n",tuple);
473
0
        }
474
0
    }
475
0
  if (image->storage_class == DirectClass)
476
0
    {
477
0
      if (image->total_colors != 0)
478
0
        (void) fprintf(file,"  Colors: %lu\n",image->total_colors);
479
0
    }
480
0
  else
481
0
    {
482
0
      if (image->total_colors <= image->colors)
483
0
        (void) fprintf(file,"  Colors: %u\n",image->colors);
484
0
      else
485
0
        (void) fprintf(file,"  Colors: %lu=>%u\n",image->total_colors,
486
0
                       image->colors);
487
0
    }
488
0
  if (image->storage_class == DirectClass)
489
0
    {
490
0
      if (image->total_colors < 1024)
491
0
        if (verbose > 1)
492
0
          (void) GetNumberColors(image,file,&image->exception);
493
0
    }
494
0
  else
495
0
    {
496
0
      char
497
0
        name[MaxTextExtent];
498
499
0
      register PixelPacket
500
0
        *p;
501
502
      /*
503
        Display image colormap.
504
      */
505
0
      p=image->colormap;
506
0
      for (i=0; i < image->colors; i++)
507
0
        {
508
0
          char
509
0
            tuple[MaxTextExtent];
510
511
0
          GetColorTuple(p,image->depth,image->matte,False,tuple);
512
0
          (void) fprintf(file,"    %" MAGICK_SIZE_T_F "u: %.1024s",
513
0
                         (MAGICK_SIZE_T) i,tuple);
514
0
          (void) fprintf(file,"\t");
515
0
          (void) QueryColorname(image,p,SVGCompliance,name,&image->exception);
516
0
          (void) fprintf(file,"  %.1024s",name);
517
0
          (void) fprintf(file,"\n");
518
0
          p++;
519
0
        }
520
0
    }
521
0
  if (image->error.mean_error_per_pixel != 0.0)
522
0
    (void) fprintf(file,"  Mean Exception Per Pixel: %ld\n",
523
0
                   (long) image->error.mean_error_per_pixel);
524
0
  if (image->error.normalized_mean_error != 0.0)
525
0
    (void) fprintf(file,"  Normalized Mean Exception: %g\n",
526
0
                   image->error.normalized_mean_error);
527
0
  if (image->error.normalized_maximum_error != 0.0)
528
0
    (void) fprintf(file,"  Normalized Maximum Exception: %gn",
529
0
                   image->error.normalized_maximum_error);
530
0
  if (image->rendering_intent == SaturationIntent)
531
0
    (void) fprintf(file,"  Rendering-Intent: saturation\n");
532
0
  else
533
0
    if (image->rendering_intent == PerceptualIntent)
534
0
      (void) fprintf(file,"  Rendering-Intent: perceptual\n");
535
0
    else
536
0
      if (image->rendering_intent == AbsoluteIntent)
537
0
        (void) fprintf(file,"  Rendering-Intent: absolute\n");
538
0
      else
539
0
        if (image->rendering_intent == RelativeIntent)
540
0
          (void) fprintf(file,"  Rendering-Intent: relative\n");
541
0
  if (image->gamma != 0.0)
542
0
    (void) fprintf(file,"  Gamma: %g\n",image->gamma);
543
0
  if ((image->chromaticity.red_primary.x != 0.0) ||
544
0
      (image->chromaticity.green_primary.x != 0.0) ||
545
0
      (image->chromaticity.blue_primary.x != 0.0) ||
546
0
      (image->chromaticity.white_point.x != 0.0))
547
0
    {
548
      /*
549
        Display image chromaticity.
550
      */
551
0
      (void) fprintf(file,"  Chromaticity:\n");
552
0
      (void) fprintf(file,"    red primary: (%g,%g)\n",
553
0
                     image->chromaticity.red_primary.x,
554
0
                     image->chromaticity.red_primary.y);
555
0
      (void) fprintf(file,"    green primary: (%g,%g)\n",
556
0
                     image->chromaticity.green_primary.x,
557
0
                     image->chromaticity.green_primary.y);
558
0
      (void) fprintf(file,"    blue primary: (%g,%g)\n",
559
0
                     image->chromaticity.blue_primary.x,
560
0
                     image->chromaticity.blue_primary.y);
561
0
      (void) fprintf(file,"    white point: (%g,%g)\n",
562
0
                     image->chromaticity.white_point.x,
563
0
                     image->chromaticity.white_point.y);
564
0
    }
565
0
  if ((image->tile_info.width*image->tile_info.height) != 0)
566
0
    (void) fprintf(file,"  Tile geometry: %lux%lu%+ld%+ld\n",
567
0
                   image->tile_info.width,image->tile_info.height,
568
0
                   image->tile_info.x,
569
0
                   image->tile_info.y);
570
0
  if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
571
0
    {
572
      /*
573
        Display image resolution.
574
      */
575
0
      (void) fprintf(file,"  Resolution: %gx%g",image->x_resolution,
576
0
                     image->y_resolution);
577
0
      if (image->units == UndefinedResolution)
578
0
        (void) fprintf(file," pixels\n");
579
0
      else
580
0
        if (image->units == PixelsPerInchResolution)
581
0
          (void) fprintf(file," pixels/inch\n");
582
0
        else
583
0
          if (image->units == PixelsPerCentimeterResolution)
584
0
            (void) fprintf(file," pixels/centimeter\n");
585
0
          else
586
0
            (void) fprintf(file,"\n");
587
0
    }
588
0
  FormatSize(GetBlobSize(image),format);
589
0
  (void) fprintf(file,"  Filesize: %.1024s\n",format);
590
0
  fprintf(file,"  Interlace: %s\n",
591
0
          InterlaceTypeToString(image->interlace == UndefinedInterlace ?
592
0
                                NoInterlace : image->interlace));
593
0
  (void) fprintf(file,"  Orientation: %s\n",
594
0
                 OrientationTypeToString(image->orientation));
595
0
  (void) QueryColorname(image,&image->background_color,SVGCompliance,color,
596
0
                        &image->exception);
597
0
  (void) fprintf(file,"  Background Color: %.1024s\n",color);
598
0
  (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
599
0
                        &image->exception);
600
0
  (void) fprintf(file,"  Border Color: %.1024s\n",color);
601
0
  (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
602
0
                        &image->exception);
603
0
  (void) fprintf(file,"  Matte Color: %.1024s\n",color);
604
0
  if ((image->page.width != 0) && (image->page.height != 0))
605
0
    (void) fprintf(file,"  Page geometry: %lux%lu%+ld%+ld\n",image->page.width,
606
0
                   image->page.height,image->page.x,image->page.y);
607
0
  (void) fprintf(file,"  Compose: %s\n",
608
0
                 CompositeOperatorToString(image->compose));
609
0
  (void) fprintf(file,"  Dispose: ");
610
0
  switch (image->dispose)
611
0
    {
612
0
    case UndefinedDispose: (void) fprintf(file,"Undefined\n"); break;
613
0
    case NoneDispose: (void) fprintf(file,"None\n"); break;
614
0
    case BackgroundDispose: (void) fprintf(file,"Background\n"); break;
615
0
    case PreviousDispose: (void) fprintf(file,"Previous\n"); break;
616
0
    default: (void) fprintf(file,"\n");  break;
617
0
    }
618
0
  if (image->delay != 0)
619
0
    (void) fprintf(file,"  Delay: %lu\n",image->delay);
620
0
  if (image->iterations != 1)
621
0
    (void) fprintf(file,"  Iterations: %lu\n",image->iterations);
622
0
  p=image;
623
0
  while (p->previous != (Image *) NULL)
624
0
    p=p->previous;
625
0
  for (count=1; p->next != (Image *) NULL; count++)
626
0
    p=p->next;
627
0
  if (count > 1)
628
0
    (void) fprintf(file,"  Scene: %lu of %lu\n",image->scene,count);
629
0
  else
630
0
    if (image->scene != 0)
631
0
      (void) fprintf(file,"  Scene: %lu\n",image->scene);
632
0
  (void) fprintf(file,"  Compression: %s\n",
633
0
                 CompressionTypeToString(image->compression));
634
  /*
635
    Display formatted image attributes. This must happen before we access
636
    any pseudo attributes like EXIF since doing so causes real attributes
637
    to be created and we would get duplicates in the output.
638
  */
639
0
  attribute=GetImageAttribute(image,(char *) NULL);
640
0
  {
641
0
    for ( ; attribute != (const ImageAttribute *) NULL;
642
0
          attribute=attribute->next)
643
0
      {
644
0
        if (LocaleNCompare("EXIF",attribute->key,4) != 0)
645
0
          {
646
0
            (void) fprintf(file,"  %c", toupper((int)attribute->key[0]));
647
0
            if (strlen(attribute->key) > 1)
648
0
              (void) fprintf(file,"%.1024s",attribute->key+1);
649
650
0
            (void) fprintf(file,": ");
651
0
            (void) fprintf(file,"%s\n",attribute->value);
652
0
          }
653
0
      }
654
0
  }
655
0
  if((profile=GetImageProfile(image,"ICM",&profile_length)) != 0)
656
0
    (void) fprintf(file,"  Profile-color: %lu bytes\n",(unsigned long)
657
0
                   profile_length);
658
0
  if((profile=GetImageProfile(image,"IPTC",&profile_length)) != 0)
659
0
    {
660
0
      char
661
0
        *tag,
662
0
        *text;
663
664
0
      size_t
665
0
        length;
666
667
      /*
668
        Describe IPTC data.
669
      */
670
0
      (void) fprintf(file,"  Profile-iptc: %lu bytes\n",(unsigned long)
671
0
                     profile_length);
672
0
      for (i=0; i+5U < profile_length; )
673
0
        {
674
0
          if (profile[i] != 0x1c)
675
0
            {
676
0
              i++;
677
0
              continue;
678
0
            }
679
0
          i++;  /* skip file separator */
680
0
          i++;  /* skip record number */
681
0
          switch (profile[i])
682
0
            {
683
0
            case 5: tag=(char *) "Image Name"; break;
684
0
            case 7: tag=(char *) "Edit Status"; break;
685
0
            case 10: tag=(char *) "Priority"; break;
686
0
            case 15: tag=(char *) "Category"; break;
687
0
            case 20: tag=(char *) "Supplemental Category"; break;
688
0
            case 22: tag=(char *) "Fixture Identifier"; break;
689
0
            case 25: tag=(char *) "Keyword"; break;
690
0
            case 30: tag=(char *) "Release Date"; break;
691
0
            case 35: tag=(char *) "Release Time"; break;
692
0
            case 40: tag=(char *) "Special Instructions"; break;
693
0
            case 45: tag=(char *) "Reference Service"; break;
694
0
            case 47: tag=(char *) "Reference Date"; break;
695
0
            case 50: tag=(char *) "Reference Number"; break;
696
0
            case 55: tag=(char *) "Created Date"; break;
697
0
            case 60: tag=(char *) "Created Time"; break;
698
0
            case 65: tag=(char *) "Originating Program"; break;
699
0
            case 70: tag=(char *) "Program Version"; break;
700
0
            case 75: tag=(char *) "Object Cyc"; break;
701
0
            case 80: tag=(char *) "Byline"; break;
702
0
            case 85: tag=(char *) "Byline Title"; break;
703
0
            case 90: tag=(char *) "City"; break;
704
0
            case 95: tag=(char *) "Province State"; break;
705
0
            case 100: tag=(char *) "Country Code"; break;
706
0
            case 101: tag=(char *) "Country"; break;
707
0
            case 103: tag=(char *) "Original Transmission Reference"; break;
708
0
            case 105: tag=(char *) "Headline"; break;
709
0
            case 110: tag=(char *) "Credit"; break;
710
0
            case 115: tag=(char *) "Source"; break;
711
0
            case 116: tag=(char *) "Copyright String"; break;
712
0
            case 120: tag=(char *) "Caption"; break;
713
0
            case 121: tag=(char *) "Local Caption"; break;
714
0
            case 122: tag=(char *) "Caption Writer"; break;
715
0
            case 200: tag=(char *) "Custom Field 1"; break;
716
0
            case 201: tag=(char *) "Custom Field 2"; break;
717
0
            case 202: tag=(char *) "Custom Field 3"; break;
718
0
            case 203: tag=(char *) "Custom Field 4"; break;
719
0
            case 204: tag=(char *) "Custom Field 5"; break;
720
0
            case 205: tag=(char *) "Custom Field 6"; break;
721
0
            case 206: tag=(char *) "Custom Field 7"; break;
722
0
            case 207: tag=(char *) "Custom Field 8"; break;
723
0
            case 208: tag=(char *) "Custom Field 9"; break;
724
0
            case 209: tag=(char *) "Custom Field 10"; break;
725
0
            case 210: tag=(char *) "Custom Field 11"; break;
726
0
            case 211: tag=(char *) "Custom Field 12"; break;
727
0
            case 212: tag=(char *) "Custom Field 13"; break;
728
0
            case 213: tag=(char *) "Custom Field 14"; break;
729
0
            case 214: tag=(char *) "Custom Field 15"; break;
730
0
            case 215: tag=(char *) "Custom Field 16"; break;
731
0
            case 216: tag=(char *) "Custom Field 17"; break;
732
0
            case 217: tag=(char *) "Custom Field 18"; break;
733
0
            case 218: tag=(char *) "Custom Field 19"; break;
734
0
            case 219: tag=(char *) "Custom Field 20"; break;
735
0
            default: tag=(char *) "unknown"; break;
736
0
            }
737
0
          i++;
738
0
          (void) fprintf(file,"    %.1024s:\n",tag);
739
0
          length=(size_t) profile[i++] << 8;
740
0
          length|=(size_t) profile[i++];
741
0
          length=Min(length,profile_length-i);
742
0
          text=MagickAllocateMemory(char *,length+1);
743
0
          if (text != (char *) NULL)
744
0
            {
745
0
              char
746
0
                **textlist;
747
748
0
              register unsigned long
749
0
                j;
750
751
0
              (void) strncpy(text,(char *) profile+i,length);
752
0
              text[length]='\0';
753
0
              textlist=StringToList(text);
754
0
              if (textlist != (char **) NULL)
755
0
                {
756
0
                  for (j=0; textlist[j] != (char *) NULL; j++)
757
0
                    {
758
0
                      (void) fprintf(file,"  %s\n",textlist[j]);
759
0
                      MagickFreeMemory(textlist[j]);
760
0
                    }
761
0
                  MagickFreeMemory(textlist);
762
0
                }
763
0
              MagickFreeMemory(text);
764
0
            }
765
0
          i+=length;
766
0
        }
767
0
    }
768
0
  {
769
0
    const char
770
0
      *profile_name;
771
772
0
    size_t
773
0
      profile_length=0;
774
775
0
    const unsigned char *
776
0
      profile_info;
777
778
0
    ImageProfileIterator
779
0
      profile_iterator;
780
781
0
    profile_iterator=AllocateImageProfileIterator(image);
782
0
    while(NextImageProfile(profile_iterator,&profile_name,&profile_info,
783
0
                           &profile_length) != MagickFail)
784
0
      {
785
0
        if ((LocaleCompare(profile_name,"ICC") == 0) ||
786
0
            (LocaleCompare(profile_name,"ICM") == 0) ||
787
0
            (LocaleCompare(profile_name,"IPTC") == 0) ||
788
0
            (LocaleCompare(profile_name,"8BIM") == 0))
789
0
          continue;
790
791
0
        if (profile_length == 0)
792
0
          continue;
793
0
        (void) fprintf(file,"  Profile-%.1024s: %lu bytes\n",
794
0
                       profile_name == (char *) NULL ? "generic" : profile_name,
795
0
                       (unsigned long) profile_length);
796
0
        if (LocaleCompare(profile_name,"EXIF") == 0)
797
0
          {
798
0
            attribute=GetImageAttribute(image,"EXIF:*");
799
0
            if (attribute != (const ImageAttribute *) NULL)
800
0
              {
801
0
                char
802
0
                  **values;
803
804
0
                register char
805
0
                  *p;
806
807
0
                values=StringToList(attribute->value);
808
0
                if (values != (char **) NULL)
809
0
                  {
810
0
                    for (x=0; values[x] != (char *) NULL; x++)
811
0
                      {
812
0
                        (void) fprintf(file,"    ");
813
0
                        for (p=values[x]; *p != '\0'; p++)
814
0
                          {
815
0
                            if (p > values[x])
816
0
                              if ((isupper((int) ((unsigned char) *p))
817
0
                                   != MagickFalse) &&
818
0
                                  (islower((int) ((unsigned char) *(p+1)))
819
0
                                   != MagickFalse))
820
0
                                (void) fprintf(file," ");
821
0
                            if (*p == '=')
822
0
                              {
823
0
                                (void) fprintf(file,": ");
824
0
                                for (p++; *p != '\0'; p++)
825
0
                                  (void) fputc(*p,file);
826
0
                                break;
827
0
                              }
828
0
                            (void) fputc(*p,file);
829
0
                          }
830
0
                        (void) fputc('\n',file);
831
0
                        MagickFreeMemory(values[x]);
832
0
                      }
833
0
                    MagickFreeMemory(values);
834
0
                  }
835
0
              }
836
0
          } /* End of EXIF */
837
0
      }
838
0
    DeallocateImageProfileIterator(profile_iterator);
839
0
  }
840
0
  if (image->montage != (char *) NULL)
841
0
    (void) fprintf(file,"  Montage: %.1024s\n",image->montage);
842
0
  if (image->directory != (char *) NULL)
843
0
    {
844
0
      Image
845
0
        *tile;
846
847
0
      ImageInfo
848
0
        *image_info;
849
850
0
      register char
851
0
        *p,
852
0
        *q;
853
854
0
      WarningHandler
855
0
        handler;
856
857
      /*
858
        Display visual image directory.
859
      */
860
0
      image_info=CloneImageInfo((ImageInfo *) NULL);
861
0
      (void) CloneString(&image_info->size,"64x64");
862
0
      (void) fprintf(file,"  Directory:\n");
863
0
      for (p=image->directory; *p != '\0'; p++)
864
0
        {
865
0
          q=p;
866
0
          while ((*q != '\n') && (*q != '\0') &&
867
0
                 ((size_t) (q-p+1) < sizeof(image_info->filename)))
868
0
            q++;
869
0
          (void) strncpy(image_info->filename,p,q-p);
870
0
          image_info->filename[q-p]='\0';
871
0
          if (*q == '\0')
872
0
            break;
873
0
          p=q;
874
0
          (void) fprintf(file,"    %.1024s",image_info->filename);
875
0
          handler=SetWarningHandler((WarningHandler) NULL);
876
0
          tile=ReadImage(image_info,&image->exception);
877
0
          (void) SetWarningHandler(handler);
878
0
          if (tile == (Image *) NULL)
879
0
            {
880
0
              (void) fprintf(file,"\n");
881
0
              continue;
882
0
            }
883
0
          (void) fprintf(file," %lux%lu %.1024s\n",tile->magick_columns,
884
0
                         tile->magick_rows,tile->magick);
885
0
          (void) SignatureImage(tile);
886
0
          attribute=GetImageAttribute(tile,(char *) NULL);
887
0
          for ( ; attribute != (const ImageAttribute *) NULL;
888
0
                attribute=attribute->next)
889
0
            {
890
0
              if (*attribute->key == '[')
891
0
                continue;
892
0
              (void) fprintf(file,"  %.1024s:\n",attribute->key);
893
0
              (void) fprintf(file,"%s\n",attribute->value);
894
0
            }
895
0
          DestroyImage(tile);
896
0
        }
897
0
      DestroyImageInfo(image_info);
898
0
    }
899
0
  if (image->taint)
900
0
    (void) fprintf(file,"  Tainted: True\n");
901
0
  else
902
0
    (void) fprintf(file,"  Tainted: False\n");
903
  /*
904
    Only display time information if the time accumulated is at least
905
    the timer's resolution.
906
  */
907
0
  if (user_time >= GetTimerResolution())
908
0
    (void) fprintf(file,"  User Time: %0.3fu\n",user_time);
909
0
  if (!(image->ping) && (elapsed_time >= GetTimerResolution()))
910
0
    {
911
0
      (void) fprintf(file,"  Elapsed Time: %ldm:%.6fs\n",
912
0
                     (long) (elapsed_time/60.0),
913
0
                     fmod(elapsed_time,60.0));
914
0
      pixels_per_second=(magick_int64_t) ((double) image->rows*
915
0
                                          image->columns/
916
0
                                          (elapsed_time > GetTimerResolution() ?
917
0
                                           elapsed_time : GetTimerResolution()));
918
0
      FormatSize(pixels_per_second,format);
919
0
      (void) fprintf(file,"  Pixels Per Second: %s\n", format);
920
0
    }
921
0
  (void) fflush(file);
922
0
  return (ferror(file) ? MagickFail : MagickPass);
923
0
}