Coverage Report

Created: 2025-06-16 07:00

/src/imagemagick/MagickCore/image.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                     IIIII  M   M   AAA    GGGG  EEEEE                       %
7
%                       I    MM MM  A   A  G      E                           %
8
%                       I    M M M  AAAAA  G  GG  EEE                         %
9
%                       I    M   M  A   A  G   G  E                           %
10
%                     IIIII  M   M  A   A   GGGG  EEEEE                       %
11
%                                                                             %
12
%                                                                             %
13
%                           MagickCore Image Methods                          %
14
%                                                                             %
15
%                              Software Design                                %
16
%                                   Cristy                                    %
17
%                                 July 1992                                   %
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/animate.h"
45
#include "MagickCore/artifact.h"
46
#include "MagickCore/attribute.h"
47
#include "MagickCore/blob.h"
48
#include "MagickCore/blob-private.h"
49
#include "MagickCore/cache.h"
50
#include "MagickCore/cache-private.h"
51
#include "MagickCore/cache-view.h"
52
#include "MagickCore/channel.h"
53
#include "MagickCore/client.h"
54
#include "MagickCore/color.h"
55
#include "MagickCore/color-private.h"
56
#include "MagickCore/colormap.h"
57
#include "MagickCore/colorspace.h"
58
#include "MagickCore/colorspace-private.h"
59
#include "MagickCore/composite.h"
60
#include "MagickCore/composite-private.h"
61
#include "MagickCore/compress.h"
62
#include "MagickCore/constitute.h"
63
#include "MagickCore/delegate.h"
64
#include "MagickCore/display.h"
65
#include "MagickCore/draw.h"
66
#include "MagickCore/enhance.h"
67
#include "MagickCore/exception.h"
68
#include "MagickCore/exception-private.h"
69
#include "MagickCore/gem.h"
70
#include "MagickCore/geometry.h"
71
#include "MagickCore/histogram.h"
72
#include "MagickCore/image-private.h"
73
#include "MagickCore/list.h"
74
#include "MagickCore/magic.h"
75
#include "MagickCore/magick.h"
76
#include "MagickCore/magick-private.h"
77
#include "MagickCore/memory_.h"
78
#include "MagickCore/memory-private.h"
79
#include "MagickCore/module.h"
80
#include "MagickCore/monitor.h"
81
#include "MagickCore/monitor-private.h"
82
#include "MagickCore/option.h"
83
#include "MagickCore/paint.h"
84
#include "MagickCore/pixel-accessor.h"
85
#include "MagickCore/profile.h"
86
#include "MagickCore/property.h"
87
#include "MagickCore/quantize.h"
88
#include "MagickCore/random_.h"
89
#include "MagickCore/resource_.h"
90
#include "MagickCore/segment.h"
91
#include "MagickCore/semaphore.h"
92
#include "MagickCore/signature-private.h"
93
#include "MagickCore/statistic.h"
94
#include "MagickCore/string_.h"
95
#include "MagickCore/string-private.h"
96
#include "MagickCore/thread-private.h"
97
#include "MagickCore/threshold.h"
98
#include "MagickCore/timer.h"
99
#include "MagickCore/timer-private.h"
100
#include "MagickCore/token.h"
101
#include "MagickCore/token-private.h"
102
#include "MagickCore/utility.h"
103
#include "MagickCore/utility-private.h"
104
#include "MagickCore/version.h"
105
#include "MagickCore/xwindow-private.h"
106

107
/*
108
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109
%                                                                             %
110
%                                                                             %
111
%                                                                             %
112
%   A c q u i r e I m a g e                                                   %
113
%                                                                             %
114
%                                                                             %
115
%                                                                             %
116
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117
%
118
%  AcquireImage() returns a pointer to an image structure initialized to
119
%  default values.
120
%
121
%  The format of the AcquireImage method is:
122
%
123
%      Image *AcquireImage(const ImageInfo *image_info,ExceptionInfo *exception)
124
%
125
%  A description of each parameter follows:
126
%
127
%    o image_info: Many of the image default values are set from this
128
%      structure.  For example, filename, compression, depth, background color,
129
%      and others.
130
%
131
%    o exception: return any errors or warnings in this structure.
132
%
133
*/
134
MagickExport Image *AcquireImage(const ImageInfo *image_info,
135
  ExceptionInfo *exception)
136
3.52M
{
137
3.52M
  const char
138
3.52M
    *option;
139
140
3.52M
  Image
141
3.52M
    *image;
142
143
3.52M
  MagickSizeType
144
3.52M
    time_limit;
145
146
3.52M
  MagickStatusType
147
3.52M
    flags;
148
149
  /*
150
    Allocate image structure.
151
  */
152
3.52M
  if (IsEventLogging() != MagickFalse)
153
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
154
3.52M
  image=(Image *) AcquireCriticalMemory(sizeof(*image));
155
3.52M
  (void) memset(image,0,sizeof(*image));
156
  /*
157
    Initialize Image structure.
158
  */
159
3.52M
  (void) CopyMagickString(image->magick,"MIFF",MagickPathExtent);
160
3.52M
  image->storage_class=DirectClass;
161
3.52M
  image->depth=MAGICKCORE_QUANTUM_DEPTH;
162
3.52M
  image->colorspace=sRGBColorspace;
163
3.52M
  image->rendering_intent=PerceptualIntent;
164
3.52M
  image->gamma=1.000/2.200;
165
3.52M
  image->chromaticity.red_primary.x=0.6400;
166
3.52M
  image->chromaticity.red_primary.y=0.3300;
167
3.52M
  image->chromaticity.red_primary.z=0.0300;
168
3.52M
  image->chromaticity.green_primary.x=0.3000;
169
3.52M
  image->chromaticity.green_primary.y=0.6000;
170
3.52M
  image->chromaticity.green_primary.z=0.1000;
171
3.52M
  image->chromaticity.blue_primary.x=0.1500;
172
3.52M
  image->chromaticity.blue_primary.y=0.0600;
173
3.52M
  image->chromaticity.blue_primary.z=0.7900;
174
3.52M
  image->chromaticity.white_point.x=0.3127;
175
3.52M
  image->chromaticity.white_point.y=0.3290;
176
3.52M
  image->chromaticity.white_point.z=0.3583;
177
3.52M
  image->interlace=NoInterlace;
178
3.52M
  image->ticks_per_second=UndefinedTicksPerSecond;
179
3.52M
  image->compose=OverCompositeOp;
180
3.52M
  GetPixelInfoRGBA(BackgroundColorRGBA,&image->background_color);
181
3.52M
  GetPixelInfoRGBA(BorderColorRGBA,&image->border_color);
182
3.52M
  GetPixelInfoRGBA(MatteColorRGBA,&image->matte_color);
183
3.52M
  GetPixelInfoRGBA(TransparentColorRGBA,&image->transparent_color);
184
3.52M
  GetTimerInfo(&image->timer);
185
3.52M
  image->cache=AcquirePixelCache(0);
186
3.52M
  image->channel_mask=AllChannels;
187
3.52M
  image->channel_map=AcquirePixelChannelMap();
188
3.52M
  image->blob=CloneBlobInfo((BlobInfo *) NULL);
189
3.52M
  image->timestamp=GetMagickTime();
190
3.52M
  time_limit=GetMagickResourceLimit(TimeResource);
191
3.52M
  if (time_limit != MagickResourceInfinity)
192
0
    image->ttl=image->timestamp+(time_t) time_limit;
193
3.52M
  image->debug=(GetLogEventMask() & (ImageEvent | TransformEvent | CoderEvent))
194
3.52M
    != 0 ? MagickTrue : MagickFalse;
195
3.52M
  image->reference_count=1;
196
3.52M
  image->semaphore=AcquireSemaphoreInfo();
197
3.52M
  image->signature=MagickCoreSignature;
198
3.52M
  if (image_info == (ImageInfo *) NULL)
199
173k
    return(image);
200
  /*
201
    Transfer image info.
202
  */
203
3.35M
  SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue :
204
3.35M
    MagickFalse);
205
3.35M
  (void) CopyMagickString(image->filename,image_info->filename,
206
3.35M
    MagickPathExtent);
207
3.35M
  (void) CopyMagickString(image->magick_filename,image_info->filename,
208
3.35M
    MagickPathExtent);
209
3.35M
  (void) CopyMagickString(image->magick,image_info->magick,MagickPathExtent);
210
3.35M
  if (image_info->size != (char *) NULL)
211
25.9k
    {
212
25.9k
      (void) ParseAbsoluteGeometry(image_info->size,&image->extract_info);
213
25.9k
      image->columns=image->extract_info.width;
214
25.9k
      image->rows=image->extract_info.height;
215
25.9k
      image->offset=image->extract_info.x;
216
25.9k
      image->extract_info.x=0;
217
25.9k
      image->extract_info.y=0;
218
25.9k
    }
219
3.35M
  if (image_info->extract != (char *) NULL)
220
29.2k
    {
221
29.2k
      RectangleInfo
222
29.2k
        geometry;
223
224
29.2k
      (void) memset(&geometry,0,sizeof(geometry));
225
29.2k
      flags=ParseAbsoluteGeometry(image_info->extract,&geometry);
226
29.2k
      if (((flags & XValue) != 0) || ((flags & YValue) != 0))
227
13.6k
        {
228
13.6k
          image->extract_info=geometry;
229
13.6k
          Swap(image->columns,image->extract_info.width);
230
13.6k
          Swap(image->rows,image->extract_info.height);
231
13.6k
        }
232
29.2k
    }
233
3.35M
  image->compression=image_info->compression;
234
3.35M
  image->quality=image_info->quality;
235
3.35M
  image->endian=image_info->endian;
236
3.35M
  image->interlace=image_info->interlace;
237
3.35M
  image->units=image_info->units;
238
3.35M
  if (image_info->density != (char *) NULL)
239
12.4k
    {
240
12.4k
      GeometryInfo
241
12.4k
        geometry_info;
242
243
12.4k
      flags=ParseGeometry(image_info->density,&geometry_info);
244
12.4k
      if ((flags & RhoValue) != 0)
245
11.3k
        image->resolution.x=geometry_info.rho;
246
12.4k
      image->resolution.y=image->resolution.x;
247
12.4k
      if ((flags & SigmaValue) != 0)
248
0
        image->resolution.y=geometry_info.sigma;
249
12.4k
    }
250
3.35M
  if (image_info->page != (char *) NULL)
251
12.9k
    {
252
12.9k
      char
253
12.9k
        *geometry;
254
255
12.9k
      image->page=image->extract_info;
256
12.9k
      geometry=GetPageGeometry(image_info->page);
257
12.9k
      (void) ParseAbsoluteGeometry(geometry,&image->page);
258
12.9k
      geometry=DestroyString(geometry);
259
12.9k
    }
260
3.35M
  if (image_info->depth != 0)
261
0
    image->depth=image_info->depth;
262
3.35M
  image->dither=image_info->dither;
263
3.35M
  image->matte_color=image_info->matte_color;
264
3.35M
  image->background_color=image_info->background_color;
265
3.35M
  image->border_color=image_info->border_color;
266
3.35M
  image->transparent_color=image_info->transparent_color;
267
3.35M
  image->ping=image_info->ping;
268
3.35M
  image->progress_monitor=image_info->progress_monitor;
269
3.35M
  image->client_data=image_info->client_data;
270
3.35M
  if (image_info->cache != (void *) NULL)
271
70.6k
    ClonePixelCacheMethods(image->cache,image_info->cache);
272
  /*
273
    Set all global options that map to per-image settings.
274
  */
275
3.35M
  (void) SyncImageSettings(image_info,image,exception);
276
  /*
277
    Global options that are only set for new images.
278
  */
279
3.35M
  option=GetImageOption(image_info,"delay");
280
3.35M
  if (option != (const char *) NULL)
281
0
    {
282
0
      GeometryInfo
283
0
        geometry_info;
284
285
0
      flags=ParseGeometry(option,&geometry_info);
286
0
      if ((flags & GreaterValue) != 0)
287
0
        {
288
0
          if ((double) image->delay > floor(geometry_info.rho+0.5))
289
0
            image->delay=(size_t) CastDoubleToSsizeT(floor(geometry_info.rho+0.5));
290
0
        }
291
0
      else
292
0
        if ((flags & LessValue) != 0)
293
0
          {
294
0
            if ((double) image->delay < floor(geometry_info.rho+0.5))
295
0
              image->ticks_per_second=CastDoubleToSsizeT(floor(
296
0
                geometry_info.sigma+0.5));
297
0
          }
298
0
        else
299
0
          image->delay=(size_t) CastDoubleToSsizeT(floor(geometry_info.rho+0.5));
300
0
      if ((flags & SigmaValue) != 0)
301
0
        image->ticks_per_second=CastDoubleToSsizeT(floor(geometry_info.sigma+0.5));
302
0
    }
303
3.35M
  option=GetImageOption(image_info,"dispose");
304
3.35M
  if (option != (const char *) NULL)
305
0
    image->dispose=(DisposeType) ParseCommandOption(MagickDisposeOptions,
306
0
      MagickFalse,option);
307
3.35M
  return(image);
308
3.52M
}
309

310
/*
311
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312
%                                                                             %
313
%                                                                             %
314
%                                                                             %
315
%   A c q u i r e I m a g e I n f o                                           %
316
%                                                                             %
317
%                                                                             %
318
%                                                                             %
319
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
320
%
321
%  AcquireImageInfo() allocates the ImageInfo structure.
322
%
323
%  The format of the AcquireImageInfo method is:
324
%
325
%      ImageInfo *AcquireImageInfo(void)
326
%
327
*/
328
MagickExport ImageInfo *AcquireImageInfo(void)
329
9.77M
{
330
9.77M
  ImageInfo
331
9.77M
    *image_info;
332
333
9.77M
  image_info=(ImageInfo *) AcquireCriticalMemory(sizeof(*image_info));
334
9.77M
  GetImageInfo(image_info);
335
9.77M
  return(image_info);
336
9.77M
}
337

338
/*
339
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340
%                                                                             %
341
%                                                                             %
342
%                                                                             %
343
%   A c q u i r e N e x t I m a g e                                           %
344
%                                                                             %
345
%                                                                             %
346
%                                                                             %
347
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348
%
349
%  AcquireNextImage() initializes the next image in a sequence to
350
%  default values.  The next member of image points to the newly allocated
351
%  image.  If there is a memory shortage, next is assigned NULL.
352
%
353
%  The format of the AcquireNextImage method is:
354
%
355
%      void AcquireNextImage(const ImageInfo *image_info,Image *image,
356
%        ExceptionInfo *exception)
357
%
358
%  A description of each parameter follows:
359
%
360
%    o image_info: Many of the image default values are set from this
361
%      structure.  For example, filename, compression, depth, background color,
362
%      and others.
363
%
364
%    o image: the image.
365
%
366
%    o exception: return any errors or warnings in this structure.
367
%
368
*/
369
MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image,
370
  ExceptionInfo *exception)
371
105k
{
372
  /*
373
    Allocate image structure.
374
  */
375
105k
  assert(image != (Image *) NULL);
376
105k
  assert(image->signature == MagickCoreSignature);
377
105k
  if (IsEventLogging() != MagickFalse)
378
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
379
105k
  image->next=AcquireImage(image_info,exception);
380
105k
  if (GetNextImageInList(image) == (Image *) NULL)
381
0
    return;
382
105k
  (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename,
383
105k
    MagickPathExtent);
384
105k
  if (image_info != (ImageInfo *) NULL)
385
105k
    (void) CopyMagickString(GetNextImageInList(image)->filename,
386
105k
      image_info->filename,MagickPathExtent);
387
105k
  DestroyBlob(GetNextImageInList(image));
388
105k
  image->next->blob=ReferenceBlob(image->blob);
389
105k
  image->next->endian=image->endian;
390
105k
  image->next->scene=image->scene+1;
391
105k
  image->next->previous=image;
392
105k
}
393

394
/*
395
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396
%                                                                             %
397
%                                                                             %
398
%                                                                             %
399
%     A p p e n d I m a g e s                                                 %
400
%                                                                             %
401
%                                                                             %
402
%                                                                             %
403
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404
%
405
%  AppendImages() takes all images from the current image pointer to the end
406
%  of the image list and appends them to each other top-to-bottom if the
407
%  stack parameter is true, otherwise left-to-right.
408
%
409
%  The current gravity setting effects how the image is justified in the
410
%  final image.
411
%
412
%  The format of the AppendImages method is:
413
%
414
%      Image *AppendImages(const Image *images,const MagickBooleanType stack,
415
%        ExceptionInfo *exception)
416
%
417
%  A description of each parameter follows:
418
%
419
%    o images: the image sequence.
420
%
421
%    o stack: A value other than 0 stacks the images top-to-bottom.
422
%
423
%    o exception: return any errors or warnings in this structure.
424
%
425
*/
426
MagickExport Image *AppendImages(const Image *images,
427
  const MagickBooleanType stack,ExceptionInfo *exception)
428
0
{
429
0
#define AppendImageTag  "Append/Image"
430
431
0
  CacheView
432
0
    *append_view;
433
434
0
  Image
435
0
    *append_image;
436
437
0
  ImageType
438
0
    image_type;
439
440
0
  MagickBooleanType
441
0
    homogeneous_colorspace,
442
0
    status;
443
444
0
  MagickOffsetType
445
0
    n;
446
447
0
  PixelTrait
448
0
    alpha_trait;
449
450
0
  RectangleInfo
451
0
    geometry;
452
453
0
  const Image
454
0
    *next;
455
456
0
  size_t
457
0
    depth,
458
0
    height,
459
0
    number_images,
460
0
    width;
461
462
0
  ssize_t
463
0
    x_offset,
464
0
    y,
465
0
    y_offset;
466
467
  /*
468
    Compute maximum area of appended area.
469
  */
470
0
  assert(images != (Image *) NULL);
471
0
  assert(images->signature == MagickCoreSignature);
472
0
  assert(exception != (ExceptionInfo *) NULL);
473
0
  assert(exception->signature == MagickCoreSignature);
474
0
  if (IsEventLogging() != MagickFalse)
475
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
476
0
  alpha_trait=images->alpha_trait;
477
0
  number_images=1;
478
0
  width=images->columns;
479
0
  height=images->rows;
480
0
  depth=images->depth;
481
0
  image_type=images->type;
482
0
  homogeneous_colorspace=MagickTrue;
483
0
  next=GetNextImageInList(images);
484
0
  for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
485
0
  {
486
0
    if (next->depth > depth)
487
0
      depth=next->depth;
488
0
    if (next->type != images->type)
489
0
      image_type=UndefinedType;
490
0
    if (next->colorspace != images->colorspace)
491
0
      homogeneous_colorspace=MagickFalse;
492
0
    if (next->alpha_trait != UndefinedPixelTrait)
493
0
      alpha_trait=BlendPixelTrait;
494
0
    number_images++;
495
0
    if (stack != MagickFalse)
496
0
      {
497
0
        if (next->columns > width)
498
0
          width=next->columns;
499
0
        height+=next->rows;
500
0
        continue;
501
0
      }
502
0
    width+=next->columns;
503
0
    if (next->rows > height)
504
0
      height=next->rows;
505
0
  }
506
  /*
507
    Append images.
508
  */
509
0
  append_image=CloneImage(images,width,height,MagickTrue,exception);
510
0
  if (append_image == (Image *) NULL)
511
0
    return((Image *) NULL);
512
0
  if (image_type != BilevelType)
513
0
    {
514
0
      if (SetImageStorageClass(append_image,DirectClass,exception) == MagickFalse)
515
0
        {
516
0
          append_image=DestroyImage(append_image);
517
0
          return((Image *) NULL);
518
0
        }
519
0
      if (homogeneous_colorspace == MagickFalse)
520
0
        (void) SetImageColorspace(append_image,sRGBColorspace,exception);
521
0
    }
522
0
  append_image->depth=depth;
523
0
  append_image->alpha_trait=alpha_trait;
524
0
  append_image->page=images->page;
525
0
  (void) SetImageBackgroundColor(append_image,exception);
526
0
  status=MagickTrue;
527
0
  x_offset=0;
528
0
  y_offset=0;
529
0
  next=images;
530
0
  append_view=AcquireAuthenticCacheView(append_image,exception);
531
0
  for (n=0; n < (MagickOffsetType) number_images; n++)
532
0
  {
533
0
    CacheView
534
0
      *image_view;
535
536
0
    MagickBooleanType
537
0
      proceed;
538
539
0
    SetGeometry(append_image,&geometry);
540
0
    GravityAdjustGeometry(next->columns,next->rows,next->gravity,&geometry);
541
0
    if (stack != MagickFalse)
542
0
      x_offset-=geometry.x;
543
0
    else
544
0
      y_offset-=geometry.y;
545
0
    image_view=AcquireVirtualCacheView(next,exception);
546
#if defined(MAGICKCORE_OPENMP_SUPPORT)
547
    #pragma omp parallel for schedule(static) shared(status) \
548
      magick_number_threads(next,next,next->rows,2)
549
#endif
550
0
    for (y=0; y < (ssize_t) next->rows; y++)
551
0
    {
552
0
      MagickBooleanType
553
0
        sync;
554
555
0
      PixelInfo
556
0
        pixel;
557
558
0
      const Quantum
559
0
        *magick_restrict p;
560
561
0
      Quantum
562
0
        *magick_restrict q;
563
564
0
      ssize_t
565
0
        x;
566
567
0
      if (status == MagickFalse)
568
0
        continue;
569
0
      p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
570
0
      q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset,
571
0
        next->columns,1,exception);
572
0
      if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
573
0
        {
574
0
          status=MagickFalse;
575
0
          continue;
576
0
        }
577
0
      GetPixelInfo(next,&pixel);
578
0
      for (x=0; x < (ssize_t) next->columns; x++)
579
0
      {
580
0
        GetPixelInfoPixel(next,p,&pixel);
581
0
        SetPixelViaPixelInfo(append_image,&pixel,q);
582
0
        p+=(ptrdiff_t) GetPixelChannels(next);
583
0
        q+=(ptrdiff_t) GetPixelChannels(append_image);
584
0
      }
585
0
      sync=SyncCacheViewAuthenticPixels(append_view,exception);
586
0
      if (sync == MagickFalse)
587
0
        status=MagickFalse;
588
0
    }
589
0
    image_view=DestroyCacheView(image_view);
590
0
    if (stack == MagickFalse)
591
0
      {
592
0
        x_offset+=(ssize_t) next->columns;
593
0
        y_offset=0;
594
0
      }
595
0
    else
596
0
      {
597
0
        x_offset=0;
598
0
        y_offset+=(ssize_t) next->rows;
599
0
      }
600
0
    proceed=SetImageProgress(append_image,AppendImageTag,n,number_images);
601
0
    if (proceed == MagickFalse)
602
0
      break;
603
0
    next=GetNextImageInList(next);
604
0
  }
