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