Coverage Report

Created: 2026-03-31 06:56

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