605
0
  append_view=DestroyCacheView(append_view);
606
0
  if (status == MagickFalse)
607
0
    append_image=DestroyImage(append_image);
608
0
  return(append_image);
609
0
}
610

611
/*
612
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613
%                                                                             %
614
%                                                                             %
615
%                                                                             %
616
%   C a t c h I m a g e E x c e p t i o n                                     %
617
%                                                                             %
618
%                                                                             %
619
%                                                                             %
620
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621
%
622
%  CatchImageException() returns if no exceptions are found in the image
623
%  sequence, otherwise it determines the most severe exception and reports
624
%  it as a warning or error depending on the severity.
625
%
626
%  The format of the CatchImageException method is:
627
%
628
%      ExceptionType CatchImageException(Image *image)
629
%
630
%  A description of each parameter follows:
631
%
632
%    o image: An image sequence.
633
%
634
*/
635
MagickExport ExceptionType CatchImageException(Image *image)
636
437
{
637
437
  ExceptionInfo
638
437
    *exception;
639
640
437
  ExceptionType
641
437
    severity;
642
643
437
  assert(image != (const Image *) NULL);
644
437
  assert(image->signature == MagickCoreSignature);
645
437
  if (IsEventLogging() != MagickFalse)
646
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
647
437
  exception=AcquireExceptionInfo();
648
437
  CatchException(exception);
649
437
  severity=exception->severity;
650
437
  exception=DestroyExceptionInfo(exception);
651
437
  return(severity);
652
437
}
653

654
/*
655
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656
%                                                                             %
657
%                                                                             %
658
%                                                                             %
659
%   C l i p I m a g e P a t h                                                 %
660
%                                                                             %
661
%                                                                             %
662
%                                                                             %
663
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664
%
665
%  ClipImagePath() sets the image clip mask based any clipping path information
666
%  if it exists.
667
%
668
%  The format of the ClipImagePath method is:
669
%
670
%      MagickBooleanType ClipImagePath(Image *image,const char *pathname,
671
%        const MagickBooleanType inside,ExceptionInfo *exception)
672
%
673
%  A description of each parameter follows:
674
%
675
%    o image: the image.
676
%
677
%    o pathname: name of clipping path resource. If name is preceded by #, use
678
%      clipping path numbered by name.
679
%
680
%    o inside: if non-zero, later operations take effect inside clipping path.
681
%      Otherwise later operations take effect outside clipping path.
682
%
683
%    o exception: return any errors or warnings in this structure.
684
%
685
*/
686
687
MagickExport MagickBooleanType ClipImage(Image *image,ExceptionInfo *exception)
688
0
{
689
0
  return(ClipImagePath(image,"#1",MagickTrue,exception));
690
0
}
691
692
MagickExport MagickBooleanType ClipImagePath(Image *image,const char *pathname,
693
  const MagickBooleanType inside,ExceptionInfo *exception)
694
0
{
695
0
#define ClipImagePathTag  "ClipPath/Image"
696
697
0
  char
698
0
    *property;
699
700
0
  const char
701
0
    *value;
702
703
0
  Image
704
0
    *clip_mask;
705
706
0
  ImageInfo
707
0
    *image_info;
708
709
0
  assert(image != (const Image *) NULL);
710
0
  assert(image->signature == MagickCoreSignature);
711
0
  assert(pathname != NULL);
712
0
  if (IsEventLogging() != MagickFalse)
713
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
714
0
  property=AcquireString(pathname);
715
0
  (void) FormatLocaleString(property,MagickPathExtent,"8BIM:1999,2998:%s",
716
0
    pathname);
717
0
  value=GetImageProperty(image,property,exception);
718
0
  property=DestroyString(property);
719
0
  if (value == (const char *) NULL)
720
0
    {
721
0
      ThrowFileException(exception,OptionError,"NoClipPathDefined",
722
0
        image->filename);
723
0
      return(MagickFalse);
724
0
    }
725
0
  image_info=AcquireImageInfo();
726
0
  (void) CopyMagickString(image_info->filename,image->filename,
727
0
     MagickPathExtent);
728
0
  (void) ConcatenateMagickString(image_info->filename,pathname,
729
0
    MagickPathExtent);
730
0
  clip_mask=BlobToImage(image_info,value,strlen(value),exception);
731
0
  image_info=DestroyImageInfo(image_info);
732
0
  if (clip_mask == (Image *) NULL)
733
0
    return(MagickFalse);
734
0
  if (clip_mask->storage_class == PseudoClass)
735
0
    {
736
0
      (void) SyncImage(clip_mask,exception);
737
0
      if (SetImageStorageClass(clip_mask,DirectClass,exception) == MagickFalse)
738
0
        return(MagickFalse);
739
0
    }
740
0
  if (inside != MagickFalse)
741
0
    (void) NegateImage(clip_mask,MagickFalse,exception);
742
0
  (void) FormatLocaleString(clip_mask->magick_filename,MagickPathExtent,
743
0
    "8BIM:1999,2998:%s\nPS",pathname);
744
0
  (void) SetImageMask(image,WritePixelMask,clip_mask,exception);
745
0
  image->mask_trait=UpdatePixelTrait;
746
0
  clip_mask=DestroyImage(clip_mask);
747
0
  return(MagickTrue);
748
0
}
749

750
/*
751
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752
%                                                                             %
753
%                                                                             %
754
%                                                                             %
755
%   C l o n e I m a g e                                                       %
756
%                                                                             %
757
%                                                                             %
758
%                                                                             %
759
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760
%
761
%  CloneImage() copies an image and returns the copy as a new image object.
762
%
763
%  If the specified columns and rows is 0, an exact copy of the image is
764
%  returned, otherwise the pixel data is undefined and must be initialized
765
%  with the QueueAuthenticPixels() and SyncAuthenticPixels() methods.  On
766
%  failure, a NULL image is returned and exception describes the reason for the
767
%  failure.
768
%
769
%  The format of the CloneImage method is:
770
%
771
%      Image *CloneImage(const Image *image,const size_t columns,
772
%        const size_t rows,const MagickBooleanType orphan,
773
%        ExceptionInfo *exception)
774
%
775
%  A description of each parameter follows:
776
%
777
%    o image: the image.
778
%
779
%    o columns: the number of columns in the cloned image.
780
%
781
%    o rows: the number of rows in the cloned image.
782
%
783
%    o detach:  With a value other than 0, the cloned image is detached from
784
%      its parent I/O stream.
785
%
786
%    o exception: return any errors or warnings in this structure.
787
%
788
*/
789
MagickExport Image *CloneImage(const Image *image,const size_t columns,
790
  const size_t rows,const MagickBooleanType detach,ExceptionInfo *exception)
791
594k
{
792
594k
  double
793
594k
    scale_x,
794
594k
    scale_y;
795
796
594k
  Image
797
594k
    *clone_image;
798
799
594k
  size_t
800
594k
    length;
801
802
  /*
803
    Clone the image.
804
  */
805
594k
  assert(image != (const Image *) NULL);
806
594k
  assert(image->signature == MagickCoreSignature);
807
594k
  assert(exception != (ExceptionInfo *) NULL);
808
594k
  assert(exception->signature == MagickCoreSignature);
809
594k
  if (IsEventLogging() != MagickFalse)
810
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
811
594k
  if ((image->columns == 0) || (image->rows == 0))
812
834
    {
813
834
      (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
814
834
        "NegativeOrZeroImageSize","`%s'",image->filename);
815
834
      return((Image *) NULL);
816
834
    }
817
593k
  clone_image=(Image *) AcquireCriticalMemory(sizeof(*clone_image));
818
593k
  (void) memset(clone_image,0,sizeof(*clone_image));
819
593k
  clone_image->signature=MagickCoreSignature;
820
593k
  clone_image->storage_class=image->storage_class;
821
593k
  clone_image->number_channels=image->number_channels;
822
593k
  clone_image->number_meta_channels=image->number_meta_channels;
823
593k
  clone_image->metacontent_extent=image->metacontent_extent;
824
593k
  clone_image->colorspace=image->colorspace;
825
593k
  clone_image->alpha_trait=image->alpha_trait;
826
593k
  clone_image->channels=image->channels;
827
593k
  clone_image->mask_trait=image->mask_trait;
828
593k
  clone_image->columns=image->columns;
829
593k
  clone_image->rows=image->rows;
830
593k
  clone_image->dither=image->dither;
831
593k
  clone_image->image_info=CloneImageInfo(image->image_info);
832
593k
  (void) CloneImageProfiles(clone_image,image);
833
593k
  (void) CloneImageProperties(clone_image,image);
834
593k
  (void) CloneImageArtifacts(clone_image,image);
835
593k
  GetTimerInfo(&clone_image->timer);
836
593k
  if (image->ascii85 != (void *) NULL)
837
0
    Ascii85Initialize(clone_image);
838
593k
  clone_image->extent=image->extent;
839
593k
  clone_image->magick_columns=image->magick_columns;
840
593k
  clone_image->magick_rows=image->magick_rows;
841
593k
  clone_image->type=image->type;
842
593k
  clone_image->channel_mask=image->channel_mask;
843
593k
  clone_image->channel_map=ClonePixelChannelMap(image->channel_map);
844
593k
  (void) CopyMagickString(clone_image->magick_filename,image->magick_filename,
845
593k
    MagickPathExtent);
846
593k
  (void) CopyMagickString(clone_image->magick,image->magick,MagickPathExtent);
847
593k
  (void) CopyMagickString(clone_image->filename,image->filename,
848
593k
    MagickPathExtent);
849
593k
  clone_image->progress_monitor=image->progress_monitor;
850
593k
  clone_image->client_data=image->client_data;
851
593k
  clone_image->reference_count=1;
852
593k
  clone_image->next=image->next;
853
593k
  clone_image->previous=image->previous;
854
593k
  clone_image->list=NewImageList();
855
593k
  if (detach == MagickFalse)
856
5.53k
    clone_image->blob=ReferenceBlob(image->blob);
857
588k
  else
858
588k
    {
859
588k
      clone_image->next=NewImageList();
860
588k
      clone_image->previous=NewImageList();
861
588k
      clone_image->blob=CloneBlobInfo((BlobInfo *) NULL);
862
588k
    }
863
593k
  clone_image->ping=image->ping;
864
593k
  clone_image->timestamp=image->timestamp;
865
593k
  clone_image->ttl=image->ttl;
866
593k
  clone_image->debug=image->debug;
867
593k
  clone_image->semaphore=AcquireSemaphoreInfo();
868
593k
  if (image->colormap != (PixelInfo *) NULL)
869
26.5k
    {
870
      /*
871
        Allocate and copy the image colormap.
872
      */
873
26.5k
      clone_image->colors=image->colors;
874
26.5k
      length=(size_t) image->colors;
875
26.5k
      clone_image->colormap=(PixelInfo *) AcquireQuantumMemory(length+1,
876
26.5k
        sizeof(*clone_image->colormap));
877
26.5k
      if (clone_image->colormap == (PixelInfo *) NULL)
878
0
        {
879
0
          clone_image=DestroyImage(clone_image);
880
0
          ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
881
0
        }
882
26.5k
      (void) memcpy(clone_image->colormap,image->colormap,length*
883
26.5k
        sizeof(*clone_image->colormap));
884
26.5k
    }
885
593k
  if ((columns == 0) || (rows == 0))
886
532k
    {
887
532k
      if (image->montage != (char *) NULL)
888
0
        (void) CloneString(&clone_image->montage,image->montage);
889
532k
      if (image->directory != (char *) NULL)
890
0
        (void) CloneString(&clone_image->directory,image->directory);
891
532k
      clone_image->cache=ReferencePixelCache(image->cache);
892
532k
      return(clone_image);
893
532k
    }
894
61.6k
  scale_x=1.0;
895
61.6k
  scale_y=1.0;
896
61.6k
  if (image->columns != 0)
897
61.6k
    scale_x=(double) columns/(double) image->columns;
898
61.6k
  if (image->rows != 0)
899
61.6k
    scale_y=(double) rows/(double) image->rows;
900
61.6k
  clone_image->page.width=(size_t) CastDoubleToSsizeT(floor(scale_x*
901
61.6k
    image->page.width+0.5));
902
61.6k
  clone_image->page.height=(size_t) CastDoubleToSsizeT(floor(scale_y*
903
61.6k
    image->page.height+0.5));
904
61.6k
  if (MagickAbsoluteValue(scale_x-scale_y) < 2.0)
905
46.1k
    scale_x=scale_y=MagickMin(scale_x,scale_y);
906
61.6k
  clone_image->page.x=CastDoubleToSsizeT(ceil(scale_x*image->page.x-0.5));
907
61.6k
  clone_image->tile_offset.x=CastDoubleToSsizeT(ceil(scale_x*
908
61.6k
    image->tile_offset.x-0.5));
909
61.6k
  clone_image->page.y=CastDoubleToSsizeT(ceil(scale_y*image->page.y-0.5));
910
61.6k
  clone_image->tile_offset.y=CastDoubleToSsizeT(ceil(scale_y*
911
61.6k
    image->tile_offset.y-0.5));
912
61.6k
  clone_image->cache=ClonePixelCache(image->cache);
913
61.6k
  if (SetImageExtent(clone_image,columns,rows,exception) == MagickFalse)
914
6.09k
    clone_image=DestroyImage(clone_image);
915
61.6k
  return(clone_image);
916
593k
}
917

918
/*
919
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
920
%                                                                             %
921
%                                                                             %
922
%                                                                             %
923
%   C l o n e I m a g e I n f o                                               %
924
%                                                                             %
925
%                                                                             %
926
%                                                                             %
927
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
928
%
929
%  CloneImageInfo() makes a copy of the given image info structure.  If
930
%  NULL is specified, a new image info structure is created initialized to
931
%  default values.
932
%
933
%  The format of the CloneImageInfo method is:
934
%
935
%      ImageInfo *CloneImageInfo(const ImageInfo *image_info)
936
%
937
%  A description of each parameter follows:
938
%
939
%    o image_info: the image info.
940
%
941
*/
942
MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info)
943
9.59M
{
944
9.59M
  ImageInfo
945
9.59M
    *clone_info;
946
947
9.59M
  clone_info=AcquireImageInfo();
948
9.59M
  if (image_info == (ImageInfo *) NULL)
949
2.42M
    return(clone_info);
950
7.17M
  clone_info->compression=image_info->compression;
951
7.17M
  clone_info->temporary=image_info->temporary;
952
7.17M
  clone_info->adjoin=image_info->adjoin;
953
7.17M
  clone_info->antialias=image_info->antialias;
954
7.17M
  clone_info->scene=image_info->scene;
955
7.17M
  clone_info->number_scenes=image_info->number_scenes;
956
7.17M
  clone_info->depth=image_info->depth;
957
7.17M
  if (image_info->size != (char *) NULL)
958
267k
    (void) CloneString(&clone_info->size,image_info->size);
959
7.17M
  if (image_info->extract != (char *) NULL)
960
70.4k
    (void) CloneString(&clone_info->extract,image_info->extract);
961
7.17M
  if (image_info->scenes != (char *) NULL)
962
26.1k
    (void) CloneString(&clone_info->scenes,image_info->scenes);
963
7.17M
  if (image_info->page != (char *) NULL)
964
25.9k
    (void) CloneString(&clone_info->page,image_info->page);
965
7.17M
  clone_info->interlace=image_info->interlace;
966
7.17M
  clone_info->endian=image_info->endian;
967
7.17M
  clone_info->units=image_info->units;
968
7.17M
  clone_info->quality=image_info->quality;
969
7.17M
  if (image_info->sampling_factor != (char *) NULL)
970
0
    (void) CloneString(&clone_info->sampling_factor,
971
0
      image_info->sampling_factor);
972
7.17M
  if (image_info->server_name != (char *) NULL)
973
0
    (void) CloneString(&clone_info->server_name,image_info->server_name);
974
7.17M
  if (image_info->font != (char *) NULL)
975
0
    (void) CloneString(&clone_info->font,image_info->font);
976
7.17M
  if (image_info->texture != (char *) NULL)
977
0
    (void) CloneString(&clone_info->texture,image_info->texture);
978
7.17M
  if (image_info->density != (char *) NULL)
979
19.2k
    (void) CloneString(&clone_info->density,image_info->density);
980
7.17M
  clone_info->pointsize=image_info->pointsize;
981
7.17M
  clone_info->fuzz=image_info->fuzz;
982
7.17M
  clone_info->matte_color=image_info->matte_color;
983
7.17M
  clone_info->background_color=image_info->background_color;
984
7.17M
  clone_info->border_color=image_info->border_color;
985
7.17M
  clone_info->transparent_color=image_info->transparent_color;
986
7.17M
  clone_info->dither=image_info->dither;
987
7.17M
  clone_info->monochrome=image_info->monochrome;
988
7.17M
  clone_info->colorspace=image_info->colorspace;
989
7.17M
  clone_info->type=image_info->type;
990
7.17M
  clone_info->orientation=image_info->orientation;
991
7.17M
  clone_info->ping=image_info->ping;
992
7.17M
  clone_info->verbose=image_info->verbose;
993
7.17M
  clone_info->progress_monitor=image_info->progress_monitor;
994
7.17M
  clone_info->client_data=image_info->client_data;
995
7.17M
  clone_info->cache=image_info->cache;
996
7.17M
  if (image_info->cache != (void *) NULL)
997
116k
    clone_info->cache=ReferencePixelCache(image_info->cache);
998
7.17M
  if (image_info->profile != (void *) NULL)
999
0
    clone_info->profile=(void *) CloneStringInfo((StringInfo *)
1000
0
      image_info->profile);
1001
7.17M
  SetImageInfoFile(clone_info,image_info->file);
1002
7.17M
  SetImageInfoBlob(clone_info,image_info->blob,image_info->length);
1003
7.17M
  clone_info->stream=image_info->stream;
1004
7.17M
  clone_info->custom_stream=image_info->custom_stream;
1005
7.17M
  (void) CopyMagickString(clone_info->magick,image_info->magick,
1006
7.17M
    MagickPathExtent);
1007
7.17M
  (void) CopyMagickString(clone_info->unique,image_info->unique,
1008
7.17M
    MagickPathExtent);
1009
7.17M
  (void) CopyMagickString(clone_info->filename,image_info->filename,
1010
7.17M
    MagickPathExtent);
1011
7.17M
  clone_info->channel=image_info->channel;
1012
7.17M
  (void) CloneImageOptions(clone_info,image_info);
1013
7.17M
  clone_info->debug=image_info->debug;
1014
7.17M
  clone_info->signature=image_info->signature;
1015
7.17M
  return(clone_info);
1016
9.59M
}
1017

1018
/*
1019
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1020
%                                                                             %
1021
%                                                                             %
1022
%                                                                             %
1023
%   C o p y I m a g e P i x e l s                                             %
1024
%                                                                             %
1025
%                                                                             %
1026
%                                                                             %
1027
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1028
%
1029
%  CopyImagePixels() copies pixels from the source image as defined by the
1030
%  geometry the destination image at the specified offset.
1031
%
1032
%  The format of the CopyImagePixels method is:
1033
%
1034
%      MagickBooleanType CopyImagePixels(Image *image,const Image *source_image,
1035
%        const RectangleInfo *geometry,const OffsetInfo *offset,
1036
%        ExceptionInfo *exception);
1037
%
1038
%  A description of each parameter follows:
1039
%
1040
%    o image: the destination image.
1041
%
1042
%    o source_image: the source image.
1043
%
1044
%    o geometry: define the dimensions of the source pixel rectangle.
1045
%
1046
%    o offset: define the offset in the destination image.
1047
%
1048
%    o exception: return any errors or warnings in this structure.
1049
%
1050
*/
1051
MagickExport MagickBooleanType CopyImagePixels(Image *image,
1052
  const Image *source_image,const RectangleInfo *geometry,
1053
  const OffsetInfo *offset,ExceptionInfo *exception)
1054
0
{
1055
0
#define CopyImageTag  "Copy/Image"
1056
1057
0
  CacheView
1058
0
    *image_view,
1059
0
    *source_view;
1060
1061
0
  MagickBooleanType
1062
0
    status;
1063
1064
0
  MagickOffsetType
1065
0
    progress;
1066
1067
0
  ssize_t
1068
0
    y;
1069
1070
0
  assert(image != (Image *) NULL);
1071
0
  assert(source_image != (Image *) NULL);
1072
0
  assert(geometry != (RectangleInfo *) NULL);
1073
0
  assert(offset != (OffsetInfo *) NULL);
1074
0
  if (IsEventLogging() != MagickFalse)
1075
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1076
0
  if ((offset->x < 0) || (offset->y < 0) ||
1077
0
      ((offset->x+(ssize_t) geometry->width) > (ssize_t) image->columns) ||
1078
0
      ((offset->y+(ssize_t) geometry->height) > (ssize_t) image->rows))
1079
0
    ThrowBinaryException(OptionError,"GeometryDoesNotContainImage",
1080
0
      image->filename);
1081
0
  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1082
0
    return(MagickFalse);
1083
  /*
1084
    Copy image pixels.
1085
  */
1086
0
  status=MagickTrue;
1087
0
  progress=0;
1088
0
  source_view=AcquireVirtualCacheView(source_image,exception);
1089
0
  image_view=AcquireAuthenticCacheView(image,exception);
1090
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1091
  #pragma omp parallel for schedule(static) shared(progress,status) \
1092
    magick_number_threads(image,source_image,geometry->height,2)
1093
#endif
1094
0
  for (y=0; y < (ssize_t) geometry->height; y++)
1095
0
  {
1096
0
    MagickBooleanType
1097
0
      sync;
1098
1099
0
    const Quantum
1100
0
      *magick_restrict p;
1101
1102
0
    ssize_t
1103
0
      x;
1104
1105
0
    Quantum
1106
0
      *magick_restrict q;
1107
1108
0
    if (status == MagickFalse)
1109
0
      continue;
1110
0
    p=GetCacheViewVirtualPixels(source_view,geometry->x,y+geometry->y,
1111
0
      geometry->width,1,exception);
1112
0
    q=QueueCacheViewAuthenticPixels(image_view,offset->x,y+offset->y,
1113
0
      geometry->width,1,exception);
1114
0
    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1115
0
      {
1116
0
        status=MagickFalse;
1117
0
        continue;
1118
0
      }
1119
0
    for (x=0; x < (ssize_t) geometry->width; x++)
1120
0
    {
1121
0
      ssize_t
1122
0
        i;
1123
1124
0
      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1125
0
      {
1126
0
        PixelChannel channel = GetPixelChannelChannel(image,i);
1127
0
        PixelTrait traits = GetPixelChannelTraits(image,channel);
1128
0
        PixelTrait source_traits=GetPixelChannelTraits(source_image,channel);
1129
0
        if ((traits == UndefinedPixelTrait) ||
1130
0
            ((traits & UpdatePixelTrait) == 0) ||
1131
0
            (source_traits == UndefinedPixelTrait))
1132
0
          continue;
1133
0
        SetPixelChannel(image,channel,p[i],q);
1134
0
      }
1135
0
      p+=(ptrdiff_t) GetPixelChannels(source_image);
1136
0
      q+=(ptrdiff_t) GetPixelChannels(image);
1137
0
    }
1138
0
    sync=SyncCacheViewAuthenticPixels(image_view,exception);
1139
0
    if (sync == MagickFalse)
1140
0
      status=MagickFalse;
1141
0
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
1142
0
      {
1143
0
        MagickBooleanType
1144
0
          proceed;
1145
1146
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1147
        #pragma omp atomic
1148
#endif
1149
0
        progress++;
1150
0
        proceed=SetImageProgress(image,CopyImageTag,progress,image->rows);
1151
0
        if (proceed == MagickFalse)
1152
0
          status=MagickFalse;
1153
0
      }
1154
0
  }
1155
0
  source_view=DestroyCacheView(source_view);
1156
0
  image_view=DestroyCacheView(image_view);
1157
0
  return(status);
1158
0
}
1159

1160
/*
1161
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1162
%                                                                             %
1163
%                                                                             %
1164
%                                                                             %
1165
%   D e s t r o y I m a g e                                                   %
1166
%                                                                             %
1167
%                                                                             %
1168
%                                                                             %
1169
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1170
%
1171
%  DestroyImage() dereferences an image, deallocating memory associated with
1172
%  the image if the reference count becomes zero.
1173
%
1174
%  The format of the DestroyImage method is:
1175
%
1176
%      Image *DestroyImage(Image *image)
1177
%
1178
%  A description of each parameter follows:
1179
%
1180
%    o image: the image.
1181
%
1182
*/
1183
MagickExport Image *DestroyImage(Image *image)
1184
8.00M
{
1185
8.00M
  MagickBooleanType
1186
8.00M
    destroy;
1187
1188
  /*
1189
    Dereference image.
1190
  */
1191
8.00M
  assert(image != (Image *) NULL);
1192
8.00M
  assert(image->signature == MagickCoreSignature);
1193
8.00M
  if (IsEventLogging() != MagickFalse)
1194
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1195
8.00M
  destroy=MagickFalse;
1196
8.00M
  LockSemaphoreInfo(image->semaphore);
1197
8.00M
  image->reference_count--;
1198
8.00M
  if (image->reference_count == 0)
1199
4.11M
    destroy=MagickTrue;
1200
8.00M
  UnlockSemaphoreInfo(image->semaphore);
1201
8.00M
  if (destroy == MagickFalse)
1202
3.88M
    return((Image *) NULL);
1203
  /*
1204
    Destroy image.
1205
  */
1206
4.11M
  DestroyImagePixels(image);
1207
4.11M
  image->channel_map=DestroyPixelChannelMap(image->channel_map);
1208
4.11M
  if (image->montage != (char *) NULL)
1209
191
    image->montage=DestroyString(image->montage);
1210
4.11M
  if (image->directory != (char *) NULL)
1211
94
    image->directory=DestroyString(image->directory);
1212
4.11M
  if (image->colormap != (PixelInfo *) NULL)
1213
168k
    image->colormap=(PixelInfo *) RelinquishMagickMemory(image->colormap);
1214
4.11M
  if (image->geometry != (char *) NULL)
1215
0
    image->geometry=DestroyString(image->geometry);
1216
4.11M
  DestroyImageProfiles(image);
1217
4.11M
  DestroyImageProperties(image);
1218
4.11M
  DestroyImageArtifacts(image);
1219
4.11M
  if (image->ascii85 != (Ascii85Info *) NULL)
1220
0
    image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85);
1221
4.11M
  if (image->image_info != (ImageInfo *) NULL)
1222
3.94M
    image->image_info=DestroyImageInfo(image->image_info);
1223
4.11M
  DestroyBlob(image);
1224
4.11M
  if (image->semaphore != (SemaphoreInfo *) NULL)
1225
4.11M
    RelinquishSemaphoreInfo(&image->semaphore);
1226
4.11M
  image->signature=(~MagickCoreSignature);
1227
4.11M
  image=(Image *) RelinquishMagickMemory(image);
1228
4.11M
  return(image);
1229
8.00M
}
1230

1231
/*
1232
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233
%                                                                             %
1234
%                                                                             %
1235
%                                                                             %
1236
%   D e s t r o y I m a g e I n f o                                           %
1237
%                                                                             %
1238
%                                                                             %
1239
%                                                                             %
1240
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1241
%
1242
%  DestroyImageInfo() deallocates memory associated with an ImageInfo
1243
%  structure.
1244
%
1245
%  The format of the DestroyImageInfo method is:
1246
%
1247
%      ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1248
%
1249
%  A description of each parameter follows:
1250
%
1251
%    o image_info: the image info.
1252
%
1253
*/
1254
MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1255
10.5M
{
1256
10.5M
  assert(image_info != (ImageInfo *) NULL);
1257
10.5M
  assert(image_info->signature == MagickCoreSignature);
1258
10.5M
  if (IsEventLogging() != MagickFalse)
1259
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1260
0
      image_info->filename);
1261
10.5M
  if (image_info->size != (char *) NULL)
1262
286k
    image_info->size=DestroyString(image_info->size);
1263
10.5M
  if (image_info->extract != (char *) NULL)
1264
88.4k
    image_info->extract=DestroyString(image_info->extract);
1265
10.5M
  if (image_info->scenes != (char *) NULL)
1266
29.4k
    image_info->scenes=DestroyString(image_info->scenes);
1267
10.5M
  if (image_info->page != (char *) NULL)
1268
32.4k
    image_info->page=DestroyString(image_info->page);
1269
10.5M
  if (image_info->sampling_factor != (char *) NULL)
1270
0
    image_info->sampling_factor=DestroyString(
1271
0
      image_info->sampling_factor);
1272
10.5M
  if (image_info->server_name != (char *) NULL)
1273
0
    image_info->server_name=DestroyString(
1274
0
      image_info->server_name);
1275
10.5M
  if (image_info->font != (char *) NULL)
1276
0
    image_info->font=DestroyString(image_info->font);
1277
10.5M
  if (image_info->texture != (char *) NULL)
1278
0
    image_info->texture=DestroyString(image_info->texture);
1279
10.5M
  if (image_info->density != (char *) NULL)
1280
25.4k
    image_info->density=DestroyString(image_info->density);
1281
10.5M
  if (image_info->cache != (void *) NULL)
1282
154k
    image_info->cache=DestroyPixelCache(image_info->cache);
1283
10.5M
  if (image_info->profile != (StringInfo *) NULL)
1284
0
    image_info->profile=(void *) DestroyStringInfo((StringInfo *)
1285
0
      image_info->profile);
1286
10.5M
  DestroyImageOptions(image_info);
1287
10.5M
  image_info->signature=(~MagickCoreSignature);
1288
10.5M
  image_info=(ImageInfo *) RelinquishMagickMemory(image_info);
1289
10.5M
  return(image_info);
1290
10.5M
}
1291

1292
/*
1293
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1294
%                                                                             %
1295
%                                                                             %
1296
%                                                                             %
1297
+   D i s a s s o c i a t e I m a g e S t r e a m                             %
1298
%                                                                             %
1299
%                                                                             %
1300
%                                                                             %
1301
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1302
%
1303
%  DisassociateImageStream() disassociates the image stream.  It checks if the
1304
%  blob of the specified image is referenced by other images. If the reference
1305
%  count is higher then 1 a new blob is assigned to the specified image.
1306
%
1307
%  The format of the DisassociateImageStream method is:
1308
%
1309
%      void DisassociateImageStream(const Image *image)
1310
%
1311
%  A description of each parameter follows:
1312
%
1313
%    o image: the image.
1314
%
1315
*/
1316
MagickExport void DisassociateImageStream(Image *image)
1317
75.7k
{
1318
75.7k
  assert(image != (Image *) NULL);
1319
75.7k
  assert(image->signature == MagickCoreSignature);
1320
75.7k
  if (IsEventLogging() != MagickFalse)
1321
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1322
75.7k
  DisassociateBlob(image);
1323
75.7k
}
1324

1325
/*
1326
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327
%                                                                             %
1328
%                                                                             %
1329
%                                                                             %
1330
%   G e t I m a g e I n f o                                                   %
1331
%                                                                             %
1332
%                                                                             %
1333
%                                                                             %
1334
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1335
%
1336
%  GetImageInfo() initializes image_info to default values.
1337
%
1338
%  The format of the GetImageInfo method is:
1339
%
1340
%      void GetImageInfo(ImageInfo *image_info)
1341
%
1342
%  A description of each parameter follows:
1343
%
1344
%    o image_info: the image info.
1345
%
1346
*/
1347
MagickExport void GetImageInfo(ImageInfo *image_info)
1348
10.5M
{
1349
10.5M
  char
1350
10.5M
    *synchronize;
1351
1352
  /*
1353
    File and image dimension members.
1354
  */
1355
10.5M
  assert(image_info != (ImageInfo *) NULL);
1356
10.5M
  if (IsEventLogging() != MagickFalse)
1357
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1358
10.5M
  (void) memset(image_info,0,sizeof(*image_info));
1359
10.5M
  image_info->adjoin=MagickTrue;
1360
10.5M
  image_info->interlace=NoInterlace;
1361
10.5M
  image_info->channel=AllChannels;
1362
10.5M
  image_info->quality=UndefinedCompressionQuality;
1363
10.5M
  image_info->antialias=MagickTrue;
1364
10.5M
  image_info->dither=MagickTrue;
1365
10.5M
  image_info->depth=0;
1366
10.5M
  synchronize=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
1367
10.5M
  if (synchronize != (const char *) NULL)
1368
0
    {
1369
0
      image_info->synchronize=IsStringTrue(synchronize);
1370
0
      synchronize=DestroyString(synchronize);
1371
0
    }
1372
10.5M
  GetPixelInfoRGBA(BackgroundColorRGBA,&image_info->background_color);
1373
10.5M
  GetPixelInfoRGBA(BorderColorRGBA,&image_info->border_color);
1374
10.5M
  GetPixelInfoRGBA(MatteColorRGBA,&image_info->matte_color);
1375
10.5M
  GetPixelInfoRGBA(TransparentColorRGBA,&image_info->transparent_color);
1376
10.5M
  image_info->debug=(GetLogEventMask() & ImageEvent) != 0 ? MagickTrue :
1377
10.5M
    MagickFalse;
1378
10.5M
  image_info->signature=MagickCoreSignature;
1379
10.5M
}
1380

1381
/*
1382
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1383
%                                                                             %
1384
%                                                                             %
1385
%                                                                             %
1386
%   G e t I m a g e I n f o F i l e                                           %
1387
%                                                                             %
1388
%                                                                             %
1389
%                                                                             %
1390
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1391
%
1392
%  GetImageInfoFile() returns the image info file member.
1393
%
1394
%  The format of the GetImageInfoFile method is:
1395
%
1396
%      FILE *GetImageInfoFile(const ImageInfo *image_info)
1397
%
1398
%  A description of each parameter follows:
1399
%
1400
%    o image_info: the image info.
1401
%
1402
*/
1403
MagickExport FILE *GetImageInfoFile(const ImageInfo *image_info)
1404
0
{
1405
0
  return(image_info->file);
1406
0
}
1407

1408
/*
1409
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410
%                                                                             %
1411
%                                                                             %
1412
%                                                                             %
1413
%   G e t I m a g e M a s k                                                   %
1414
%                                                                             %
1415
%                                                                             %
1416
%                                                                             %
1417
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1418
%
1419
%  GetImageMask() returns the mask associated with the image.
1420
%
1421
%  The format of the GetImageMask method is:
1422
%
1423
%      Image *GetImageMask(const Image *image,const PixelMask type,
1424
%        ExceptionInfo *exception)
1425
%
1426
%  A description of each parameter follows:
1427
%
1428
%    o image: the image.
1429
%
1430
%    o type: the mask type, ReadPixelMask or WritePixelMask.
1431
%
1432
*/
1433
MagickExport Image *GetImageMask(const Image *image,const PixelMask type,
1434
  ExceptionInfo *exception)
1435
0
{
1436
0
  CacheView
1437
0
    *mask_view,
1438
0
    *image_view;
1439
1440
0
  Image
1441
0
    *mask_image;
1442
1443
0
  MagickBooleanType
1444
0
    status;
1445
1446
0
  ssize_t
1447
0
    y;
1448
1449
  /*
1450
    Get image mask.
1451
  */
1452
0
  assert(image != (Image *) NULL);
1453
0
  assert(image->signature == MagickCoreSignature);
1454
0
  if (IsEventLogging() != MagickFalse)
1455
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1456
0
  switch (type)
1457
0
  {
1458
0
    case ReadPixelMask:
1459
0
    {
1460
0
      if ((image->channels & ReadMaskChannel) == 0)
1461
0
        return((Image *) NULL);
1462
0
      break;
1463
0
    }
1464
0
    case WritePixelMask:
1465
0
    {
1466
0
      if ((image->channels & WriteMaskChannel) == 0)
1467
0
        return((Image *) NULL);
1468
0
      break;
1469
0
    }
1470
0
    default:
1471
0
    {
1472
0
      if ((image->channels & CompositeMaskChannel) == 0)
1473
0
        return((Image *) NULL);
1474
0
      break;
1475
0
    }
1476
0
  }
1477
0
  mask_image=AcquireImage((ImageInfo *) NULL,exception);
1478
0
  status=SetImageExtent(mask_image,image->columns,image->rows,exception);
1479
0
  if (status == MagickFalse)
1480
0
    return(DestroyImage(mask_image));
1481
0
  status=MagickTrue;
1482
0
  mask_image->alpha_trait=UndefinedPixelTrait;
1483
0
  (void) SetImageColorspace(mask_image,GRAYColorspace,exception);
1484
0
  image_view=AcquireVirtualCacheView(image,exception);
1485
0
  mask_view=AcquireAuthenticCacheView(mask_image,exception);
1486
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1487
  #pragma omp parallel for schedule(static) shared(status) \
1488
    magick_number_threads(image,image,image->rows,2)
1489
#endif
1490
0
  for (y=0; y < (ssize_t) image->rows; y++)
1491
0
  {
1492
0
    const Quantum
1493
0
      *magick_restrict p;
1494
1495
0
    Quantum
1496
0
      *magick_restrict q;
1497
1498
0
    ssize_t
1499
0
      x;
1500
1501
0
    if (status == MagickFalse)
1502
0
      continue;
1503
0
    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1504
0
    q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1505
0
      exception);
1506
0
    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1507
0
      {
1508
0
        status=MagickFalse;
1509
0
        continue;
1510
0
      }
1511
0
    for (x=0; x < (ssize_t) image->columns; x++)
1512
0
    {
1513
0
      switch (type)
1514
0
      {
1515
0
        case ReadPixelMask:
1516
0
        {
1517
0
          SetPixelGray(mask_image,GetPixelReadMask(image,p),q);
1518
0
          break;
1519
0
        }
1520
0
        case WritePixelMask:
1521
0
        {
1522
0
          SetPixelGray(mask_image,GetPixelWriteMask(image,p),q);
1523
0
          break;
1524
0
        }
1525
0
        default:
1526
0
        {
1527
0
          SetPixelGray(mask_image,GetPixelCompositeMask(image,p),q);
1528
0
          break;
1529
0
        }
1530
0
      }
1531
0
      p+=(ptrdiff_t) GetPixelChannels(image);
1532
0
      q+=(ptrdiff_t) GetPixelChannels(mask_image);
1533
0
    }
1534
0
    if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1535
0
      status=MagickFalse;
1536
0
  }
1537
0
  mask_view=DestroyCacheView(mask_view);
1538
0
  image_view=DestroyCacheView(image_view);
1539
0
  if (status == MagickFalse)
1540
0
    mask_image=DestroyImage(mask_image);
1541
0
  return(mask_image);
1542
0
}
1543

1544
/*
1545
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1546
%                                                                             %
1547
%                                                                             %
1548
%                                                                             %
1549
+   G e t I m a g e R e f e r e n c e C o u n t                               %
1550
%                                                                             %
1551
%                                                                             %
1552
%                                                                             %
1553
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554
%
1555
%  GetImageReferenceCount() returns the image reference count.
1556
%
1557
%  The format of the GetReferenceCount method is:
1558
%
1559
%      ssize_t GetImageReferenceCount(Image *image)
1560
%
1561
%  A description of each parameter follows:
1562
%
1563
%    o image: the image.
1564
%
1565
*/
1566
MagickExport ssize_t GetImageReferenceCount(Image *image)
1567
0
{
1568
0
  ssize_t
1569
0
    reference_count;
1570
1571
0
  assert(image != (Image *) NULL);
1572
0
  assert(image->signature == MagickCoreSignature);
1573
0
  if (IsEventLogging() != MagickFalse)
1574
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1575
0
  LockSemaphoreInfo(image->semaphore);
1576
0
  reference_count=image->reference_count;
1577
0
  UnlockSemaphoreInfo(image->semaphore);
1578
0
  return(reference_count);
1579
0
}
1580

1581
/*
1582
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1583
%                                                                             %
1584
%                                                                             %
1585
%                                                                             %
1586
%   G e t I m a g e V i r t u a l P i x e l M e t h o d                       %
1587
%                                                                             %
1588
%                                                                             %
1589
%                                                                             %
1590
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1591
%
1592
%  GetImageVirtualPixelMethod() gets the "virtual pixels" method for the
1593
%  image.  A virtual pixel is any pixel access that is outside the boundaries
1594
%  of the image cache.
1595
%
1596
%  The format of the GetImageVirtualPixelMethod() method is:
1597
%
1598
%      VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1599
%
1600
%  A description of each parameter follows:
1601
%
1602
%    o image: the image.
1603
%
1604
*/
1605
MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1606
3.88M
{
1607
3.88M
  assert(image != (Image *) NULL);
1608
3.88M
  assert(image->signature == MagickCoreSignature);
1609
3.88M
  if (IsEventLogging() != MagickFalse)
1610
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1611
3.88M
  return(GetPixelCacheVirtualMethod(image));
1612
3.88M
}
1613

1614
/*
1615
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1616
%                                                                             %
1617
%                                                                             %
1618
%                                                                             %
1619
%  I n t e r p r e t I m a g e F i l e n a m e                                %
1620
%                                                                             %
1621
%                                                                             %
1622
%                                                                             %
1623
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1624
%
1625
%  InterpretImageFilename() interprets embedded characters in an image filename.
1626
%  The filename length is returned.
1627
%
1628
%  The format of the InterpretImageFilename method is:
1629
%
1630
%      size_t InterpretImageFilename(const ImageInfo *image_info,Image *image,
1631
%        const char *format,int value,char *filename,ExceptionInfo *exception)
1632
%
1633
%  A description of each parameter follows.
1634
%
1635
%    o image_info: the image info..
1636
%
1637
%    o image: the image.
1638
%
1639
%    o format:  A filename describing the format to use to write the numeric
1640
%      argument. Only the first numeric format identifier is replaced.
1641
%
1642
%    o value:  Numeric value to substitute into format filename.
1643
%
1644
%    o filename:  return the formatted filename in this character buffer.
1645
%
1646
%    o exception: return any errors or warnings in this structure.
1647
%
1648
*/
1649
MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
1650
  Image *image,const char *format,int value,char *filename,
1651
  ExceptionInfo *exception)
1652
84.1k
{
1653
84.1k
  char
1654
84.1k
    *q;
1655
1656
84.1k
  const char
1657
84.1k
    *p;
1658
1659
84.1k
  int
1660
84.1k
    c;
1661
1662
84.1k
  MagickBooleanType
1663
84.1k
    canonical;
1664
1665
84.1k
  ssize_t
1666
84.1k
    field_width,
1667
84.1k
    offset;
1668
1669
84.1k
  canonical=MagickFalse;
1670
84.1k
  offset=0;
1671
84.1k
  (void) CopyMagickString(filename,format,MagickPathExtent);
1672
84.1k
  if (IsStringTrue(GetImageOption(image_info,"filename:literal")) != MagickFalse)
1673
0
    return(strlen(filename));
1674
168k
  for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
1675
84.1k
  {
1676
84.1k
    q=(char *) p+1;
1677
84.1k
    if (*q == '%')
1678
0
      {
1679
0
        p=q+1;
1680
0
        continue;
1681
0
      }
1682
84.1k
    field_width=0;
1683
84.1k
    if (*q == '0')
1684
0
      field_width=(ssize_t) strtol(q,&q,10);
1685
84.1k
    switch (*q)
1686
84.1k
    {
1687
84.1k
      case 'd':
1688
84.1k
      case 'o':
1689
84.1k
      case 'x':
1690
84.1k
      {
1691
84.1k
        q++;
1692
84.1k
        c=(*q);
1693
84.1k
        *q='\0';
1694
84.1k
        (void) FormatLocaleString(filename+(p-format-offset),(size_t)
1695
84.1k
          (MagickPathExtent-(p-format-offset)),p,value);
1696
84.1k
        offset+=(4-field_width);
1697
84.1k
        *q=(char) c;
1698
84.1k
        (void) ConcatenateMagickString(filename,q,MagickPathExtent);
1699
84.1k
        canonical=MagickTrue;
1700
84.1k
        if (*(q-1) != '%')
1701
84.1k
          break;
1702
0
        p++;
1703
0
        break;
1704
84.1k
      }
1705
0
      case '[':
1706
0
      {
1707
0
        char
1708
0
          pattern[MagickPathExtent];
1709
1710
0
        const char
1711
0
          *option;
1712
1713
0
        char
1714
0
          *r;
1715
1716
0
        ssize_t
1717
0
          i;
1718
1719
0
        ssize_t
1720
0
          depth;
1721
1722
        /*
1723
          Image option.
1724
        */
1725
0
        if (strchr(p,']') == (char *) NULL)
1726
0
          break;
1727
0
        depth=1;
1728
0
        r=q+1;
1729
0
        for (i=0; (i < (MagickPathExtent-1L)) && (*r != '\0'); i++)
1730
0
        {
1731
0
          if (*r == '[')
1732
0
            depth++;
1733
0
          if (*r == ']')
1734
0
            depth--;
1735
0
          if (depth <= 0)
1736
0
            break;
1737
0
          pattern[i]=(*r++);
1738
0
        }
1739
0
        pattern[i]='\0';
1740
0
        if (LocaleNCompare(pattern,"filename:",9) != 0)
1741
0
          break;
1742
0
        option=(const char *) NULL;
1743
0
        if (image != (Image *) NULL)
1744
0
          option=GetImageProperty(image,pattern,exception);
1745
0
        if ((option == (const char *) NULL) && (image != (Image *) NULL))
1746
0
          option=GetImageArtifact(image,pattern);
1747
0
        if ((option == (const char *) NULL) &&
1748
0
            (image_info != (ImageInfo *) NULL))
1749
0
          option=GetImageOption(image_info,pattern);
1750
0
        if (option == (const char *) NULL)
1751
0
          break;
1752
0
        q--;
1753
0
        c=(*q);
1754
0
        *q='\0';
1755
0
        (void) CopyMagickString(filename+(p-format-offset),option,(size_t)
1756
0
          (MagickPathExtent-(p-format-offset)));
1757
0
        offset+=(ssize_t) strlen(pattern)-(ssize_t) strlen(option)+3;
1758
0
        *q=(char) c;
1759
0
        (void) ConcatenateMagickString(filename,r+1,MagickPathExtent);
1760
0
        canonical=MagickTrue;
1761
0
        if (*(q-1) != '%')
1762
0
          break;
1763
0
        p++;
1764
0
        break;
1765
0
      }
1766
0
      default:
1767
0
        break;
1768
84.1k
    }
1769
84.1k
  }
1770
84.1k
  if (canonical == MagickFalse)
1771
0
    (void) CopyMagickString(filename,format,MagickPathExtent);
1772
84.1k
  else
1773
3.86M
    for (q=filename; *q != '\0'; q++)
1774
3.78M
      if ((*q == '%') && (*(q+1) == '%'))
1775
0
        (void) CopyMagickString(q,q+1,(size_t) (MagickPathExtent-(q-filename)));
1776
84.1k
  return(strlen(filename));
1777
84.1k
}
1778

1779
/*
1780
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781
%                                                                             %
1782
%                                                                             %
1783
%                                                                             %
1784
%   I s H i g h D y n a m i c R a n g e I m a g e                             %
1785
%                                                                             %
1786
%                                                                             %
1787
%                                                                             %
1788
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1789
%
1790
%  IsHighDynamicRangeImage() returns MagickTrue if any pixel component is
1791
%  non-integer or exceeds the bounds of the quantum depth (e.g. for Q16
1792
%  0..65535.
1793
%
1794
%  The format of the IsHighDynamicRangeImage method is:
1795
%
1796
%      MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1797
%        ExceptionInfo *exception)
1798
%
1799
%  A description of each parameter follows:
1800
%
1801
%    o image: the image.
1802
%
1803
%    o exception: return any errors or warnings in this structure.
1804
%
1805
*/
1806
MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1807
  ExceptionInfo *exception)
1808
3.88k
{
1809
#if !defined(MAGICKCORE_HDRI_SUPPORT)
1810
  (void) image;
1811
  (void) exception;
1812
  return(MagickFalse);
1813
#else
1814
3.88k
  CacheView
1815
3.88k
    *image_view;
1816
1817
3.88k
  MagickBooleanType
1818
3.88k
    hdri = MagickFalse;
1819
1820
3.88k
  ssize_t
1821
3.88k
    y;
1822
1823
3.88k
  assert(image != (Image *) NULL);
1824
3.88k
  assert(image->signature == MagickCoreSignature);
1825
3.88k
  if (IsEventLogging() != MagickFalse)
1826
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1827
3.88k
  image_view=AcquireVirtualCacheView(image,exception);
1828
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1829
  #pragma omp parallel for schedule(static) shared(hdri) \
1830
    magick_number_threads(image,image,image->rows,2)
1831
#endif
1832
170k
  for (y=0; y < (ssize_t) image->rows; y++)
1833
167k
  {
1834
167k
    const Quantum
1835
167k
      *p;
1836
1837
167k
    ssize_t
1838
167k
      x;
1839
1840
167k
    if (hdri != MagickFalse)
1841
49.0k
      continue;
1842
118k
    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1843
118k
    if (p == (const Quantum *) NULL)
1844
0
      continue;
1845
112M
    for (x=0; x < (ssize_t) image->columns; x++)
1846
111M
    {
1847
111M
      ssize_t
1848
111M
        i;
1849
1850
610M
      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1851
498M
      {
1852
498M
        double
1853
498M
          pixel;
1854
1855
498M
        PixelTrait
1856
498M
          traits;
1857
1858
498M
        traits=GetPixelChannelTraits(image,(PixelChannel) i);
1859
498M
        if (traits == UndefinedPixelTrait)
1860
32.6M
          continue;
1861
466M
        pixel=(double) p[i];
1862
466M
        if ((pixel < 0.0) || (pixel > (double) QuantumRange) ||
1863
466M
            (pixel != (double) ((QuantumAny) pixel)))
1864
2.14k
          {
1865
2.14k
            hdri=MagickTrue;
1866
2.14k
            break;
1867
2.14k
          }
1868
466M
      }
1869
111M
      if (hdri != MagickFalse)
1870
2.14k
        break;
1871
111M
      p+=(ptrdiff_t) GetPixelChannels(image);
1872
111M
    }
1873
118k
  }
1874
3.88k
  image_view=DestroyCacheView(image_view);
1875
3.88k
  return(hdri);
1876
3.88k
#endif
1877
3.88k
}
1878

1879
/*
1880
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1881
%                                                                             %
1882
%                                                                             %
1883
%                                                                             %
1884
%     I s I m a g e O b j e c t                                               %
1885
%                                                                             %
1886
%                                                                             %
1887
%                                                                             %
1888
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1889
%
1890
%  IsImageObject() returns MagickTrue if the image sequence contains a valid
1891
%  set of image objects.
1892
%
1893
%  The format of the IsImageObject method is:
1894
%
1895
%      MagickBooleanType IsImageObject(const Image *image)
1896
%
1897
%  A description of each parameter follows:
1898
%
1899
%    o image: the image.
1900
%
1901
*/
1902
MagickExport MagickBooleanType IsImageObject(const Image *image)
1903
0
{
1904
0
  const Image
1905
0
    *p;
1906
1907
0
  assert(image != (Image *) NULL);
1908
0
  if (IsEventLogging() != MagickFalse)
1909
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1910
0
  for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1911
0
    if (p->signature != MagickCoreSignature)
1912
0
      return(MagickFalse);
1913
0
  return(MagickTrue);
1914
0
}
1915

1916
/*
1917
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1918
%                                                                             %
1919
%                                                                             %
1920
%                                                                             %
1921
%     I s T a i n t I m a g e                                                 %
1922
%                                                                             %
1923
%                                                                             %
1924
%                                                                             %
1925
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1926
%
1927
%  IsTaintImage() returns MagickTrue any pixel in the image has been altered
1928
%  since it was first constituted.
1929
%
1930
%  The format of the IsTaintImage method is:
1931
%
1932
%      MagickBooleanType IsTaintImage(const Image *image)
1933
%
1934
%  A description of each parameter follows:
1935
%
1936
%    o image: the image.
1937
%
1938
*/
1939
MagickExport MagickBooleanType IsTaintImage(const Image *image)
1940
0
{
1941
0
  char
1942
0
    magick[MagickPathExtent],
1943
0
    filename[MagickPathExtent];
1944
1945
0
  const Image
1946
0
    *p;
1947
1948
0
  assert(image != (Image *) NULL);
1949
0
  assert(image->signature == MagickCoreSignature);
1950
0
  if (IsEventLogging() != MagickFalse)
1951
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1952
0
  (void) CopyMagickString(magick,image->magick,MagickPathExtent);
1953
0
  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
1954
0
  for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1955
0
  {
1956
0
    if (p->taint != MagickFalse)
1957
0
      return(MagickTrue);
1958
0
    if (LocaleCompare(p->magick,magick) != 0)
1959
0
      return(MagickTrue);
1960
0
    if (LocaleCompare(p->filename,filename) != 0)
1961
0
      return(MagickTrue);
1962
0
  }
1963
0
  return(MagickFalse);
1964
0
}
1965

1966
/*
1967
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1968
%                                                                             %
1969
%                                                                             %
1970
%                                                                             %
1971
%   M o d i f y I m a g e                                                     %
1972
%                                                                             %
1973
%                                                                             %
1974
%                                                                             %
1975
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1976
%
1977
%  ModifyImage() ensures that there is only a single reference to the image
1978
%  to be modified, updating the provided image pointer to point to a clone of
1979
%  the original image if necessary.
1980
%
1981
%  The format of the ModifyImage method is:
1982
%
1983
%      MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception)
1984
%
1985
%  A description of each parameter follows:
1986
%
1987
%    o image: the image.
1988
%
1989
%    o exception: return any errors or warnings in this structure.
1990
%
1991
*/
1992
MagickExport MagickBooleanType ModifyImage(Image **image,
1993
  ExceptionInfo *exception)
1994
0
{
1995
0
  Image
1996
0
    *clone_image;
1997
1998
0
  assert(image != (Image **) NULL);
1999
0
  assert(*image != (Image *) NULL);
2000
0
  assert((*image)->signature == MagickCoreSignature);
2001
0
  if (IsEventLogging() != MagickFalse)
2002
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
2003
0
  if (GetImageReferenceCount(*image) <= 1)
2004
0
    return(MagickTrue);
2005
0
  clone_image=CloneImage(*image,0,0,MagickTrue,exception);
2006
0
  LockSemaphoreInfo((*image)->semaphore);
2007
0
  (*image)->reference_count--;
2008
0
  UnlockSemaphoreInfo((*image)->semaphore);
2009
0
  *image=clone_image;
2010
0
  return(MagickTrue);
2011
0
}
2012

2013
/*
2014
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2015
%                                                                             %
2016
%                                                                             %
2017
%                                                                             %
2018
%   N e w M a g i c k I m a g e                                               %
2019
%                                                                             %
2020
%                                                                             %
2021
%                                                                             %
2022
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2023
%
2024
%  NewMagickImage() creates a blank image canvas of the specified size and
2025
%  background color.
2026
%
2027
%  The format of the NewMagickImage method is:
2028
%
2029
%      Image *NewMagickImage(const ImageInfo *image_info,const size_t width,
2030
%        const size_t height,const PixelInfo *background,
2031
%        ExceptionInfo *exception)
2032
%
2033
%  A description of each parameter follows:
2034
%
2035
%    o image: the image.
2036
%
2037
%    o width: the image width.
2038
%
2039
%    o height: the image height.
2040
%
2041
%    o background: the image color.
2042
%
2043
%    o exception: return any errors or warnings in this structure.
2044
%
2045
*/
2046
MagickExport Image *NewMagickImage(const ImageInfo *image_info,
2047
  const size_t width,const size_t height,const PixelInfo *background,
2048
  ExceptionInfo *exception)
2049
0
{
2050
0
  CacheView
2051
0
    *image_view;
2052
2053
0
  Image
2054
0
    *image;
2055
2056
0
  MagickBooleanType
2057
0
    status;
2058
2059
0
  ssize_t
2060
0
    y;
2061
2062
0
  assert(image_info != (const ImageInfo *) NULL);
2063
0
  assert(image_info->signature == MagickCoreSignature);
2064
0
  assert(background != (const PixelInfo *) NULL);
2065
0
  if (IsEventLogging() != MagickFalse)
2066
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2067
0
  image=AcquireImage(image_info,exception);
2068
0
  image->columns=width;
2069
0
  image->rows=height;
2070
0
  image->colorspace=background->colorspace;
2071
0
  image->alpha_trait=background->alpha_trait;
2072
0
  image->fuzz=background->fuzz;
2073
0
  image->depth=background->depth;
2074
0
  status=MagickTrue;
2075
0
  image_view=AcquireAuthenticCacheView(image,exception);
2076
#if defined(MAGICKCORE_OPENMP_SUPPORT)
2077
  #pragma omp parallel for schedule(static) shared(status) \
2078
    magick_number_threads(image,image,image->rows,2)
2079
#endif
2080
0
  for (y=0; y < (ssize_t) image->rows; y++)
2081
0
  {
2082
0
    Quantum
2083
0
      *magick_restrict q;
2084
2085
0
    ssize_t
2086
0
      x;
2087
2088
0
    if (status == MagickFalse)
2089
0
      continue;
2090
0
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2091
0
    if (q == (Quantum *) NULL)
2092
0
      {
2093
0
        status=MagickFalse;
2094
0
        continue;
2095
0
      }
2096
0
    for (x=0; x < (ssize_t) image->columns; x++)
2097
0
    {
2098
0
      SetPixelViaPixelInfo(image,background,q);
2099
0
      q+=(ptrdiff_t) GetPixelChannels(image);
2100
0
    }
2101
0
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2102
0
      status=MagickFalse;
2103
0
  }
2104
0
  image_view=DestroyCacheView(image_view);
2105
0
  if (status == MagickFalse)
2106
0
    image=DestroyImage(image);
2107
0
  return(image);
2108
0
}
2109

2110
/*
2111
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2112
%                                                                             %
2113
%                                                                             %
2114
%                                                                             %
2115
%   R e f e r e n c e I m a g e                                               %
2116
%                                                                             %
2117
%                                                                             %
2118
%                                                                             %
2119
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2120
%
2121
%  ReferenceImage() increments the reference count associated with an image
2122
%  returning a pointer to the image.
2123
%
2124
%  The format of the ReferenceImage method is:
2125
%
2126
%      Image *ReferenceImage(Image *image)
2127
%
2128
%  A description of each parameter follows:
2129
%
2130
%    o image: the image.
2131
%
2132
*/
2133
MagickExport Image *ReferenceImage(Image *image)
2134
3.88M
{
2135
3.88M
  assert(image != (Image *) NULL);
2136
3.88M
  assert(image->signature == MagickCoreSignature);
2137
3.88M
  if (IsEventLogging() != MagickFalse)
2138
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2139
3.88M
  LockSemaphoreInfo(image->semaphore);
2140
3.88M
  image->reference_count++;
2141
3.88M
  UnlockSemaphoreInfo(image->semaphore);
2142
3.88M
  return(image);
2143
3.88M
}
2144

2145
/*
2146
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2147
%                                                                             %
2148
%                                                                             %
2149
%                                                                             %
2150
%   R e s e t I m a g e P a g e                                               %
2151
%                                                                             %
2152
%                                                                             %
2153
%                                                                             %
2154
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2155
%
2156
%  ResetImagePage() resets the image page canvas and position.
2157
%
2158
%  The format of the ResetImagePage method is:
2159
%
2160
%      MagickBooleanType ResetImagePage(Image *image,const char *page)
2161
%
2162
%  A description of each parameter follows:
2163
%
2164
%    o image: the image.
2165
%
2166
%    o page: the relative page specification.
2167
%
2168
*/
2169
MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page)
2170
38.6k
{
2171
38.6k
  MagickStatusType
2172
38.6k
    flags;
2173
2174
38.6k
  RectangleInfo
2175
38.6k
    geometry;
2176
2177
38.6k
  assert(image != (Image *) NULL);
2178
38.6k
  assert(image->signature == MagickCoreSignature);
2179
38.6k
  if (IsEventLogging() != MagickFalse)
2180
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2181
38.6k
  flags=ParseAbsoluteGeometry(page,&geometry);
2182
38.6k
  if ((flags & WidthValue) != 0)
2183
38.6k
    {
2184
38.6k
      if ((flags & HeightValue) == 0)
2185
0
        geometry.height=geometry.width;
2186
38.6k
      image->page.width=geometry.width;
2187
38.6k
      image->page.height=geometry.height;
2188
38.6k
    }
2189
38.6k
  if ((flags & AspectValue) != 0)
2190
0
    {
2191
0
      if ((flags & XValue) != 0)
2192
0
        image->page.x+=geometry.x;
2193
0
      if ((flags & YValue) != 0)
2194
0
        image->page.y+=geometry.y;
2195
0
    }
2196
38.6k
  else
2197
38.6k
    {
2198
38.6k
      if ((flags & XValue) != 0)
2199
38.6k
        {
2200
38.6k
          image->page.x=geometry.x;
2201
38.6k
          if ((image->page.width == 0) && (geometry.x > 0))
2202
0
            image->page.width=(size_t) ((ssize_t) image->columns+geometry.x);
2203
38.6k
        }
2204
38.6k
      if ((flags & YValue) != 0)
2205
38.6k
        {
2206
38.6k
          image->page.y=geometry.y;
2207
38.6k
          if ((image->page.height == 0) && (geometry.y > 0))
2208
0
            image->page.height=(size_t) ((ssize_t) image->rows+geometry.y);
2209
38.6k
        }
2210
38.6k
    }
2211
38.6k
  return(MagickTrue);
2212
38.6k
}
2213

2214
/*
2215
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2216
%                                                                             %
2217
%                                                                             %
2218
%                                                                             %
2219
%   R e s e t I m a g e P i x e l s                                           %
2220
%                                                                             %
2221
%                                                                             %
2222
%                                                                             %
2223
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2224
%
2225
%  ResetImagePixels() reset the image pixels, that is, all the pixel components
2226
%  are zeroed.
2227
%
2228
%  The format of the SetImage method is:
2229
%
2230
%      MagickBooleanType ResetImagePixels(Image *image,
2231
%        ExceptionInfo *exception)
2232
%
2233
%  A description of each parameter follows:
2234
%
2235
%    o image: the image.
2236
%
2237
%    o exception: return any errors or warnings in this structure.
2238
%
2239
*/
2240
MagickExport MagickBooleanType ResetImagePixels(Image *image,
2241
  ExceptionInfo *exception)
2242
245k
{
2243
245k
  CacheView
2244
245k
    *image_view;
2245
2246
245k
  MagickBooleanType
2247
245k
    status;
2248
2249
245k
  size_t
2250
245k
    length;
2251
2252
245k
  ssize_t
2253
245k
    y;
2254
2255
245k
  void
2256
245k
    *pixels;
2257
2258
245k
  assert(image != (Image *) NULL);
2259
245k
  assert(image->signature == MagickCoreSignature);
2260
245k
  if (IsEventLogging() != MagickFalse)
2261
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2262
245k
  pixels=AcquirePixelCachePixels(image,&length,exception);
2263
245k
  if (pixels != (void *) NULL)
2264
240k
    {
2265
      /*
2266
        Reset in-core image pixels.
2267
      */
2268
240k
      (void) memset(pixels,0,length);
2269
240k
      return(MagickTrue);
2270
240k
    }
2271
  /*
2272
    Reset image pixels.
2273
  */
2274
4.98k
  status=MagickTrue;
2275
4.98k
  image_view=AcquireAuthenticCacheView(image,exception);
2276
#if defined(MAGICKCORE_OPENMP_SUPPORT)
2277
  #pragma omp parallel for schedule(static) shared(status) \
2278
    magick_number_threads(image,image,image->rows,2)
2279
#endif
2280
1.09M
  for (y=0; y < (ssize_t) image->rows; y++)
2281
1.09M
  {
2282
1.09M
    Quantum
2283
1.09M
      *magick_restrict q;
2284
2285
1.09M
    ssize_t
2286
1.09M
      x;
2287
2288
1.09M
    if (status == MagickFalse)
2289
0
      continue;
2290
1.09M
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2291
1.09M
    if (q == (Quantum *) NULL)
2292
0
      {
2293
0
        status=MagickFalse;
2294
0
        continue;
2295
0
      }
2296
596M
    for (x=0; x < (ssize_t) image->columns; x++)
2297
595M
    {
2298
595M
      (void) memset(q,0,GetPixelChannels(image)*sizeof(Quantum));
2299
595M
      q+=(ptrdiff_t) GetPixelChannels(image);
2300
595M
    }
2301
1.09M
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2302
0
      status=MagickFalse;
2303
1.09M
  }
2304
4.98k
  image_view=DestroyCacheView(image_view);
2305
4.98k
  return(status);
2306
245k
}
2307

2308
/*
2309
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2310
%                                                                             %
2311
%                                                                             %
2312
%                                                                             %
2313
%     S e t I m a g e A l p h a                                               %
2314
%                                                                             %
2315
%                                                                             %
2316
%                                                                             %
2317
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2318
%
2319
%  SetImageAlpha() sets the alpha levels of the image.
2320
%
2321
%  The format of the SetImageAlpha method is:
2322
%
2323
%      MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha,
2324
%        ExceptionInfo *exception)
2325
%
2326
%  A description of each parameter follows:
2327
%
2328
%    o image: the image.
2329
%
2330
%    o alpha: the level of transparency: 0 is fully transparent and QuantumRange
2331
%      is fully opaque.
2332
%
2333
%    o exception: return any errors or warnings in this structure.
2334
%
2335
*/
2336
MagickExport MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha,
2337
  ExceptionInfo *exception)
2338
47.4k
{
2339
47.4k
  CacheView
2340
47.4k
    *image_view;
2341
2342
47.4k
  MagickBooleanType
2343
47.4k
    status;
2344
2345
47.4k
  ssize_t
2346
47.4k
    y;
2347
2348
47.4k
  assert(image != (Image *) NULL);
2349
47.4k
  assert(image->signature == MagickCoreSignature);
2350
47.4k
  if (IsEventLogging() != MagickFalse)
2351
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2352
47.4k
  image->alpha_trait=BlendPixelTrait;
2353
47.4k
  status=MagickTrue;
2354
47.4k
  image_view=AcquireAuthenticCacheView(image,exception);
2355
#if defined(MAGICKCORE_OPENMP_SUPPORT)
2356
  #pragma omp parallel for schedule(static) shared(status) \
2357
    magick_number_threads(image,image,image->rows,2)
2358
#endif
2359
8.17M
  for (y=0; y < (ssize_t) image->rows; y++)
2360
8.12M
  {
2361
8.12M
    Quantum
2362
8.12M
      *magick_restrict q;
2363
2364
8.12M
    ssize_t
2365
8.12M
      x;
2366
2367
8.12M
    if (status == MagickFalse)
2368
0
      continue;
2369
8.12M
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2370
8.12M
    if (q == (Quantum *) NULL)
2371
0
      {
2372
0
        status=MagickFalse;
2373
0
        continue;
2374
0
      }
2375
6.11G
    for (x=0; x < (ssize_t) image->columns; x++)
2376
6.10G
    {
2377
6.10G
      if (GetPixelWriteMask(image,q) > (QuantumRange/2))
2378
6.10G
        SetPixelAlpha(image,alpha,q);
2379
6.10G
      q+=(ptrdiff_t) GetPixelChannels(image);
2380
6.10G
    }
2381
8.12M
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2382
0
      status=MagickFalse;
2383
8.12M
  }
2384
47.4k
  image_view=DestroyCacheView(image_view);
2385
47.4k
  return(status);
2386
47.4k
}
2387

2388
/*
2389
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2390
%                                                                             %
2391
%                                                                             %
2392
%                                                                             %
2393
%   S e t I m a g e B a c k g r o u n d C o l o r                             %
2394
%                                                                             %
2395
%                                                                             %
2396
%                                                                             %
2397
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2398
%
2399
%  SetImageBackgroundColor() initializes the image pixels to the image
2400
%  background color.  The background color is defined by the background_color
2401
%  member of the image structure.
2402
%
2403
%  The format of the SetImage method is:
2404
%
2405
%      MagickBooleanType SetImageBackgroundColor(Image *image,
2406
%        ExceptionInfo *exception)
2407
%
2408
%  A description of each parameter follows:
2409
%
2410
%    o image: the image.
2411
%
2412
%    o exception: return any errors or warnings in this structure.
2413
%
2414
*/
2415
MagickExport MagickBooleanType SetImageBackgroundColor(Image *image,
2416
  ExceptionInfo *exception)
2417
301k
{
2418
301k
  CacheView
2419
301k
    *image_view;
2420
2421
301k
  MagickBooleanType
2422
301k
    status;
2423
2424
301k
  PixelInfo
2425
301k
    background;
2426
2427
301k
  ssize_t
2428
301k
    y;
2429
2430
301k
  assert(image != (Image *) NULL);
2431
301k
  assert(image->signature == MagickCoreSignature);
2432
301k
  if (IsEventLogging() != MagickFalse)
2433
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2434
301k
  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2435
4.06k
    return(MagickFalse);
2436
297k
  if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
2437
297k
      ((image->alpha_trait & BlendPixelTrait) == 0))
2438
181k
    (void) SetImageAlphaChannel(image,ActivateAlphaChannel,exception);
2439
297k
  ConformPixelInfo(image,&image->background_color,&background,exception);
2440
  /*
2441
    Set image background color.
2442
  */
2443
297k
  status=MagickTrue;
2444
297k
  image_view=AcquireAuthenticCacheView(image,exception);
2445
#if defined(MAGICKCORE_OPENMP_SUPPORT)
2446
  #pragma omp parallel for schedule(static) shared(status) \
2447
    magick_number_threads(image,image,image->rows,2)
2448
#endif
2449
18.4M
  for (y=0; y < (ssize_t) image->rows; y++)
2450
18.1M
  {
2451
18.1M
    Quantum
2452
18.1M
      *magick_restrict q;
2453
2454
18.1M
    ssize_t
2455
18.1M
      x;
2456
2457
18.1M
    if (status == MagickFalse)
2458
0
      continue;
2459
18.1M
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2460
18.1M
    if (q == (Quantum *) NULL)
2461
0
      {
2462
0
        status=MagickFalse;
2463
0
        continue;
2464
0
      }
2465
14.8G
    for (x=0; x < (ssize_t) image->columns; x++)
2466
14.8G
    {
2467
14.8G
      SetPixelViaPixelInfo(image,&background,q);
2468
14.8G
      q+=(ptrdiff_t) GetPixelChannels(image);
2469
14.8G
    }
2470
18.1M
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2471
0
      status=MagickFalse;
2472
18.1M
  }
2473
297k
  image_view=DestroyCacheView(image_view);
2474
297k
  return(status);
2475
301k
}
2476

2477
/*
2478
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2479
%                                                                             %
2480
%                                                                             %
2481
%                                                                             %
2482
%   S e t I m a g e C h a n n e l M a s k                                     %
2483
%                                                                             %
2484
%                                                                             %
2485
%                                                                             %
2486
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2487
%
2488
%  SetImageChannelMask() sets the image channel mask from the specified channel
2489
%  mask.
2490
%
2491
%  The format of the SetImageChannelMask method is:
2492
%
2493
%      ChannelType SetImageChannelMask(Image *image,
2494
%        const ChannelType channel_mask)
2495
%
2496
%  A description of each parameter follows:
2497
%
2498
%    o image: the image.
2499
%
2500
%    o channel_mask: the channel mask.
2501
%
2502
*/
2503
MagickExport ChannelType SetImageChannelMask(Image *image,
2504
  const ChannelType channel_mask)
2505
174k
{
2506
174k
  return(SetPixelChannelMask(image,channel_mask));
2507
174k
}
2508

2509
/*
2510
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2511
%                                                                             %
2512
%                                                                             %
2513
%                                                                             %
2514
%   S e t I m a g e C o l o r                                                 %
2515
%                                                                             %
2516
%                                                                             %
2517
%                                                                             %
2518
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2519
%
2520
%  SetImageColor() set the entire image canvas to the specified color.
2521
%
2522
%  The format of the SetImageColor method is:
2523
%
2524
%      MagickBooleanType SetImageColor(Image *image,const PixelInfo *color,
2525
%        ExceptionInfo *exception)
2526
%
2527
%  A description of each parameter follows:
2528
%
2529
%    o image: the image.
2530
%
2531
%    o background: the image color.
2532
%
2533
%    o exception: return any errors or warnings in this structure.
2534
%
2535
*/
2536
MagickExport MagickBooleanType SetImageColor(Image *image,
2537
  const PixelInfo *color,ExceptionInfo *exception)
2538
521
{
2539
521
  CacheView
2540
521
    *image_view;
2541
2542
521
  MagickBooleanType
2543
521
    status;
2544
2545
521
  ssize_t
2546
521
    y;
2547
2548
521
  assert(image != (Image *) NULL);
2549
521
  assert(image->signature == MagickCoreSignature);
2550
521
  assert(color != (const PixelInfo *) NULL);
2551
521
  if (IsEventLogging() != MagickFalse)
2552
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2553
521
  image->colorspace=color->colorspace;
2554
521
  image->alpha_trait=color->alpha_trait;
2555
521
  image->fuzz=color->fuzz;
2556
521
  image->depth=color->depth;
2557
521
  status=MagickTrue;
2558
521
  image_view=AcquireAuthenticCacheView(image,exception);
2559
#if defined(MAGICKCORE_OPENMP_SUPPORT)
2560
  #pragma omp parallel for schedule(static) shared(status) \
2561
    magick_number_threads(image,image,image->rows,2)
2562
#endif
2563
963M
  for (y=0; y < (ssize_t) image->rows; y++)
2564
963M
  {
2565
963M
    Quantum
2566
963M
      *magick_restrict q;
2567
2568
963M
    ssize_t
2569
963M
      x;
2570
2571
963M
    if (status == MagickFalse)
2572
963M
      continue;
2573
8.90k
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2574
8.90k
    if (q == (Quantum *) NULL)
2575
125
      {
2576
125
        status=MagickFalse;
2577
125
        continue;
2578
125
      }
2579
1.63M
    for (x=0; x < (ssize_t) image->columns; x++)
2580
1.63M
    {
2581
1.63M
      SetPixelViaPixelInfo(image,color,q);
2582
1.63M
      q+=(ptrdiff_t) GetPixelChannels(image);
2583
1.63M
    }
2584
8.77k
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2585
0
      status=MagickFalse;
2586
8.77k
  }
2587
521
  image_view=DestroyCacheView(image_view);
2588
521
  return(status);
2589
521
}
2590

2591
/*
2592
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2593
%                                                                             %
2594
%                                                                             %
2595
%                                                                             %
2596
%   S e t I m a g e S t o r a g e C l a s s                                   %
2597
%                                                                             %
2598
%                                                                             %
2599
%                                                                             %
2600
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2601
%
2602
%  SetImageStorageClass() sets the image class: DirectClass for true color
2603
%  images or PseudoClass for colormapped images.
2604
%
2605
%  The format of the SetImageStorageClass method is:
2606
%
2607
%      MagickBooleanType SetImageStorageClass(Image *image,
2608
%        const ClassType storage_class,ExceptionInfo *exception)
2609
%
2610
%  A description of each parameter follows:
2611
%
2612
%    o image: the image.
2613
%
2614
%    o storage_class:  The image class.
2615
%
2616
%    o exception: return any errors or warnings in this structure.
2617
%
2618
*/
2619
MagickExport MagickBooleanType SetImageStorageClass(Image *image,
2620
  const ClassType storage_class,ExceptionInfo *exception)
2621
833k
{
2622
833k
  assert(image != (Image *) NULL);
2623
833k
  assert(image->signature == MagickCoreSignature);
2624
833k
  assert(exception != (ExceptionInfo *) NULL);
2625
833k
  assert(exception->signature == MagickCoreSignature);
2626
833k
  if (IsEventLogging() != MagickFalse)
2627
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2628
833k
  image->storage_class=storage_class;
2629
833k
  return(SyncImagePixelCache(image,exception));
2630
833k
}
2631

2632
/*
2633
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2634
%                                                                             %
2635
%                                                                             %
2636
%                                                                             %
2637
%   S e t I m a g e E x t e n t                                               %
2638
%                                                                             %
2639
%                                                                             %
2640
%                                                                             %
2641
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2642
%
2643
%  SetImageExtent() sets the image size (i.e. columns & rows).
2644
%
2645
%  The format of the SetImageExtent method is:
2646
%
2647
%      MagickBooleanType SetImageExtent(Image *image,const size_t columns,
2648
%        const size_t rows,ExceptionInfo *exception)
2649
%
2650
%  A description of each parameter follows:
2651
%
2652
%    o image: the image.
2653
%
2654
%    o columns:  The image width in pixels.
2655
%
2656
%    o rows:  The image height in pixels.
2657
%
2658
%    o exception: return any errors or warnings in this structure.
2659
%
2660
*/
2661
MagickExport MagickBooleanType SetImageExtent(Image *image,const size_t columns,
2662
  const size_t rows,ExceptionInfo *exception)
2663
845k
{
2664
845k
  if ((columns == 0) || (rows == 0))
2665
838k
    ThrowBinaryException(ImageError,"NegativeOrZeroImageSize",image->filename);
2666
838k
  image->columns=columns;
2667
838k
  image->rows=rows;
2668
838k
  if (image->depth == 0)
2669
637
    {
2670
637
      image->depth=8;
2671
637
      (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2672
637
        "ImageDepthNotSupported","`%s'",image->filename);
2673
637
    }
2674
838k
  if (image->depth > (8*sizeof(MagickSizeType)))
2675
1.01k
    {
2676
1.01k
      image->depth=8*sizeof(MagickSizeType);
2677
1.01k
      (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2678
1.01k
        "ImageDepthNotSupported","`%s'",image->filename);
2679
1.01k
    }
2680
838k
  return(SyncImagePixelCache(image,exception));
2681
845k
}
2682

2683
/*
2684
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2685
%                                                                             %
2686
%                                                                             %
2687
%                                                                             %
2688
+   S e t I m a g e I n f o                                                   %
2689
%                                                                             %
2690
%                                                                             %
2691
%                                                                             %
2692
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2693
%
2694
%  SetImageInfo() initializes the 'magick' field of the ImageInfo structure.
2695
%  It is set to a type of image format based on the prefix or suffix of the
2696
%  filename.  For example, 'ps:image' returns PS indicating a Postscript image.
2697
%  JPEG is returned for this filename: 'image.jpg'.  The filename prefix has
2698
%  precedence over the suffix.  Use an optional index enclosed in brackets
2699
%  after a file name to specify a desired scene of a multi-resolution image
2700
%  format like Photo CD (e.g. img0001.pcd[4]).  A True (non-zero) return value
2701
%  indicates success.
2702
%
2703
%  The format of the SetImageInfo method is:
2704
%
2705
%      MagickBooleanType SetImageInfo(ImageInfo *image_info,
2706
%        const unsigned int frames,ExceptionInfo *exception)
2707
%
2708
%  A description of each parameter follows:
2709
%
2710
%    o image_info: the image info.
2711
%
2712
%    o frames: the number of images you intend to write.
2713
%
2714
%    o exception: return any errors or warnings in this structure.
2715
%
2716
*/
2717
2718
static const MagickInfo *SetImageInfoFromExtension(ImageInfo *image_info,
2719
  const char *component,char *magic,ExceptionInfo *exception)
2720
57.5k
{
2721
57.5k
  const MagickInfo
2722
57.5k
    *magick_info;
2723
2724
57.5k
  MagickFormatType
2725
57.5k
    format_type;
2726
2727
57.5k
  ssize_t
2728
57.5k
    i;
2729
2730
57.5k
  static const char
2731
57.5k
    *format_type_formats[] =
2732
57.5k
    {
2733
57.5k
      "AUTOTRACE",
2734
57.5k
      "BROWSE",
2735
57.5k
      "DCRAW",
2736
57.5k
      "EDIT",
2737
57.5k
      "LAUNCH",
2738
57.5k
      "MPEG:DECODE",
2739
57.5k
      "MPEG:ENCODE",
2740
57.5k
      "PRINT",
2741
57.5k
      "PS:ALPHA",
2742
57.5k
      "PS:CMYK",
2743
57.5k
      "PS:COLOR",
2744
57.5k
      "PS:GRAY",
2745
57.5k
      "PS:MONO",
2746
57.5k
      "SCAN",
2747
57.5k
      "SHOW",
2748
57.5k
      "WIN",
2749
57.5k
      (char *) NULL
2750
57.5k
    };
2751
2752
  /*
2753
    User specified image format.
2754
  */
2755
57.5k
  (void) CopyMagickString(magic,component,MagickPathExtent);
2756
57.5k
  LocaleUpper(magic);
2757
  /*
2758
    Look for explicit image formats.
2759
  */
2760
57.5k
  format_type=UndefinedFormatType;
2761
57.5k
  magick_info=GetMagickInfo(magic,exception);
2762
57.5k
  if ((magick_info != (const MagickInfo *) NULL) &&
2763
57.5k
      (magick_info->format_type != UndefinedFormatType))
2764
1.29k
    format_type=magick_info->format_type;
2765
57.5k
  i=0;
2766
957k
  while ((format_type == UndefinedFormatType) &&
2767
957k
         (format_type_formats[i] != (char *) NULL))
2768
900k
  {
2769
900k
    if ((*magic == *format_type_formats[i]) &&
2770
900k
        (LocaleCompare(magic,format_type_formats[i]) == 0))
2771
25
      format_type=ExplicitFormatType;
2772
900k
    i++;
2773
900k
  }
2774
57.5k
  if (format_type == UndefinedFormatType)
2775
56.2k
    (void) CopyMagickString(image_info->magick,magic,MagickPathExtent);
2776
1.31k
  else
2777
1.31k
    if (format_type == ExplicitFormatType)
2778
445
      {
2779
445
        image_info->affirm=MagickTrue;
2780
445
        (void) CopyMagickString(image_info->magick,magic,MagickPathExtent);
2781
445
      }
2782
57.5k
  if (LocaleCompare(magic,"RGB") == 0)
2783
17
    image_info->affirm=MagickFalse;  /* maybe SGI disguised as RGB */
2784
57.5k
  return(magick_info);
2785
57.5k
}
2786
2787
MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
2788
  const unsigned int frames,ExceptionInfo *exception)
2789
2.25M
{
2790
2.25M
  char
2791
2.25M
    component[MagickPathExtent],
2792
2.25M
    magic[MagickPathExtent],
2793
2.25M
    path[MagickPathExtent],
2794
2.25M
    *q;
2795
2796
2.25M
  const char
2797
2.25M
    *p;
2798
2799
2.25M
  const MagicInfo
2800
2.25M
    *magic_info;
2801
2802
2.25M
  const MagickInfo
2803
2.25M
    *magick_info;
2804
2805
2.25M
  ExceptionInfo
2806
2.25M
    *sans_exception;
2807
2808
2.25M
  Image
2809
2.25M
    *image;
2810
2811
2.25M
  MagickBooleanType
2812
2.25M
    status;
2813
2814
2.25M
  ssize_t
2815
2.25M
    count;
2816
2817
  /*
2818
    Look for 'image.format' in filename.
2819
  */
2820
2.25M
  assert(image_info != (ImageInfo *) NULL);
2821
2.25M
  assert(image_info->signature == MagickCoreSignature);
2822
2.25M
  if (IsEventLogging() != MagickFalse)
2823
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2824
0
      image_info->filename);
2825
2.25M
  *component='\0';
2826
2.25M
  GetPathComponent(image_info->filename,SubimagePath,component);
2827
2.25M
  if (*component != '\0')
2828
24.3k
    {
2829
      /*
2830
        Look for scene specification (e.g. img0001.pcd[4]).
2831
      */
2832
24.3k
      if (IsSceneGeometry(component,MagickFalse) == MagickFalse)
2833
20.6k
        {
2834
20.6k
          if (IsGeometry(component) != MagickFalse)
2835
20.6k
            (void) CloneString(&image_info->extract,component);
2836
20.6k
        }
2837
3.68k
      else
2838
3.68k
        {
2839
3.68k
          size_t
2840
3.68k
            first,
2841
3.68k
            last;
2842
2843
3.68k
          (void) CloneString(&image_info->scenes,component);
2844
3.68k
          image_info->scene=StringToUnsignedLong(image_info->scenes);
2845
3.68k
          image_info->number_scenes=image_info->scene;
2846
3.68k
          p=image_info->scenes;
2847
28.2k
          for (q=(char *) image_info->scenes; *q != '\0'; p++)
2848
24.6k
          {
2849
29.5k
            while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
2850
4.93k
              p++;
2851
24.6k
            first=(size_t) strtol(p,&q,10);
2852
24.6k
            last=first;
2853
28.8k
            while (isspace((int) ((unsigned char) *q)) != 0)
2854
4.28k
              q++;
2855
24.6k
            if (*q == '-')
2856
18.4k
              last=(size_t) strtol(q+1,&q,10);
2857
24.6k
            if (first > last)
2858
4.36k
              Swap(first,last);
2859
24.6k
            if (first < image_info->scene)
2860
3.03k
              image_info->scene=first;
2861
24.6k
            if (last > image_info->number_scenes)
2862
1.40k
              image_info->number_scenes=last;
2863
24.6k
            p=q;
2864
24.6k
          }
2865
3.68k
          image_info->number_scenes-=image_info->scene-1;
2866
3.68k
        }
2867
24.3k
    }
2868
2.25M
  *component='\0';
2869
2.25M
  if (*image_info->magick == '\0')
2870
973k
    GetPathComponent(image_info->filename,ExtensionPath,component);
2871
2.25M
  if (*component != '\0')
2872
72.7k
    {
2873
      /*
2874
        Base path sans any compression extension.
2875
      */
2876
72.7k
      GetPathComponent(image_info->filename,BasePathSansCompressExtension,path);
2877
72.7k
      GetPathComponent(path,ExtensionPath,component);
2878
72.7k
    }
2879
2.25M
  image_info->affirm=MagickFalse;
2880
2.25M
  sans_exception=AcquireExceptionInfo();
2881
2.25M
  if ((*component != '\0') && (IsGlob(component) == MagickFalse))
2882
56.1k
    magick_info=SetImageInfoFromExtension(image_info,component,magic,
2883
56.1k
      sans_exception);
2884
  /*
2885
    Look for explicit 'format:image' in filename.
2886
  */
2887
2.25M
  *magic='\0';
2888
2.25M
  GetPathComponent(image_info->filename,MagickPath,magic);
2889
2.25M
  if (*magic == '\0')
2890
326k
    {
2891
326k
      (void) CopyMagickString(magic,image_info->magick,MagickPathExtent);
2892
326k
      magick_info=GetMagickInfo(magic,sans_exception);
2893
326k
      if ((magick_info != (const MagickInfo *) NULL) &&
2894
326k
          (magick_info->format_type == ExplicitFormatType))
2895
528
        image_info->affirm=MagickTrue;
2896
326k
      if (frames == 0)
2897
96.3k
        GetPathComponent(image_info->filename,CanonicalPath,component);
2898
229k
      else
2899
229k
        GetPathComponent(image_info->filename,SubcanonicalPath,component);
2900
326k
      (void) CopyMagickString(image_info->filename,component,MagickPathExtent);
2901
326k
    }
2902
1.92M
  else
2903
1.92M
    {
2904
1.92M
      const DelegateInfo
2905
1.92M
        *delegate_info;
2906
2907
      /*
2908
        User specified image format.
2909
      */
2910
1.92M
      LocaleUpper(magic);
2911
1.92M
      magick_info=GetMagickInfo(magic,sans_exception);
2912
1.92M
      delegate_info=(const DelegateInfo *) NULL;
2913
1.92M
      if (magick_info == (const MagickInfo *) NULL)
2914
13.4k
        {
2915
13.4k
          delegate_info=GetDelegateInfo(magic,"*",sans_exception);
2916
13.4k
          if (delegate_info == (const DelegateInfo *) NULL)
2917
10.5k
            delegate_info=GetDelegateInfo("*",magic,sans_exception);
2918
13.4k
          if ((delegate_info == (const DelegateInfo *) NULL) &&
2919
13.4k
              ((*component != '\0') && (IsGlob(component) == MagickFalse)))
2920
1.44k
            {
2921
              /*
2922
                Retry in case GetMagickInfo loaded a custom module.
2923
              */
2924
1.44k
              magick_info=SetImageInfoFromExtension(image_info,component,magic,
2925
1.44k
                sans_exception);
2926
1.44k
            }
2927
13.4k
        }
2928
1.92M
      if (((magick_info != (const MagickInfo *) NULL) ||
2929
1.92M
           (delegate_info != (const DelegateInfo *) NULL)) &&
2930
1.92M
          (IsMagickConflict(magic) == MagickFalse))
2931
1.91M
        {
2932
1.91M
          image_info->affirm=MagickTrue;
2933
1.91M
          (void) CopyMagickString(image_info->magick,magic,MagickPathExtent);
2934
1.91M
          GetPathComponent(image_info->filename,CanonicalPath,component);
2935
1.91M
          (void) CopyMagickString(image_info->filename,component,
2936
1.91M
            MagickPathExtent);
2937
1.91M
        }
2938
1.92M
    }
2939
2.25M
  sans_exception=DestroyExceptionInfo(sans_exception);
2940
2.25M
  if ((magick_info == (const MagickInfo *) NULL) ||
2941
2.25M
      (GetMagickEndianSupport(magick_info) == MagickFalse))
2942
1.91M
    image_info->endian=UndefinedEndian;
2943
2.25M
  if ((image_info->adjoin != MagickFalse) && (frames > 1))
2944
0
    {
2945
      /*
2946
        Test for multiple image support (e.g. image%02d.png).
2947
      */
2948
0
      (void) InterpretImageFilename(image_info,(Image *) NULL,
2949
0
        image_info->filename,(int) image_info->scene,component,exception);
2950
0
      if ((LocaleCompare(component,image_info->filename) != 0) &&
2951
0
          (strchr(component,'%') == (char *) NULL))
2952
0
        image_info->adjoin=MagickFalse;
2953
0
    }
2954
2.25M
  if ((image_info->adjoin != MagickFalse) && (frames > 0))
2955
906k
    {
2956
      /*
2957
        Some image formats do not support multiple frames per file.
2958
      */
2959
906k
      magick_info=GetMagickInfo(magic,exception);
2960
906k
      if (magick_info != (const MagickInfo *) NULL)
2961
865k
        if (GetMagickAdjoin(magick_info) == MagickFalse)
2962
404k
          image_info->adjoin=MagickFalse;
2963
906k
    }
2964
2.25M
  if (image_info->affirm != MagickFalse)
2965
1.91M
    return(MagickTrue);
2966
335k
  if (frames == 0)
2967
104k
    {
2968
104k
      unsigned char
2969
104k
        *magick;
2970
2971
104k
      size_t
2972
104k
        magick_size;
2973
2974
      /*
2975
        Determine the image format from the first few bytes of the file.
2976
      */
2977
104k
      magick_size=GetMagicPatternExtent(exception);
2978
104k
      if (magick_size == 0)
2979
0
        return(MagickFalse);
2980
104k
      image=AcquireImage(image_info,exception);
2981
104k
      (void) CopyMagickString(image->filename,image_info->filename,
2982
104k
        MagickPathExtent);
2983
104k
      sans_exception=AcquireExceptionInfo();
2984
104k
      status=OpenBlob(image_info,image,ReadBinaryBlobMode,sans_exception);
2985
104k
      sans_exception=DestroyExceptionInfo(sans_exception);
2986
104k
      if (status == MagickFalse)
2987
12.4k
        {
2988
12.4k
          image=DestroyImage(image);
2989
12.4k
          return(MagickFalse);
2990
12.4k
        }
2991
91.8k
      if ((IsBlobSeekable(image) == MagickFalse) ||
2992
91.8k
          (IsBlobExempt(image) != MagickFalse))
2993
3.94k
        {
2994
          /*
2995
            Copy image to seekable temporary file.
2996
          */
2997
3.94k
          *component='\0';
2998
3.94k
          status=ImageToFile(image,component,exception);
2999
3.94k
          if (CloseBlob(image) == MagickFalse)
3000
0
            status=MagickFalse;
3001
3.94k
          if (status == MagickFalse)
3002
0
            {
3003
0
              (void) RelinquishUniqueFileResource(component);
3004
0
              image=DestroyImage(image);
3005
0
              return(MagickFalse);
3006
0
            }
3007
3.94k
          SetImageInfoFile(image_info,(FILE *) NULL);
3008
3.94k
          (void) CopyMagickString(image->filename,component,MagickPathExtent);
3009
3.94k
          status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3010
3.94k
          if (status == MagickFalse)
3011
0
            {
3012
0
              (void) RelinquishUniqueFileResource(component);
3013
0
              image=DestroyImage(image);
3014
0
              return(MagickFalse);
3015
0
            }
3016
3.94k
          (void) CopyMagickString(image_info->filename,component,
3017
3.94k
            MagickPathExtent);
3018
3.94k
          image_info->temporary=MagickTrue;
3019
3.94k
        }
3020
91.8k
      magick=(unsigned char *) AcquireQuantumMemory(1,magick_size);
3021
91.8k
      if (magick == (unsigned char *) NULL)
3022
0
        {
3023
0
          (void) CloseBlob(image);
3024
0
          image=DestroyImage(image);
3025
0
          return(MagickFalse);
3026
0
        }
3027
91.8k
      (void) memset(magick,0,magick_size);
3028
91.8k
      count=ReadBlob(image,magick_size,magick);
3029
91.8k
      (void) SeekBlob(image,-((MagickOffsetType) count),SEEK_CUR);
3030
91.8k
      (void) CloseBlob(image);
3031
91.8k
      image=DestroyImage(image);
3032
      /*
3033
        Check magic cache.
3034
      */
3035
91.8k
      sans_exception=AcquireExceptionInfo();
3036
91.8k
      magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
3037
91.8k
      magick=(unsigned char *) RelinquishMagickMemory(magick);
3038
91.8k
      if ((magic_info != (const MagicInfo *) NULL) &&
3039
91.8k
          (GetMagicName(magic_info) != (char *) NULL))
3040
74.3k
        {
3041
          /*
3042
            Try to use magick_info that was determined earlier by the extension
3043
          */
3044
74.3k
          if ((magick_info != (const MagickInfo *) NULL) &&
3045
74.3k
              (GetMagickUseExtension(magick_info) != MagickFalse) &&
3046
74.3k
              (LocaleCompare(magick_info->magick_module,GetMagicName(
3047
12.3k
                magic_info)) == 0))
3048
12.1k
            (void) CopyMagickString(image_info->magick,magick_info->name,
3049
12.1k
              MagickPathExtent);
3050
62.2k
          else
3051
62.2k
            {
3052
62.2k
              (void) CopyMagickString(image_info->magick,GetMagicName(
3053
62.2k
                magic_info),MagickPathExtent);
3054
62.2k
              magick_info=GetMagickInfo(image_info->magick,sans_exception);
3055
62.2k
            }
3056
74.3k
          if ((magick_info == (const MagickInfo *) NULL) ||
3057
74.3k
              (GetMagickEndianSupport(magick_info) == MagickFalse))
3058
64.6k
            image_info->endian=UndefinedEndian;
3059
74.3k
          sans_exception=DestroyExceptionInfo(sans_exception);
3060
74.3k
          return(MagickTrue);
3061
74.3k
        }
3062
17.4k
      magick_info=GetMagickInfo(image_info->magick,sans_exception);
3063
17.4k
      if ((magick_info == (const MagickInfo *) NULL) ||
3064
17.4k
          (GetMagickEndianSupport(magick_info) == MagickFalse))
3065
15.8k
        image_info->endian=UndefinedEndian;
3066
17.4k
      sans_exception=DestroyExceptionInfo(sans_exception);
3067
17.4k
    }
3068
248k
  return(MagickTrue);
3069
335k
}
3070

3071
/*
3072
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3073
%                                                                             %
3074
%                                                                             %
3075
%                                                                             %
3076
%   S e t I m a g e I n f o B l o b                                           %
3077
%                                                                             %
3078
%                                                                             %
3079
%                                                                             %
3080
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3081
%
3082
%  SetImageInfoBlob() sets the image info blob member.
3083
%
3084
%  The format of the SetImageInfoBlob method is:
3085
%
3086
%      void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3087
%        const size_t length)
3088
%
3089
%  A description of each parameter follows:
3090
%
3091
%    o image_info: the image info.
3092
%
3093
%    o blob: the blob.
3094
%
3095
%    o length: the blob length.
3096
%
3097
*/
3098
MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3099
  const size_t length)
3100
7.23M
{
3101
7.23M
  assert(image_info != (ImageInfo *) NULL);
3102
7.23M
  assert(image_info->signature == MagickCoreSignature);
3103
7.23M
  if (IsEventLogging() != MagickFalse)
3104
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3105
0
      image_info->filename);
3106
7.23M
  image_info->blob=(void *) blob;
3107
7.23M
  image_info->length=length;
3108
7.23M
}
3109

3110
/*
3111
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3112
%                                                                             %
3113
%                                                                             %
3114
%                                                                             %
3115
%   S e t I m a g e I n f o C u s t o m S t r e a m                           %
3116
%                                                                             %
3117
%                                                                             %
3118
%                                                                             %
3119
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3120
%
3121
%  SetImageInfoCustomStream() sets the image info custom stream handlers.
3122
%
3123
%  The format of the SetImageInfoCustomStream method is:
3124
%
3125
%      void SetImageInfoCustomStream(ImageInfo *image_info,
3126
%        CustomStreamInfo *custom_stream)
3127
%
3128
%  A description of each parameter follows:
3129
%
3130
%    o image_info: the image info.
3131
%
3132
%    o custom_stream: your custom stream methods.
3133
%
3134
*/
3135
MagickExport void SetImageInfoCustomStream(ImageInfo *image_info,
3136
  CustomStreamInfo *custom_stream)
3137
0
{
3138
0
  assert(image_info != (ImageInfo *) NULL);
3139
0
  assert(image_info->signature == MagickCoreSignature);
3140
0
  if (IsEventLogging() != MagickFalse)
3141
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3142
0
      image_info->filename);
3143
0
  image_info->custom_stream=(CustomStreamInfo *) custom_stream;
3144
0
}
3145

3146
/*
3147
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3148
%                                                                             %
3149
%                                                                             %
3150
%                                                                             %
3151
%   S e t I m a g e I n f o F i l e                                           %
3152
%                                                                             %
3153
%                                                                             %
3154
%                                                                             %
3155
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3156
%
3157
%  SetImageInfoFile() sets the image info file member.
3158
%
3159
%  The format of the SetImageInfoFile method is:
3160
%
3161
%      void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3162
%
3163
%  A description of each parameter follows:
3164
%
3165
%    o image_info: the image info.
3166
%
3167
%    o file: the file.
3168
%
3169
*/
3170
MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3171
7.17M
{
3172
7.17M
  assert(image_info != (ImageInfo *) NULL);
3173
7.17M
  assert(image_info->signature == MagickCoreSignature);
3174
7.17M
  if (IsEventLogging() != MagickFalse)
3175
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3176
0
      image_info->filename);
3177
7.17M
  image_info->file=file;
3178
7.17M
}
3179

3180
/*
3181
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3182
%                                                                             %
3183
%                                                                             %
3184
%                                                                             %
3185
%   S e t I m a g e M a s k                                                   %
3186
%                                                                             %
3187
%                                                                             %
3188
%                                                                             %
3189
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3190
%
3191
%  SetImageMask() associates a mask with the image.  The mask must be the same
3192
%  dimensions as the image.
3193
%
3194
%  The format of the SetImageMask method is:
3195
%
3196
%      MagickBooleanType SetImageMask(Image *image,const PixelMask type,
3197
%        const Image *mask,ExceptionInfo *exception)
3198
%
3199
%  A description of each parameter follows:
3200
%
3201
%    o image: the image.
3202
%
3203
%    o type: the mask type, ReadPixelMask or WritePixelMask.
3204
%
3205
%    o mask: the image mask.
3206
%
3207
%    o exception: return any errors or warnings in this structure.
3208
%
3209
*/
3210
MagickExport MagickBooleanType SetImageMask(Image *image,const PixelMask type,
3211
  const Image *mask,ExceptionInfo *exception)
3212
337k
{
3213
337k
  CacheView
3214
337k
    *mask_view,
3215
337k
    *image_view;
3216
3217
337k
  MagickBooleanType
3218
337k
    status;
3219
3220
337k
  ssize_t
3221
337k
    y;
3222
3223
  /*
3224
    Set image mask.
3225
  */
3226
337k
  assert(image != (Image *) NULL);
3227
337k
  if (IsEventLogging() != MagickFalse)
3228
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3229
337k
  assert(image->signature == MagickCoreSignature);
3230
337k
  if (mask == (const Image *) NULL)
3231
171k
    {
3232
171k
      switch (type)
3233
171k
      {
3234
0
        case ReadPixelMask:
3235
0
        {
3236
0
          image->channels=(ChannelType) ((unsigned int) image->channels &
3237
0
            (unsigned int) ~ReadMaskChannel);
3238
0
          break;
3239
0
        }
3240
9.67k
        case WritePixelMask:
3241
9.67k
        {
3242
9.67k
          image->channels=(ChannelType) ((unsigned int) image->channels &
3243
9.67k
            (unsigned int) ~WriteMaskChannel);
3244
9.67k
          magick_fallthrough;
3245
9.67k
        }
3246
171k
        default:
3247
171k
        {
3248
171k
          image->channels=(ChannelType) ((unsigned int) image->channels &
3249
171k
            (unsigned int) ~CompositeMaskChannel);
3250
171k
          break;
3251
9.67k
        }
3252
171k
      }
3253
171k
      return(SyncImagePixelCache(image,exception));
3254
171k
    }
3255
165k
  switch (type)
3256
165k
  {
3257
0
    case ReadPixelMask:
3258
0
    {
3259
0
      image->channels=(ChannelType) (image->channels | ReadMaskChannel);
3260
0
      break;
3261
0
    }
3262
2.94k
    case WritePixelMask:
3263
2.94k
    {
3264
2.94k
      image->channels=(ChannelType) (image->channels | WriteMaskChannel);
3265
2.94k
      break;
3266
0
    }
3267
162k
    default:
3268
162k
    {
3269
162k
      image->channels=(ChannelType) (image->channels | CompositeMaskChannel);
3270
162k
      break;
3271
0
    }
3272
165k
  }
3273
165k
  if (SyncImagePixelCache(image,exception) == MagickFalse)
3274
0
    return(MagickFalse);
3275
165k
  status=MagickTrue;
3276
165k
  image->mask_trait=UpdatePixelTrait;
3277
165k
  mask_view=AcquireVirtualCacheView(mask,exception);
3278
165k
  image_view=AcquireAuthenticCacheView(image,exception);
3279
#if defined(MAGICKCORE_OPENMP_SUPPORT)
3280
  #pragma omp parallel for schedule(static) shared(status) \
3281
    magick_number_threads(mask,image,image->rows,2)
3282
#endif
3283
4.05M
  for (y=0; y < (ssize_t) image->rows; y++)
3284
3.89M
  {
3285
3.89M
    const Quantum
3286
3.89M
      *magick_restrict p;
3287
3288
3.89M
    Quantum
3289
3.89M
      *magick_restrict q;
3290
3291
3.89M
    ssize_t
3292
3.89M
      x;
3293
3294
3.89M
    if (status == MagickFalse)
3295
0
      continue;
3296
3.89M
    p=GetCacheViewVirtualPixels(mask_view,0,y,mask->columns,1,exception);
3297
3.89M
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3298
3.89M
    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
3299
0
      {
3300
0
        status=MagickFalse;
3301
0
        continue;
3302
0
      }
3303
212M
    for (x=0; x < (ssize_t) image->columns; x++)
3304
208M
    {
3305
208M
      MagickRealType
3306
208M
        intensity;
3307
3308
208M
      intensity=0.0;
3309
208M
      if ((x < (ssize_t) mask->columns) && (y < (ssize_t) mask->rows))
3310
208M
        intensity=GetPixelIntensity(mask,p);
3311
208M
      switch (type)
3312
208M
      {
3313
0
        case ReadPixelMask:
3314
0
        {
3315
0
          SetPixelReadMask(image,ClampToQuantum(intensity),q);
3316
0
          break;
3317
0
        }
3318
988k
        case WritePixelMask:
3319
988k
        {
3320
988k
          SetPixelWriteMask(image,ClampToQuantum(intensity),q);
3321
988k
          break;
3322
0
        }
3323
207M
        default:
3324
207M
        {
3325
207M
          SetPixelCompositeMask(image,ClampToQuantum(intensity),q);
3326
207M
          break;
3327
0
        }
3328
208M
      }
3329
208M
      p+=(ptrdiff_t) GetPixelChannels(mask);
3330
208M
      q+=(ptrdiff_t) GetPixelChannels(image);
3331
208M
    }
3332
3.89M
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3333
0
      status=MagickFalse;
3334
3.89M
  }
3335
165k
  image->mask_trait=UndefinedPixelTrait;
3336
165k
  mask_view=DestroyCacheView(mask_view);
3337
165k
  image_view=DestroyCacheView(image_view);
3338
165k
  return(status);
3339
165k
}
3340

3341
/*
3342
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3343
%                                                                             %
3344
%                                                                             %
3345
%                                                                             %
3346
%   S e t I m a g e R e g i o n M a s k                                       %
3347
%                                                                             %
3348
%                                                                             %
3349
%                                                                             %
3350
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3351
%
3352
%  SetImageRegionMask() associates a mask with the image as defined by the
3353
%  specified region.
3354
%
3355
%  The format of the SetImageRegionMask method is:
3356
%
3357
%      MagickBooleanType SetImageRegionMask(Image *image,const PixelMask type,
3358
%        const RectangleInfo *region,ExceptionInfo *exception)
3359
%
3360
%  A description of each parameter follows:
3361
%
3362
%    o image: the image.
3363
%
3364
%    o type: the mask type, ReadPixelMask or WritePixelMask.
3365
%
3366
%    o geometry: the mask region.
3367
%
3368
%    o exception: return any errors or warnings in this structure.
3369
%
3370
*/
3371
MagickExport MagickBooleanType SetImageRegionMask(Image *image,
3372
  const PixelMask type,const RectangleInfo *region,ExceptionInfo *exception)
3373
0
{
3374
0
  CacheView
3375
0
    *image_view;
3376
3377
0
  MagickBooleanType
3378
0
    status;
3379
3380
0
  ssize_t
3381
0
    y;
3382
3383
  /*
3384
    Set image mask as defined by the region.
3385
  */
3386
0
  assert(image != (Image *) NULL);
3387
0
  assert(image->signature == MagickCoreSignature);
3388
0
  if (IsEventLogging() != MagickFalse)
3389
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3390
0
  if (region == (const RectangleInfo *) NULL)
3391
0
    {
3392
0
      switch (type)
3393
0
      {
3394
0
        case ReadPixelMask:
3395
0
        {
3396
0
          image->channels=(ChannelType) ((unsigned int) image->channels &
3397
0
            (unsigned int) ~ReadMaskChannel);
3398
0
          break;
3399
0
        }
3400
0
        case WritePixelMask:
3401
0
        {
3402
0
          image->channels=(ChannelType) ((unsigned int) image->channels &
3403
0
            (unsigned int) ~WriteMaskChannel);
3404
0
          break;
3405
0
        }
3406
0
        default:
3407
0
        {
3408
0
          image->channels=(ChannelType) ((unsigned int) image->channels &
3409
0
            (unsigned int) ~CompositeMaskChannel);
3410
0
          break;
3411
0
        }
3412
0
      }
3413
0
      return(SyncImagePixelCache(image,exception));
3414
0
    }
3415
0
  switch (type)
3416
0
  {
3417
0
    case ReadPixelMask:
3418
0
    {
3419
0
      image->channels=(ChannelType) (image->channels | ReadMaskChannel);
3420
0
      break;
3421
0
    }
3422
0
    case WritePixelMask:
3423
0
    {
3424
0
      image->channels=(ChannelType) (image->channels | WriteMaskChannel);
3425
0
      break;
3426
0
    }
3427
0
    default:
3428
0
    {
3429
0
      image->channels=(ChannelType) (image->channels | CompositeMaskChannel);
3430
0
      break;
3431
0
    }
3432
0
  }
3433
0
  if (SyncImagePixelCache(image,exception) == MagickFalse)
3434
0
    return(MagickFalse);
3435
0
  status=MagickTrue;
3436
0
  image->mask_trait=UpdatePixelTrait;
3437
0
  image_view=AcquireAuthenticCacheView(image,exception);
3438
#if defined(MAGICKCORE_OPENMP_SUPPORT)
3439
  #pragma omp parallel for schedule(static) shared(status) \
3440
    magick_number_threads(image,image,image->rows,2)
3441
#endif
3442
0
  for (y=0; y < (ssize_t) image->rows; y++)
3443
0
  {
3444
0
    Quantum
3445
0
      *magick_restrict q;
3446
3447
0
    ssize_t
3448
0
      x;
3449
3450
0
    if (status == MagickFalse)
3451
0
      continue;
3452
0
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3453
0
    if (q == (Quantum *) NULL)
3454
0
      {
3455
0
        status=MagickFalse;
3456
0
        continue;
3457
0
      }
3458
0
    for (x=0; x < (ssize_t) image->columns; x++)
3459
0
    {
3460
0
      Quantum
3461
0
        pixel;
3462
3463
0
      pixel=QuantumRange;
3464
0
      if (((x >= region->x) && (x < (region->x+(ssize_t) region->width))) &&
3465
0
          ((y >= region->y) && (y < (region->y+(ssize_t) region->height))))
3466
0
        pixel=(Quantum) 0;
3467
0
      switch (type)
3468
0
      {
3469
0
        case ReadPixelMask:
3470
0
        {
3471
0
          SetPixelReadMask(image,pixel,q);
3472
0
          break;
3473
0
        }
3474
0
        case WritePixelMask:
3475
0
        {
3476
0
          SetPixelWriteMask(image,pixel,q);
3477
0
          break;
3478
0
        }
3479
0
        default:
3480
0
        {
3481
0
          SetPixelCompositeMask(image,pixel,q);
3482
0
          break;
3483
0
        }
3484
0
      }
3485
0
      q+=(ptrdiff_t) GetPixelChannels(image);
3486
0
    }
3487
0
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3488
0
      status=MagickFalse;
3489
0
  }
3490
0
  image->mask_trait=UndefinedPixelTrait;
3491
0
  image_view=DestroyCacheView(image_view);
3492
0
  return(status);
3493
0
}
3494

3495
/*
3496
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3497
%                                                                             %
3498
%                                                                             %
3499
%                                                                             %
3500
%   S e t I m a g e V i r t u a l P i x e l M e t h o d                       %
3501
%                                                                             %
3502
%                                                                             %
3503
%                                                                             %
3504
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3505
%
3506
%  SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
3507
%  image and returns the previous setting.  A virtual pixel is any pixel access
3508
%  that is outside the boundaries of the image cache.
3509
%
3510
%  The format of the SetImageVirtualPixelMethod() method is:
3511
%
3512
%      VirtualPixelMethod SetImageVirtualPixelMethod(Image *image,
3513
%        const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
3514
%
3515
%  A description of each parameter follows:
3516
%
3517
%    o image: the image.
3518
%
3519
%    o virtual_pixel_method: choose the type of virtual pixel.
3520
%
3521
%    o exception: return any errors or warnings in this structure.
3522
%
3523
*/
3524
MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(Image *image,
3525
  const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
3526
1.46k
{
3527
1.46k
  assert(image != (const Image *) NULL);
3528
1.46k
  assert(image->signature == MagickCoreSignature);
3529
1.46k
  if (IsEventLogging() != MagickFalse)
3530
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3531
1.46k
  return(SetPixelCacheVirtualMethod(image,virtual_pixel_method,exception));
3532
1.46k
}
3533

3534
/*
3535
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3536
%                                                                             %
3537
%                                                                             %
3538
%                                                                             %
3539
%     S m u s h I m a g e s                                                   %
3540
%                                                                             %
3541
%                                                                             %
3542
%                                                                             %
3543
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3544
%
3545
%  SmushImages() takes all images from the current image pointer to the end
3546
%  of the image list and smushes them to each other top-to-bottom if the
3547
%  stack parameter is true, otherwise left-to-right.
3548
%
3549
%  The current gravity setting now effects how the image is justified in the
3550
%  final image.
3551
%
3552
%  The format of the SmushImages method is:
3553
%
3554
%      Image *SmushImages(const Image *images,const MagickBooleanType stack,
3555
%        ExceptionInfo *exception)
3556
%
3557
%  A description of each parameter follows:
3558
%
3559
%    o images: the image sequence.
3560
%
3561
%    o stack: A value other than 0 stacks the images top-to-bottom.
3562
%
3563
%    o offset: minimum distance in pixels between images.
3564
%
3565
%    o exception: return any errors or warnings in this structure.
3566
%
3567
*/
3568
3569
static ssize_t SmushXGap(const Image *smush_image,const Image *images,
3570
  const ssize_t offset,ExceptionInfo *exception)
3571
0
{
3572
0
  CacheView
3573
0
    *left_view,
3574
0
    *right_view;
3575
3576
0
  const Image
3577
0
    *left_image,
3578
0
    *right_image;
3579
3580
0
  RectangleInfo
3581
0
    left_geometry,
3582
0
    right_geometry;
3583
3584
0
  const Quantum
3585
0
    *p;
3586
3587
0
  ssize_t
3588
0
    i,
3589
0
    y;
3590
3591
0
  size_t
3592
0
    gap;
3593
3594
0
  ssize_t
3595
0
    x;
3596
3597
0
  if (images->previous == (Image *) NULL)
3598
0
    return(0);
3599
0
  right_image=images;
3600
0
  SetGeometry(smush_image,&right_geometry);
3601
0
  GravityAdjustGeometry(right_image->columns,right_image->rows,
3602
0
    right_image->gravity,&right_geometry);
3603
0
  left_image=images->previous;
3604
0
  SetGeometry(smush_image,&left_geometry);
3605
0
  GravityAdjustGeometry(left_image->columns,left_image->rows,
3606
0
    left_image->gravity,&left_geometry);
3607
0
  gap=right_image->columns;
3608
0
  left_view=AcquireVirtualCacheView(left_image,exception);
3609
0
  right_view=AcquireVirtualCacheView(right_image,exception);
3610
0
  for (y=0; y < (ssize_t) smush_image->rows; y++)
3611
0
  {
3612
0
    for (x=(ssize_t) left_image->columns-1; x > 0; x--)
3613
0
    {
3614
0
      p=GetCacheViewVirtualPixels(left_view,x,left_geometry.y+y,1,1,exception);
3615
0
      if ((p == (const Quantum *) NULL) ||
3616
0
          (GetPixelAlpha(left_image,p) != TransparentAlpha) ||
3617
0
          (((ssize_t) left_image->columns-x-1) >= (ssize_t) gap))
3618
0
        break;
3619
0
    }
3620
0
    i=(ssize_t) left_image->columns-x-1;
3621
0
    for (x=0; x < (ssize_t) right_image->columns; x++)
3622
0
    {
3623
0
      p=GetCacheViewVirtualPixels(right_view,x,right_geometry.y+y,1,1,
3624
0
        exception);
3625
0
      if ((p == (const Quantum *) NULL) ||
3626
0
          (GetPixelAlpha(right_image,p) != TransparentAlpha) ||
3627
0
          ((x+i) >= (ssize_t) gap))
3628
0
        break;
3629
0
    }
3630
0
    if ((x+i) < (ssize_t) gap)
3631
0
      gap=(size_t) (x+i);
3632
0
  }
3633
0
  right_view=DestroyCacheView(right_view);
3634
0
  left_view=DestroyCacheView(left_view);
3635
0
  if (y < (ssize_t) smush_image->rows)
3636
0
    return(offset);
3637
0
  return((ssize_t) gap-offset);
3638
0
}
3639
3640
static ssize_t SmushYGap(const Image *smush_image,const Image *images,
3641
  const ssize_t offset,ExceptionInfo *exception)
3642
0
{
3643
0
  CacheView
3644
0
    *bottom_view,
3645
0
    *top_view;
3646
3647
0
  const Image
3648
0
    *bottom_image,
3649
0
    *top_image;
3650
3651
0
  RectangleInfo
3652
0
    bottom_geometry,
3653
0
    top_geometry;
3654
3655
0
  const Quantum
3656
0
    *p;
3657
3658
0
  ssize_t
3659
0
    i,
3660
0
    x;
3661
3662
0
  size_t
3663
0
    gap;
3664
3665
0
  ssize_t
3666
0
    y;
3667
3668
0
  if (images->previous == (Image *) NULL)
3669
0
    return(0);
3670
0
  bottom_image=images;
3671
0
  SetGeometry(smush_image,&bottom_geometry);
3672
0
  GravityAdjustGeometry(bottom_image->columns,bottom_image->rows,
3673
0
    bottom_image->gravity,&bottom_geometry);
3674
0
  top_image=images->previous;
3675
0
  SetGeometry(smush_image,&top_geometry);
3676
0
  GravityAdjustGeometry(top_image->columns,top_image->rows,top_image->gravity,
3677
0
    &top_geometry);
3678
0
  gap=bottom_image->rows;
3679
0
  top_view=AcquireVirtualCacheView(top_image,exception);
3680
0
  bottom_view=AcquireVirtualCacheView(bottom_image,exception);
3681
0
  for (x=0; x < (ssize_t) smush_image->columns; x++)
3682
0
  {
3683
0
    for (y=(ssize_t) top_image->rows-1; y > 0; y--)
3684
0
    {
3685
0
      p=GetCacheViewVirtualPixels(top_view,top_geometry.x+x,y,1,1,exception);
3686
0
      if ((p == (const Quantum *) NULL) ||
3687
0
          (GetPixelAlpha(top_image,p) != TransparentAlpha) ||
3688
0
          (((ssize_t) top_image->rows-y-1) >= (ssize_t) gap))
3689
0
        break;
3690
0
    }
3691
0
    i=(ssize_t) top_image->rows-y-1;
3692
0
    for (y=0; y < (ssize_t) bottom_image->rows; y++)
3693
0
    {
3694
0
      p=GetCacheViewVirtualPixels(bottom_view,bottom_geometry.x+x,y,1,1,
3695
0
        exception);
3696
0
      if ((p == (const Quantum *) NULL) ||
3697
0
          (GetPixelAlpha(bottom_image,p) != TransparentAlpha) ||
3698
0
          ((y+i) >= (ssize_t) gap))
3699
0
        break;
3700
0
    }
3701
0
    if ((y+i) < (ssize_t) gap)
3702
0
      gap=(size_t) (y+i);
3703
0
  }
3704
0
  bottom_view=DestroyCacheView(bottom_view);
3705
0
  top_view=DestroyCacheView(top_view);
3706
0
  if (x < (ssize_t) smush_image->columns)
3707
0
    return(offset);
3708
0
  return((ssize_t) gap-offset);
3709
0
}
3710
3711
MagickExport Image *SmushImages(const Image *images,
3712
  const MagickBooleanType stack,const ssize_t offset,ExceptionInfo *exception)
3713
0
{
3714
0
#define SmushImageTag  "Smush/Image"
3715
3716
0
  const Image
3717
0
    *image;
3718
3719
0
  Image
3720
0
    *smush_image;
3721
3722
0
  MagickBooleanType
3723
0
    proceed,
3724
0
    status;
3725
3726
0
  MagickOffsetType
3727
0
    n;
3728
3729
0
  PixelTrait
3730
0
    alpha_trait;
3731
3732
0
  RectangleInfo
3733
0
    geometry;
3734
3735
0
  const Image
3736
0
    *next;
3737
3738
0
  size_t
3739
0
    height,
3740
0
    number_images,
3741
0
    width;
3742
3743
0
  ssize_t
3744
0
    x_offset,
3745
0
    y_offset;
3746
3747
  /*
3748
    Compute maximum area of smushed area.
3749
  */
3750
0
  assert(images != (Image *) NULL);
3751
0
  assert(images->signature == MagickCoreSignature);
3752
0
  assert(exception != (ExceptionInfo *) NULL);
3753
0
  assert(exception->signature == MagickCoreSignature);
3754
0
  if (IsEventLogging() != MagickFalse)
3755
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3756
0
  image=images;
3757
0
  alpha_trait=image->alpha_trait;
3758
0
  number_images=1;
3759
0
  width=image->columns;
3760
0
  height=image->rows;
3761
0
  next=GetNextImageInList(image);
3762
0
  for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
3763
0
  {
3764
0
    if (next->alpha_trait != UndefinedPixelTrait)
3765
0
      alpha_trait=BlendPixelTrait;
3766
0
    number_images++;
3767
0
    if (stack != MagickFalse)
3768
0
      {
3769
0
        if (next->columns > width)
3770
0
          width=next->columns;
3771
0
        height+=next->rows;
3772
0
        if (next->previous != (Image *) NULL)
3773
0
          height=(size_t) MagickMax((ssize_t) height+offset,0U);
3774
0
        continue;
3775
0
      }
3776
0
    width+=next->columns;
3777
0
    if (next->previous != (Image *) NULL)
3778
0
      width=(size_t) MagickMax((ssize_t) width+offset,0U);
3779
0
    if (next->rows > height)
3780
0
      height=next->rows;
3781
0
  }
3782
  /*
3783
    Smush images.
3784
  */
3785
0
  smush_image=CloneImage(image,width,height,MagickTrue,exception);
3786
0
  if (smush_image == (Image *) NULL)
3787
0
    return((Image *) NULL);
3788
0
  if (SetImageStorageClass(smush_image,DirectClass,exception) == MagickFalse)
3789
0
    {
3790
0
      smush_image=DestroyImage(smush_image);
3791
0
      return((Image *) NULL);
3792
0
    }
3793
0
  smush_image->alpha_trait=alpha_trait;
3794
0
  (void) SetImageBackgroundColor(smush_image,exception);
3795
0
  status=MagickTrue;
3796
0
  x_offset=0;
3797
0
  y_offset=0;
3798
0
  for (n=0; n < (MagickOffsetType) number_images; n++)
3799
0
  {
3800
0
    SetGeometry(smush_image,&geometry);
3801
0
    GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry);
3802
0
    if (stack != MagickFalse)
3803
0
      {
3804
0
        x_offset-=geometry.x;
3805
0
        y_offset-=SmushYGap(smush_image,image,offset,exception);
3806
0
      }
3807
0
    else
3808
0
      {
3809
0
        x_offset-=SmushXGap(smush_image,image,offset,exception);
3810
0
        y_offset-=geometry.y;
3811
0
      }
3812
0
    status=CompositeImage(smush_image,image,OverCompositeOp,MagickTrue,x_offset,
3813
0
      y_offset,exception);
3814
0
    proceed=SetImageProgress(image,SmushImageTag,n,number_images);
3815
0
    if (proceed == MagickFalse)
3816
0
      break;
3817
0
    if (stack == MagickFalse)
3818
0
      {
3819
0
        x_offset+=(ssize_t) image->columns;
3820
0
        y_offset=0;
3821
0
      }
3822
0
    else
3823
0
      {
3824
0
        x_offset=0;
3825
0
        y_offset+=(ssize_t) image->rows;
3826
0
      }
3827
0
    image=GetNextImageInList(image);
3828
0
  }
3829
0
  if (stack == MagickFalse)
3830
0
    smush_image->columns=(size_t) x_offset;
3831
0
  else
3832
0
    smush_image->rows=(size_t) y_offset;
3833
0
  if (status == MagickFalse)
3834
0
    smush_image=DestroyImage(smush_image);
3835
0
  return(smush_image);
3836
0
}
3837

3838
/*
3839
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3840
%                                                                             %
3841
%                                                                             %
3842
%                                                                             %
3843
%   S t r i p I m a g e                                                       %
3844
%                                                                             %
3845
%                                                                             %
3846
%                                                                             %
3847
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3848
%
3849
%  StripImage() strips an image of all profiles and comments.
3850
%
3851
%  The format of the StripImage method is:
3852
%
3853
%      MagickBooleanType StripImage(Image *image,ExceptionInfo *exception)
3854
%
3855
%  A description of each parameter follows:
3856
%
3857
%    o image: the image.
3858
%
3859
%    o exception: return any errors or warnings in this structure.
3860
%
3861
*/
3862
MagickExport MagickBooleanType StripImage(Image *image,
3863
  ExceptionInfo *magick_unused(exception))
3864
0
{
3865
0
  MagickBooleanType
3866
0
    status;
3867
3868
0
  magick_unreferenced(exception);
3869
0
  assert(image != (Image *) NULL);
3870
0
  if (IsEventLogging() != MagickFalse)
3871
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3872
0
  DestroyImageProfiles(image);
3873
0
  (void) DeleteImageProperty(image,"comment");
3874
0
  (void) DeleteImageProperty(image,"date:create");
3875
0
  (void) DeleteImageProperty(image,"date:modify");
3876
0
  (void) DeleteImageProperty(image,"date:timestamp");
3877
0
  status=SetImageArtifact(image,"png:exclude-chunk",
3878
0
    "bKGD,caNv,cHRM,eXIf,gAMA,iCCP,iTXt,pHYs,sRGB,tEXt,zCCP,zTXt,date");
3879
0
  return(status);
3880
0
}
3881

3882
/*
3883
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3884
%                                                                             %
3885
%                                                                             %
3886
%                                                                             %
3887
+   S y n c I m a g e                                                         %
3888
%                                                                             %
3889
%                                                                             %
3890
%                                                                             %
3891
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3892
%
3893
%  SyncImage() initializes the red, green, and blue intensities of each pixel
3894
%  as defined by the colormap index.
3895
%
3896
%  The format of the SyncImage method is:
3897
%
3898
%      MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception)
3899
%
3900
%  A description of each parameter follows:
3901
%
3902
%    o image: the image.
3903
%
3904
%    o exception: return any errors or warnings in this structure.
3905
%
3906
*/
3907
3908
static inline Quantum PushColormapIndex(Image *image,const Quantum index,
3909
  MagickBooleanType *range_exception)
3910
911M
{
3911
911M
  if ((size_t) index < image->colors)
3912
819M
    return(index);
3913
91.2M
  *range_exception=MagickTrue;
3914
91.2M
  return((Quantum) 0);
3915
911M
}
3916
3917
MagickExport MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception)
3918
23.7k
{
3919
23.7k
  CacheView
3920
23.7k
    *image_view;
3921
3922
23.7k
  MagickBooleanType
3923
23.7k
    range_exception,
3924
23.7k
    status,
3925
23.7k
    taint;
3926
3927
23.7k
  ssize_t
3928
23.7k
    y;
3929
3930
23.7k
  assert(image != (Image *) NULL);
3931
23.7k
  assert(image->signature == MagickCoreSignature);
3932
23.7k
  if (IsEventLogging() != MagickFalse)
3933
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3934
23.7k
  if (image->ping != MagickFalse)
3935
441
    return(MagickTrue);
3936
23.2k
  if (image->storage_class != PseudoClass)
3937
952
    return(MagickFalse);
3938
22.3k
  assert(image->colormap != (PixelInfo *) NULL);
3939
22.3k
  range_exception=MagickFalse;
3940
22.3k
  status=MagickTrue;
3941
22.3k
  taint=image->taint;
3942
22.3k
  image_view=AcquireAuthenticCacheView(image,exception);
3943
#if defined(MAGICKCORE_OPENMP_SUPPORT)
3944
  #pragma omp parallel for schedule(static) shared(range_exception,status) \
3945
    magick_number_threads(image,image,image->rows,2)
3946
#endif
3947
2.14M
  for (y=0; y < (ssize_t) image->rows; y++)
3948
2.12M
  {
3949
2.12M
    Quantum
3950
2.12M
      index;
3951
3952
2.12M
    Quantum
3953
2.12M
      *magick_restrict q;
3954
3955
2.12M
    ssize_t
3956
2.12M
      x;
3957
3958
2.12M
    if (status == MagickFalse)
3959
0
      continue;
3960
2.12M
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3961
2.12M
    if (q == (Quantum *) NULL)
3962
0
      {
3963
0
        status=MagickFalse;
3964
0
        continue;
3965
0
      }
3966
913M
    for (x=0; x < (ssize_t) image->columns; x++)
3967
911M
    {
3968
911M
      index=PushColormapIndex(image,GetPixelIndex(image,q),&range_exception);
3969
911M
      SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
3970
911M
      q+=(ptrdiff_t) GetPixelChannels(image);
3971
911M
    }
3972
2.12M
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3973
0
      status=MagickFalse;
3974
2.12M
  }
3975
22.3k
  image_view=DestroyCacheView(image_view);
3976
22.3k
  image->taint=taint;
3977
22.3k
  if ((image->ping == MagickFalse) && (range_exception != MagickFalse))
3978
3.37k
    (void) ThrowMagickException(exception,GetMagickModule(),
3979
3.37k
      CorruptImageWarning,"InvalidColormapIndex","`%s'",image->filename);
3980
22.3k
  return(status);
3981
22.3k
}
3982

3983
/*
3984
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3985
%                                                                             %
3986
%                                                                             %
3987
%                                                                             %
3988
%   S y n c I m a g e S e t t i n g s                                         %
3989
%                                                                             %
3990
%                                                                             %
3991
%                                                                             %
3992
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3993
%
3994
%  SyncImageSettings() syncs any image_info global options into per-image
3995
%  attributes.
3996
%
3997
%  Note: in IMv6 free form 'options' were always mapped into 'artifacts', so
3998
%  that operations and coders can find such settings.  In IMv7 if a desired
3999
%  per-image artifact is not set, then it will directly look for a global
4000
%  option as a fallback, as such this copy is no longer needed, only the
4001
%  link set up.
4002
%
4003
%  The format of the SyncImageSettings method is:
4004
%
4005
%      MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
4006
%        Image *image,ExceptionInfo *exception)
4007
%      MagickBooleanType SyncImagesSettings(const ImageInfo *image_info,
4008
%        Image *image,ExceptionInfo *exception)
4009
%
4010
%  A description of each parameter follows:
4011
%
4012
%    o image_info: the image info.
4013
%
4014
%    o image: the image.
4015
%
4016
%    o exception: return any errors or warnings in this structure.
4017
%
4018
*/
4019
4020
MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info,
4021
  Image *images,ExceptionInfo *exception)
4022
0
{
4023
0
  Image
4024
0
    *image;
4025
4026
0
  assert(image_info != (const ImageInfo *) NULL);
4027
0
  assert(image_info->signature == MagickCoreSignature);
4028
0
  assert(images != (Image *) NULL);
4029
0
  assert(images->signature == MagickCoreSignature);
4030
0
  if (IsEventLogging() != MagickFalse)
4031
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
4032
0
  image=images;
4033
0
  for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
4034
0
    (void) SyncImageSettings(image_info,image,exception);
4035
0
  (void) DeleteImageOption(image_info,"page");
4036
0
  return(MagickTrue);
4037
0
}
4038
4039
MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
4040
  Image *image,ExceptionInfo *exception)
4041
3.35M
{
4042
3.35M
  const char
4043
3.35M
    *option;
4044
4045
3.35M
  GeometryInfo
4046
3.35M
    geometry_info;
4047
4048
3.35M
  MagickStatusType
4049
3.35M
    flags;
4050
4051
3.35M
  ResolutionType
4052
3.35M
    units;
4053
4054
  /*
4055
    Sync image options.
4056
  */
4057
3.35M
  assert(image_info != (const ImageInfo *) NULL);
4058
3.35M
  assert(image_info->signature == MagickCoreSignature);
4059
3.35M
  assert(image != (Image *) NULL);
4060
3.35M
  assert(image->signature == MagickCoreSignature);
4061
3.35M
  if (IsEventLogging() != MagickFalse)
4062
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4063
3.35M
  option=GetImageOption(image_info,"background");
4064
3.35M
  if (option != (const char *) NULL)
4065
0
    (void) QueryColorCompliance(option,AllCompliance,&image->background_color,
4066
0
      exception);
4067
3.35M
  option=GetImageOption(image_info,"black-point-compensation");
4068
3.35M
  if (option != (const char *) NULL)
4069
0
    image->black_point_compensation=(MagickBooleanType) ParseCommandOption(
4070
0
      MagickBooleanOptions,MagickFalse,option);
4071
3.35M
  option=GetImageOption(image_info,"blue-primary");
4072
3.35M
  if (option != (const char *) NULL)
4073
0
    {
4074
0
      flags=ParseGeometry(option,&geometry_info);
4075
0
      if ((flags & RhoValue) != 0)
4076
0
        image->chromaticity.blue_primary.x=geometry_info.rho;
4077
0
      image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x;
4078
0
      if ((flags & SigmaValue) != 0)
4079
0
        image->chromaticity.blue_primary.y=geometry_info.sigma;
4080
0
    }
4081
3.35M
  option=GetImageOption(image_info,"bordercolor");
4082
3.35M
  if (option != (const char *) NULL)
4083
0
    (void) QueryColorCompliance(option,AllCompliance,&image->border_color,
4084
0
      exception);
4085
  /* FUTURE: do not sync compose to per-image compose setting here */
4086
3.35M
  option=GetImageOption(image_info,"compose");
4087
3.35M
  if (option != (const char *) NULL)
4088
0
    image->compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
4089
0
      MagickFalse,option);
4090
  /* -- */
4091
3.35M
  option=GetImageOption(image_info,"compress");
4092
3.35M
  if (option != (const char *) NULL)
4093
0
    image->compression=(CompressionType) ParseCommandOption(
4094
0
      MagickCompressOptions,MagickFalse,option);
4095
3.35M
  option=GetImageOption(image_info,"debug");
4096
3.35M
  if (option != (const char *) NULL)
4097
0
    image->debug=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions,
4098
0
      MagickFalse,option);
4099
3.35M
  option=GetImageOption(image_info,"density");
4100
3.35M
  if (option != (const char *) NULL)
4101
0
    {
4102
0
      flags=ParseGeometry(option,&geometry_info);
4103
0
      if ((flags & RhoValue) != 0)
4104
0
        image->resolution.x=geometry_info.rho;
4105
0
      image->resolution.y=image->resolution.x;
4106
0
      if ((flags & SigmaValue) != 0)
4107
0
        image->resolution.y=geometry_info.sigma;
4108
0
    }
4109
3.35M
  option=GetImageOption(image_info,"depth");
4110
3.35M
  if (option != (const char *) NULL)
4111
0
    image->depth=StringToUnsignedLong(option);
4112
3.35M
  option=GetImageOption(image_info,"endian");
4113
3.35M
  if (option != (const char *) NULL)
4114
0
    image->endian=(EndianType) ParseCommandOption(MagickEndianOptions,
4115
0
      MagickFalse,option);
4116
3.35M
  option=GetImageOption(image_info,"filter");
4117
3.35M
  if (option != (const char *) NULL)
4118
0
    image->filter=(FilterType) ParseCommandOption(MagickFilterOptions,
4119
0
      MagickFalse,option);
4120
3.35M
  option=GetImageOption(image_info,"fuzz");
4121
3.35M
  if (option != (const char *) NULL)
4122
0
    image->fuzz=StringToDoubleInterval(option,(double) QuantumRange+1.0);
4123
3.35M
  option=GetImageOption(image_info,"gravity");
4124
3.35M
  if (option != (const char *) NULL)
4125
0
    image->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
4126
0
      MagickFalse,option);
4127
3.35M
  option=GetImageOption(image_info,"green-primary");
4128
3.35M
  if (option != (const char *) NULL)
4129
0
    {
4130
0
      flags=ParseGeometry(option,&geometry_info);
4131
0
      if ((flags & RhoValue) != 0)
4132
0
        image->chromaticity.green_primary.x=geometry_info.rho;
4133
0
      image->chromaticity.green_primary.y=image->chromaticity.green_primary.x;
4134
0
      if ((flags & SigmaValue) != 0)
4135
0
        image->chromaticity.green_primary.y=geometry_info.sigma;
4136
0
    }
4137
3.35M
  option=GetImageOption(image_info,"intent");
4138
3.35M
  if (option != (const char *) NULL)
4139
0
    image->rendering_intent=(RenderingIntent) ParseCommandOption(
4140
0
      MagickIntentOptions,MagickFalse,option);
4141
3.35M
  option=GetImageOption(image_info,"intensity");
4142
3.35M
  if (option != (const char *) NULL)
4143
0
    image->intensity=(PixelIntensityMethod) ParseCommandOption(
4144
0
      MagickPixelIntensityOptions,MagickFalse,option);
4145
3.35M
  option=GetImageOption(image_info,"interlace");
4146
3.35M
  if (option != (const char *) NULL)
4147
0
    image->interlace=(InterlaceType) ParseCommandOption(MagickInterlaceOptions,
4148
0
      MagickFalse,option);
4149
3.35M
  option=GetImageOption(image_info,"interpolate");
4150
3.35M
  if (option != (const char *) NULL)
4151
0
    image->interpolate=(PixelInterpolateMethod) ParseCommandOption(
4152
0
      MagickInterpolateOptions,MagickFalse,option);
4153
3.35M
  option=GetImageOption(image_info,"loop");
4154
3.35M
  if (option != (const char *) NULL)
4155
0
    image->iterations=StringToUnsignedLong(option);
4156
3.35M
  option=GetImageOption(image_info,"mattecolor");
4157
3.35M
  if (option != (const char *) NULL)
4158
0
    (void) QueryColorCompliance(option,AllCompliance,&image->matte_color,
4159
0
      exception);
4160
3.35M
  option=GetImageOption(image_info,"orient");
4161
3.35M
  if (option != (const char *) NULL)
4162
0
    image->orientation=(OrientationType) ParseCommandOption(
4163
0
      MagickOrientationOptions,MagickFalse,option);
4164
3.35M
  option=GetImageOption(image_info,"page");
4165
3.35M
  if (option != (const char *) NULL)
4166
0
    {
4167
0
      char
4168
0
        *geometry;
4169
4170
0
      geometry=GetPageGeometry(option);
4171
0
      flags=ParseAbsoluteGeometry(geometry,&image->page);
4172
0
      geometry=DestroyString(geometry);
4173
0
    }
4174
3.35M
  option=GetImageOption(image_info,"quality");
4175
3.35M
  if (option != (const char *) NULL)
4176
0
    image->quality=StringToUnsignedLong(option);
4177
3.35M
  option=GetImageOption(image_info,"red-primary");
4178
3.35M
  if (option != (const char *) NULL)
4179
0
    {
4180
0
      flags=ParseGeometry(option,&geometry_info);
4181
0
      if ((flags & RhoValue) != 0)
4182
0
        image->chromaticity.red_primary.x=geometry_info.rho;
4183
0
      image->chromaticity.red_primary.y=image->chromaticity.red_primary.x;
4184
0
      if ((flags & SigmaValue) != 0)
4185
0
        image->chromaticity.red_primary.y=geometry_info.sigma;
4186
0
    }
4187
3.35M
  if (image_info->quality != UndefinedCompressionQuality)
4188
0
    image->quality=image_info->quality;
4189
3.35M
  option=GetImageOption(image_info,"scene");
4190
3.35M
  if (option != (const char *) NULL)
4191
0
    image->scene=StringToUnsignedLong(option);
4192
3.35M
  option=GetImageOption(image_info,"taint");
4193
3.35M
  if (option != (const char *) NULL)
4194
0
    image->taint=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions,
4195
0
      MagickFalse,option);
4196
3.35M
  option=GetImageOption(image_info,"tile-offset");
4197
3.35M
  if (option != (const char *) NULL)
4198
0
    {
4199
0
      char
4200
0
        *geometry;
4201
4202
0
      geometry=GetPageGeometry(option);
4203
0
      flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
4204
0
      geometry=DestroyString(geometry);
4205
0
    }
4206
3.35M
  option=GetImageOption(image_info,"transparent-color");
4207
3.35M
  if (option != (const char *) NULL)
4208
0
    (void) QueryColorCompliance(option,AllCompliance,&image->transparent_color,
4209
0
      exception);
4210
3.35M
  option=GetImageOption(image_info,"type");
4211
3.35M
  if (option != (const char *) NULL)
4212
0
    image->type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
4213
0
      option);
4214
3.35M
  option=GetImageOption(image_info,"units");
4215
3.35M
  units=image_info->units;
4216
3.35M
  if (option != (const char *) NULL)
4217
0
    units=(ResolutionType) ParseCommandOption(MagickResolutionOptions,
4218
0
      MagickFalse,option);
4219
3.35M
  if (units != UndefinedResolution)
4220
0
    {
4221
0
      if (image->units != units)
4222
0
        switch (image->units)
4223
0
        {
4224
0
          case PixelsPerInchResolution:
4225
0
          {
4226
0
            if (units == PixelsPerCentimeterResolution)
4227
0
              {
4228
0
                image->resolution.x/=2.54;
4229
0
                image->resolution.y/=2.54;
4230
0
              }
4231
0
            break;
4232
0
          }
4233
0
          case PixelsPerCentimeterResolution:
4234
0
          {
4235
0
            if (units == PixelsPerInchResolution)
4236
0
              {
4237
0
                image->resolution.x=(double) ((size_t) (100.0*2.54*
4238
0
                  image->resolution.x+0.5))/100.0;
4239
0
                image->resolution.y=(double) ((size_t) (100.0*2.54*
4240
0
                  image->resolution.y+0.5))/100.0;
4241
0
              }
4242
0
            break;
4243
0
          }
4244
0
          default:
4245
0
            break;
4246
0
        }
4247
0
      image->units=units;
4248
0
      option=GetImageOption(image_info,"density");
4249
0
      if (option != (const char *) NULL)
4250
0
        {
4251
0
          flags=ParseGeometry(option,&geometry_info);
4252
0
          if ((flags & RhoValue) != 0)
4253
0
            image->resolution.x=geometry_info.rho;
4254
0
          image->resolution.y=image->resolution.x;
4255
0
          if ((flags & SigmaValue) != 0)
4256
0
            image->resolution.y=geometry_info.sigma;
4257
0
        }
4258
0
    }
4259
3.35M
  option=GetImageOption(image_info,"virtual-pixel");
4260
3.35M
  if (option != (const char *) NULL)
4261
0
    (void) SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
4262
0
      ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,option),
4263
0
      exception);
4264
3.35M
  option=GetImageOption(image_info,"white-point");
4265
3.35M
  if (option != (const char *) NULL)
4266
0
    {
4267
0
      flags=ParseGeometry(option,&geometry_info);
4268
0
      if ((flags & RhoValue) != 0)
4269
0
        image->chromaticity.white_point.x=geometry_info.rho;
4270
0
      image->chromaticity.white_point.y=image->chromaticity.white_point.x;
4271
0
      if ((flags & SigmaValue) != 0)
4272
0
        image->chromaticity.white_point.y=geometry_info.sigma;
4273
0
    }
4274
  /*
4275
    Pointer to allow the lookup of pre-image artifact will fallback to a global
4276
    option setting/define.  This saves a lot of duplication of global options
4277
    into per-image artifacts, while ensuring only specifically set per-image
4278
    artifacts are preserved when parenthesis ends.
4279
  */
4280
3.35M
  if (image->image_info != (ImageInfo *) NULL)
4281
0
    image->image_info=DestroyImageInfo(image->image_info);
4282
3.35M
  image->image_info=CloneImageInfo(image_info);
4283
3.35M
  return(MagickTrue);
4284
3.35M
}