]> granicus.if.org Git - imagemagick/blob - MagickCore/image.c
7c7d73095596108376e1996551f724222ac9b688
[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 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2014 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",MaxTextExtent);
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=AllocateSemaphoreInfo();
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,MaxTextExtent);
221   (void) CopyMagickString(image->magick_filename,image_info->filename,
222     MaxTextExtent);
223   (void) CopyMagickString(image->magick,image_info->magick,MaxTextExtent);
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     MaxTextExtent);
398   if (image_info != (ImageInfo *) NULL)
399     (void) CopyMagickString(GetNextImageInList(image)->filename,
400       image_info->filename,MaxTextExtent);
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 == BlendPixelTrait)
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         SetPixelInfoPixel(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,MaxTextExtent,"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,MaxTextExtent);
735   (void) ConcatenateMagickString(image_info->filename,pathname,MaxTextExtent);
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,MaxTextExtent,
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   clone_image=(Image *) AcquireMagickMemory(sizeof(*clone_image));
816   if (clone_image == (Image *) NULL)
817     ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
818   (void) ResetMagickMemory(clone_image,0,sizeof(*clone_image));
819   clone_image->signature=MagickSignature;
820   clone_image->storage_class=image->storage_class;
821   clone_image->number_channels=image->number_channels;
822   clone_image->number_meta_channels=image->number_meta_channels;
823   clone_image->metacontent_extent=image->metacontent_extent;
824   clone_image->colorspace=image->colorspace;
825   clone_image->read_mask=image->read_mask;
826   clone_image->write_mask=image->write_mask;
827   clone_image->alpha_trait=image->alpha_trait;
828   clone_image->columns=image->columns;
829   clone_image->rows=image->rows;
830   clone_image->dither=image->dither;
831   if (image->colormap != (PixelInfo *) NULL)
832     {
833       /*
834         Allocate and copy the image colormap.
835       */
836       clone_image->colors=image->colors;
837       length=(size_t) image->colors;
838       clone_image->colormap=(PixelInfo *) AcquireQuantumMemory(length,
839         sizeof(*clone_image->colormap));
840       if (clone_image->colormap == (PixelInfo *) NULL)
841         ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
842       (void) CopyMagickMemory(clone_image->colormap,image->colormap,length*
843         sizeof(*clone_image->colormap));
844     }
845   (void) CloneImageProfiles(clone_image,image);
846   (void) CloneImageProperties(clone_image,image);
847   (void) CloneImageArtifacts(clone_image,image);
848   GetTimerInfo(&clone_image->timer);
849   if (image->ascii85 != (void *) NULL)
850     Ascii85Initialize(clone_image);
851   clone_image->magick_columns=image->magick_columns;
852   clone_image->magick_rows=image->magick_rows;
853   clone_image->type=image->type;
854   clone_image->channel_mask=image->channel_mask;
855   clone_image->channel_map=ClonePixelChannelMap(image->channel_map);
856   (void) CopyMagickString(clone_image->magick_filename,image->magick_filename,
857     MaxTextExtent);
858   (void) CopyMagickString(clone_image->magick,image->magick,MaxTextExtent);
859   (void) CopyMagickString(clone_image->filename,image->filename,MaxTextExtent);
860   clone_image->progress_monitor=image->progress_monitor;
861   clone_image->client_data=image->client_data;
862   clone_image->reference_count=1;
863   clone_image->next=image->next;
864   clone_image->previous=image->previous;
865   clone_image->list=NewImageList();
866   if (detach == MagickFalse)
867     clone_image->blob=ReferenceBlob(image->blob);
868   else
869     {
870       clone_image->next=NewImageList();
871       clone_image->previous=NewImageList();
872       clone_image->blob=CloneBlobInfo((BlobInfo *) NULL);
873     }
874   clone_image->ping=image->ping;
875   clone_image->debug=IsEventLogging();
876   clone_image->semaphore=AllocateSemaphoreInfo();
877   if ((columns == 0) && (rows == 0))
878     {
879       if (image->montage != (char *) NULL)
880         (void) CloneString(&clone_image->montage,image->montage);
881       if (image->directory != (char *) NULL)
882         (void) CloneString(&clone_image->directory,image->directory);
883       clone_image->cache=ReferencePixelCache(image->cache);
884       return(clone_image);
885     }
886   scale=(double) columns/(double) image->columns;
887   clone_image->page.width=(size_t) floor(scale*image->page.width+0.5);
888   clone_image->page.x=(ssize_t) ceil(scale*image->page.x-0.5);
889   clone_image->tile_offset.x=(ssize_t) ceil(scale*image->tile_offset.x-0.5);
890   scale=(double) rows/(double) image->rows;
891   clone_image->page.height=(size_t) floor(scale*image->page.height+0.5);
892   clone_image->page.y=(ssize_t) ceil(scale*image->page.y-0.5);
893   clone_image->tile_offset.y=(ssize_t) ceil(scale*image->tile_offset.y-0.5);
894   clone_image->columns=columns;
895   clone_image->rows=rows;
896   clone_image->cache=ClonePixelCache(image->cache);
897
898   return(clone_image);
899 }
900 \f
901 /*
902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903 %                                                                             %
904 %                                                                             %
905 %                                                                             %
906 %   C l o n e I m a g e I n f o                                               %
907 %                                                                             %
908 %                                                                             %
909 %                                                                             %
910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
911 %
912 %  CloneImageInfo() makes a copy of the given image info structure.  If
913 %  NULL is specified, a new image info structure is created initialized to
914 %  default values.
915 %
916 %  The format of the CloneImageInfo method is:
917 %
918 %      ImageInfo *CloneImageInfo(const ImageInfo *image_info)
919 %
920 %  A description of each parameter follows:
921 %
922 %    o image_info: the image info.
923 %
924 */
925 MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info)
926 {
927   ImageInfo
928     *clone_info;
929
930   clone_info=AcquireImageInfo();
931   if (image_info == (ImageInfo *) NULL)
932     return(clone_info);
933   clone_info->compression=image_info->compression;
934   clone_info->temporary=image_info->temporary;
935   clone_info->adjoin=image_info->adjoin;
936   clone_info->antialias=image_info->antialias;
937   clone_info->scene=image_info->scene;
938   clone_info->number_scenes=image_info->number_scenes;
939   clone_info->depth=image_info->depth;
940   (void) CloneString(&clone_info->size,image_info->size);
941   (void) CloneString(&clone_info->extract,image_info->extract);
942   (void) CloneString(&clone_info->scenes,image_info->scenes);
943   (void) CloneString(&clone_info->page,image_info->page);
944   clone_info->interlace=image_info->interlace;
945   clone_info->endian=image_info->endian;
946   clone_info->units=image_info->units;
947   clone_info->quality=image_info->quality;
948   (void) CloneString(&clone_info->sampling_factor,image_info->sampling_factor);
949   (void) CloneString(&clone_info->server_name,image_info->server_name);
950   (void) CloneString(&clone_info->font,image_info->font);
951   (void) CloneString(&clone_info->texture,image_info->texture);
952   (void) CloneString(&clone_info->density,image_info->density);
953   clone_info->pointsize=image_info->pointsize;
954   clone_info->fuzz=image_info->fuzz;
955   clone_info->background_color=image_info->background_color;
956   clone_info->border_color=image_info->border_color;
957   clone_info->matte_color=image_info->matte_color;
958   clone_info->transparent_color=image_info->transparent_color;
959   clone_info->dither=image_info->dither;
960   clone_info->monochrome=image_info->monochrome;
961   clone_info->colorspace=image_info->colorspace;
962   clone_info->type=image_info->type;
963   clone_info->orientation=image_info->orientation;
964   clone_info->preview_type=image_info->preview_type;
965   clone_info->group=image_info->group;
966   clone_info->ping=image_info->ping;
967   clone_info->verbose=image_info->verbose;
968   (void) CloneString(&clone_info->view,image_info->view);
969   clone_info->progress_monitor=image_info->progress_monitor;
970   clone_info->client_data=image_info->client_data;
971   clone_info->cache=image_info->cache;
972   if (image_info->cache != (void *) NULL)
973     clone_info->cache=ReferencePixelCache(image_info->cache);
974   if (image_info->profile != (void *) NULL)
975     clone_info->profile=(void *) CloneStringInfo((StringInfo *)
976       image_info->profile);
977   SetImageInfoFile(clone_info,image_info->file);
978   SetImageInfoBlob(clone_info,image_info->blob,image_info->length);
979   clone_info->stream=image_info->stream;
980   (void) CopyMagickString(clone_info->magick,image_info->magick,MaxTextExtent);
981   (void) CopyMagickString(clone_info->unique,image_info->unique,MaxTextExtent);
982   (void) CopyMagickString(clone_info->zero,image_info->zero,MaxTextExtent);
983   (void) CopyMagickString(clone_info->filename,image_info->filename,
984     MaxTextExtent);
985   clone_info->channel=image_info->channel;
986   (void) CloneImageOptions(clone_info,image_info);
987   clone_info->debug=IsEventLogging();
988   clone_info->signature=image_info->signature;
989   return(clone_info);
990 }
991 \f
992 /*
993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
994 %                                                                             %
995 %                                                                             %
996 %                                                                             %
997 %   D e s t r o y I m a g e                                                   %
998 %                                                                             %
999 %                                                                             %
1000 %                                                                             %
1001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002 %
1003 %  DestroyImage() dereferences an image, deallocating memory associated with
1004 %  the image if the reference count becomes zero.
1005 %
1006 %  The format of the DestroyImage method is:
1007 %
1008 %      Image *DestroyImage(Image *image)
1009 %
1010 %  A description of each parameter follows:
1011 %
1012 %    o image: the image.
1013 %
1014 */
1015 MagickExport Image *DestroyImage(Image *image)
1016 {
1017   MagickBooleanType
1018     destroy;
1019
1020   /*
1021     Dereference image.
1022   */
1023   assert(image != (Image *) NULL);
1024   assert(image->signature == MagickSignature);
1025   if (image->debug != MagickFalse)
1026     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1027   destroy=MagickFalse;
1028   LockSemaphoreInfo(image->semaphore);
1029   image->reference_count--;
1030   if (image->reference_count == 0)
1031     destroy=MagickTrue;
1032   UnlockSemaphoreInfo(image->semaphore);
1033   if (destroy == MagickFalse)
1034     return((Image *) NULL);
1035   /*
1036     Destroy image.
1037   */
1038   DestroyImagePixels(image);
1039   image->channel_map=DestroyPixelChannelMap(image->channel_map);
1040   if (image->montage != (char *) NULL)
1041     image->montage=DestroyString(image->montage);
1042   if (image->directory != (char *) NULL)
1043     image->directory=DestroyString(image->directory);
1044   if (image->colormap != (PixelInfo *) NULL)
1045     image->colormap=(PixelInfo *) RelinquishMagickMemory(image->colormap);
1046   if (image->geometry != (char *) NULL)
1047     image->geometry=DestroyString(image->geometry);
1048   DestroyImageProfiles(image);
1049   DestroyImageProperties(image);
1050   DestroyImageArtifacts(image);
1051   if (image->ascii85 != (Ascii85Info*) NULL)
1052     image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85);
1053   DestroyBlob(image);
1054   if (image->semaphore != (SemaphoreInfo *) NULL)
1055     DestroySemaphoreInfo(&image->semaphore);
1056   image->signature=(~MagickSignature);
1057   image=(Image *) RelinquishMagickMemory(image);
1058   return(image);
1059 }
1060 \f
1061 /*
1062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063 %                                                                             %
1064 %                                                                             %
1065 %                                                                             %
1066 %   D e s t r o y I m a g e I n f o                                           %
1067 %                                                                             %
1068 %                                                                             %
1069 %                                                                             %
1070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1071 %
1072 %  DestroyImageInfo() deallocates memory associated with an ImageInfo
1073 %  structure.
1074 %
1075 %  The format of the DestroyImageInfo method is:
1076 %
1077 %      ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1078 %
1079 %  A description of each parameter follows:
1080 %
1081 %    o image_info: the image info.
1082 %
1083 */
1084 MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1085 {
1086   assert(image_info != (ImageInfo *) NULL);
1087   assert(image_info->signature == MagickSignature);
1088   if (image_info->debug != MagickFalse)
1089     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1090       image_info->filename);
1091   if (image_info->size != (char *) NULL)
1092     image_info->size=DestroyString(image_info->size);
1093   if (image_info->extract != (char *) NULL)
1094     image_info->extract=DestroyString(image_info->extract);
1095   if (image_info->scenes != (char *) NULL)
1096     image_info->scenes=DestroyString(image_info->scenes);
1097   if (image_info->page != (char *) NULL)
1098     image_info->page=DestroyString(image_info->page);
1099   if (image_info->sampling_factor != (char *) NULL)
1100     image_info->sampling_factor=DestroyString(
1101       image_info->sampling_factor);
1102   if (image_info->server_name != (char *) NULL)
1103     image_info->server_name=DestroyString(
1104       image_info->server_name);
1105   if (image_info->font != (char *) NULL)
1106     image_info->font=DestroyString(image_info->font);
1107   if (image_info->texture != (char *) NULL)
1108     image_info->texture=DestroyString(image_info->texture);
1109   if (image_info->density != (char *) NULL)
1110     image_info->density=DestroyString(image_info->density);
1111   if (image_info->view != (char *) NULL)
1112     image_info->view=DestroyString(image_info->view);
1113   if (image_info->cache != (void *) NULL)
1114     image_info->cache=DestroyPixelCache(image_info->cache);
1115   if (image_info->profile != (StringInfo *) NULL)
1116     image_info->profile=(void *) DestroyStringInfo((StringInfo *)
1117       image_info->profile);
1118   DestroyImageOptions(image_info);
1119   image_info->signature=(~MagickSignature);
1120   image_info=(ImageInfo *) RelinquishMagickMemory(image_info);
1121   return(image_info);
1122 }
1123 \f
1124 /*
1125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1126 %                                                                             %
1127 %                                                                             %
1128 %                                                                             %
1129 +   D i s a s s o c i a t e I m a g e S t r e a m                             %
1130 %                                                                             %
1131 %                                                                             %
1132 %                                                                             %
1133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1134 %
1135 %  DisassociateImageStream() disassociates the image stream.
1136 %
1137 %  The format of the DisassociateImageStream method is:
1138 %
1139 %      MagickBooleanType DisassociateImageStream(const Image *image)
1140 %
1141 %  A description of each parameter follows:
1142 %
1143 %    o image: the image.
1144 %
1145 */
1146 MagickExport void DisassociateImageStream(Image *image)
1147 {
1148   assert(image != (const Image *) NULL);
1149   assert(image->signature == MagickSignature);
1150   if (image->debug != MagickFalse)
1151     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1152   (void) DetachBlob(image->blob);
1153 }
1154 \f
1155 /*
1156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157 %                                                                             %
1158 %                                                                             %
1159 %                                                                             %
1160 %   G e t I m a g e I n f o                                                   %
1161 %                                                                             %
1162 %                                                                             %
1163 %                                                                             %
1164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165 %
1166 %  GetImageInfo() initializes image_info to default values.
1167 %
1168 %  The format of the GetImageInfo method is:
1169 %
1170 %      void GetImageInfo(ImageInfo *image_info)
1171 %
1172 %  A description of each parameter follows:
1173 %
1174 %    o image_info: the image info.
1175 %
1176 */
1177 MagickExport void GetImageInfo(ImageInfo *image_info)
1178 {
1179   char
1180     *synchronize;
1181
1182   ExceptionInfo
1183     *exception;
1184
1185   /*
1186     File and image dimension members.
1187   */
1188   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1189   assert(image_info != (ImageInfo *) NULL);
1190   (void) ResetMagickMemory(image_info,0,sizeof(*image_info));
1191   image_info->adjoin=MagickTrue;
1192   image_info->interlace=NoInterlace;
1193   image_info->channel=DefaultChannels;
1194   image_info->quality=UndefinedCompressionQuality;
1195   image_info->antialias=MagickTrue;
1196   image_info->dither=MagickTrue;
1197   synchronize=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
1198   if (synchronize != (const char *) NULL)
1199     {
1200       image_info->synchronize=IsStringTrue(synchronize);
1201       synchronize=DestroyString(synchronize);
1202     }
1203   exception=AcquireExceptionInfo();
1204   (void) QueryColorCompliance(BackgroundColor,AllCompliance,
1205     &image_info->background_color,exception);
1206   (void) QueryColorCompliance(BorderColor,AllCompliance,
1207     &image_info->border_color,exception);
1208   (void) QueryColorCompliance(MatteColor,AllCompliance,&image_info->matte_color,
1209     exception);
1210   (void) QueryColorCompliance(TransparentColor,AllCompliance,
1211     &image_info->transparent_color,exception);
1212   exception=DestroyExceptionInfo(exception);
1213   image_info->debug=IsEventLogging();
1214   image_info->signature=MagickSignature;
1215 }
1216 \f
1217 /*
1218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1219 %                                                                             %
1220 %                                                                             %
1221 %                                                                             %
1222 %   G e t I m a g e I n f o F i l e                                           %
1223 %                                                                             %
1224 %                                                                             %
1225 %                                                                             %
1226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1227 %
1228 %  GetImageInfoFile() returns the image info file member.
1229 %
1230 %  The format of the GetImageInfoFile method is:
1231 %
1232 %      FILE *GetImageInfoFile(const ImageInfo *image_info)
1233 %
1234 %  A description of each parameter follows:
1235 %
1236 %    o image_info: the image info.
1237 %
1238 */
1239 MagickExport FILE *GetImageInfoFile(const ImageInfo *image_info)
1240 {
1241   return(image_info->file);
1242 }
1243 \f
1244 /*
1245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1246 %                                                                             %
1247 %                                                                             %
1248 %                                                                             %
1249 %   G e t I m a g e M a s k                                                   %
1250 %                                                                             %
1251 %                                                                             %
1252 %                                                                             %
1253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254 %
1255 %  GetImageMask() returns the mask associated with the image.
1256 %
1257 %  The format of the GetImageMask method is:
1258 %
1259 %      Image *GetImageMask(const Image *image,ExceptionInfo *exception)
1260 %
1261 %  A description of each parameter follows:
1262 %
1263 %    o image: the image.
1264 %
1265 */
1266 MagickExport Image *GetImageMask(const Image *image,ExceptionInfo *exception)
1267 {
1268   CacheView
1269     *mask_view,
1270     *image_view;
1271
1272   Image
1273     *mask_image;
1274
1275   MagickBooleanType
1276     status;
1277
1278   ssize_t
1279     y;
1280
1281   /*
1282     Get image mask.
1283   */
1284   assert(image != (Image *) NULL);
1285   if (image->debug != MagickFalse)
1286     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1287   assert(image->signature == MagickSignature);
1288   mask_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
1289   if (mask_image == (Image *) NULL)
1290     return((Image *) NULL);
1291   status=MagickTrue;
1292   (void) SetImageColorspace(mask_image,GRAYColorspace,exception);
1293   mask_image->read_mask=MagickFalse;
1294   image_view=AcquireVirtualCacheView(image,exception);
1295   mask_view=AcquireAuthenticCacheView(mask_image,exception);
1296   for (y=0; y < (ssize_t) image->rows; y++)
1297   {
1298     register const Quantum
1299       *restrict p;
1300
1301     register Quantum
1302       *restrict q;
1303
1304     register ssize_t
1305       x;
1306
1307     if (status == MagickFalse)
1308       continue;
1309     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1310     q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1311       exception);
1312     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1313       {
1314         status=MagickFalse;
1315         continue;
1316       }
1317     for (x=0; x < (ssize_t) image->columns; x++)
1318     {
1319       SetPixelGray(mask_image,GetPixelReadMask(image,p),q);
1320       p+=GetPixelChannels(image);
1321       q+=GetPixelChannels(mask_image);
1322     }
1323     if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1324       status=MagickFalse;
1325   }
1326   mask_view=DestroyCacheView(mask_view);
1327   image_view=DestroyCacheView(image_view);
1328   if (status == MagickFalse)
1329     mask_image=DestroyImage(mask_image);
1330   return(mask_image);
1331 }
1332 \f
1333 /*
1334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1335 %                                                                             %
1336 %                                                                             %
1337 %                                                                             %
1338 +   G e t I m a g e R e f e r e n c e C o u n t                               %
1339 %                                                                             %
1340 %                                                                             %
1341 %                                                                             %
1342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1343 %
1344 %  GetImageReferenceCount() returns the image reference count.
1345 %
1346 %  The format of the GetReferenceCount method is:
1347 %
1348 %      ssize_t GetImageReferenceCount(Image *image)
1349 %
1350 %  A description of each parameter follows:
1351 %
1352 %    o image: the image.
1353 %
1354 */
1355 MagickExport ssize_t GetImageReferenceCount(Image *image)
1356 {
1357   ssize_t
1358     reference_count;
1359
1360   assert(image != (Image *) NULL);
1361   assert(image->signature == MagickSignature);
1362   if (image->debug != MagickFalse)
1363     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1364   LockSemaphoreInfo(image->semaphore);
1365   reference_count=image->reference_count;
1366   UnlockSemaphoreInfo(image->semaphore);
1367   return(reference_count);
1368 }
1369 \f
1370 /*
1371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1372 %                                                                             %
1373 %                                                                             %
1374 %                                                                             %
1375 %   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                       %
1376 %                                                                             %
1377 %                                                                             %
1378 %                                                                             %
1379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1380 %
1381 %  GetImageVirtualPixelMethod() gets the "virtual pixels" method for the
1382 %  image.  A virtual pixel is any pixel access that is outside the boundaries
1383 %  of the image cache.
1384 %
1385 %  The format of the GetImageVirtualPixelMethod() method is:
1386 %
1387 %      VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1388 %
1389 %  A description of each parameter follows:
1390 %
1391 %    o image: the image.
1392 %
1393 */
1394 MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1395 {
1396   assert(image != (Image *) NULL);
1397   assert(image->signature == MagickSignature);
1398   if (image->debug != MagickFalse)
1399     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1400   return(GetPixelCacheVirtualMethod(image));
1401 }
1402 \f
1403 /*
1404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1405 %                                                                             %
1406 %                                                                             %
1407 %                                                                             %
1408 %  I n t e r p r e t I m a g e F i l e n a m e                                %
1409 %                                                                             %
1410 %                                                                             %
1411 %                                                                             %
1412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1413 %
1414 %  InterpretImageFilename() interprets embedded characters in an image filename.
1415 %  The filename length is returned.
1416 %
1417 %  The format of the InterpretImageFilename method is:
1418 %
1419 %      size_t InterpretImageFilename(const ImageInfo *image_info,Image *image,
1420 %        const char *format,int value,char *filename,ExceptionInfo *exception)
1421 %
1422 %  A description of each parameter follows.
1423 %
1424 %    o image_info: the image info..
1425 %
1426 %    o image: the image.
1427 %
1428 %    o format:  A filename describing the format to use to write the numeric
1429 %      argument. Only the first numeric format identifier is replaced.
1430 %
1431 %    o value:  Numeric value to substitute into format filename.
1432 %
1433 %    o filename:  return the formatted filename in this character buffer.
1434 %
1435 %    o exception: return any errors or warnings in this structure.
1436 %
1437 */
1438 MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
1439   Image *image,const char *format,int value,char *filename,
1440   ExceptionInfo *exception)
1441 {
1442   char
1443     *q;
1444
1445   int
1446     c;
1447
1448   MagickBooleanType
1449     canonical;
1450
1451   register const char
1452     *p;
1453
1454   size_t
1455     length;
1456
1457   canonical=MagickFalse;
1458   length=0;
1459   (void) CopyMagickString(filename,format,MaxTextExtent);
1460   for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
1461   {
1462     q=(char *) p+1;
1463     if (*q == '%')
1464       {
1465         p=q+1;
1466         continue;
1467       }
1468     if (*q == '0')
1469       {
1470         ssize_t
1471           value;
1472
1473         value=(ssize_t) strtol(q,&q,10);
1474         (void) value;
1475       }
1476     switch (*q)
1477     {
1478       case 'd':
1479       case 'o':
1480       case 'x':
1481       {
1482         q++;
1483         c=(*q);
1484         *q='\0';
1485         (void) FormatLocaleString(filename+(p-format),(size_t) (MaxTextExtent-
1486           (p-format)),p,value);
1487         *q=c;
1488         (void) ConcatenateMagickString(filename,q,MaxTextExtent);
1489         canonical=MagickTrue;
1490         if (*(q-1) != '%')
1491           break;
1492         p++;
1493         break;
1494       }
1495       case '[':
1496       {
1497         char
1498           pattern[MaxTextExtent];
1499
1500         const char
1501           *value;
1502
1503         register char
1504           *r;
1505
1506         register ssize_t
1507           i;
1508
1509         ssize_t
1510           depth;
1511
1512         /*
1513           Image option.
1514         */
1515         /* FUTURE: Compare update with code from InterpretImageProperties()
1516            Note that a 'filename:' property should not need depth recursion.
1517         */
1518         if (strchr(p,']') == (char *) NULL)
1519           break;
1520         depth=1;
1521         r=q+1;
1522         for (i=0; (i < (MaxTextExtent-1L)) && (*r != '\0'); i++)
1523         {
1524           if (*r == '[')
1525             depth++;
1526           if (*r == ']')
1527             depth--;
1528           if (depth <= 0)
1529             break;
1530           pattern[i]=(*r++);
1531         }
1532         pattern[i]='\0';
1533         if (LocaleNCompare(pattern,"filename:",9) != 0)
1534           break;
1535         value=(const char *) NULL;
1536 #if 0
1537         // FUTURE: remove this code. -- Anthony  29 Arpil 2012
1538         // Removed as GetMagickProperty() will will never match a "filename:"
1539         // string as this is not a 'known' image property.
1540         //
1541         if ((image_info != (const ImageInfo *) NULL) &&
1542             (image != (const Image *) NULL))
1543           value=GetMagickProperty(image_info,image,pattern,exception);
1544         else
1545 #endif
1546         if (image != (Image *) NULL)
1547           value=GetImageProperty(image,pattern,exception);
1548         if ((value == (const char *) NULL) && (image != (Image *) NULL))
1549           value=GetImageArtifact(image,pattern);
1550         if ((value == (const char *) NULL) &&
1551             (image_info != (ImageInfo *) NULL))
1552           value=GetImageOption(image_info,pattern);
1553         if (value == (const char *) NULL)
1554           break;
1555         q--;
1556         c=(*q);
1557         *q='\0';
1558         (void) CopyMagickString(filename+(p-format-length),value,(size_t)
1559           (MaxTextExtent-(p-format-length)));
1560         length+=strlen(pattern)-1;
1561         *q=c;
1562         (void) ConcatenateMagickString(filename,r+1,MaxTextExtent);
1563         canonical=MagickTrue;
1564         if (*(q-1) != '%')
1565           break;
1566         p++;
1567         break;
1568       }
1569       default:
1570         break;
1571     }
1572   }
1573   for (q=filename; *q != '\0'; q++)
1574     if ((*q == '%') && (*(q+1) == '%'))
1575       {
1576         (void) CopyMagickString(q,q+1,(size_t) (MaxTextExtent-(q-filename)));
1577         canonical=MagickTrue;
1578       }
1579   if (canonical == MagickFalse)
1580     (void) CopyMagickString(filename,format,MaxTextExtent);
1581   return(strlen(filename));
1582 }
1583 \f
1584 /*
1585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1586 %                                                                             %
1587 %                                                                             %
1588 %                                                                             %
1589 %   I s H i g h D y n a m i c R a n g e I m a g e                             %
1590 %                                                                             %
1591 %                                                                             %
1592 %                                                                             %
1593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1594 %
1595 %  IsHighDynamicRangeImage() returns MagickTrue if any pixel component is
1596 %  non-integer or exceeds the bounds of the quantum depth (e.g. for Q16
1597 %  0..65535.
1598 %
1599 %  The format of the IsHighDynamicRangeImage method is:
1600 %
1601 %      MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1602 %        ExceptionInfo *exception)
1603 %
1604 %  A description of each parameter follows:
1605 %
1606 %    o image: the image.
1607 %
1608 %    o exception: return any errors or warnings in this structure.
1609 %
1610 */
1611 MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1612   ExceptionInfo *exception)
1613 {
1614 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1615   (void) image;
1616   (void) exception;
1617   return(MagickFalse);
1618 #else
1619   CacheView
1620     *image_view;
1621
1622   MagickBooleanType
1623     status;
1624
1625   ssize_t
1626     y;
1627
1628   assert(image != (Image *) NULL);
1629   assert(image->signature == MagickSignature);
1630   if (image->debug != MagickFalse)
1631     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1632   status=MagickTrue;
1633   image_view=AcquireVirtualCacheView(image,exception);
1634 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1635   #pragma omp parallel for schedule(static,4) shared(status) \
1636     magick_threads(image,image,image->rows,1)
1637 #endif
1638   for (y=0; y < (ssize_t) image->rows; y++)
1639   {
1640     register const Quantum
1641       *p;
1642
1643     register ssize_t
1644       x;
1645
1646     if (status == MagickFalse)
1647       continue;
1648     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1649     if (p == (const Quantum *) NULL)
1650       {
1651         status=MagickFalse;
1652         continue;
1653       }
1654     for (x=0; x < (ssize_t) image->columns; x++)
1655     {
1656       register ssize_t
1657         i;
1658
1659       if (GetPixelReadMask(image,p) == 0)
1660         {
1661           p+=GetPixelChannels(image);
1662           continue;
1663         }
1664       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1665       {
1666         double
1667           pixel;
1668
1669         PixelTrait
1670           traits;
1671
1672         traits=GetPixelChannelTraits(image,(PixelChannel) i);
1673         if (traits == UndefinedPixelTrait)
1674           continue;
1675         pixel=(double) p[i];
1676         if ((pixel < 0.0) || (pixel > QuantumRange) ||
1677             (pixel != (double) ((QuantumAny) pixel)))
1678           break;
1679       }
1680       p+=GetPixelChannels(image);
1681       if (i < (ssize_t) GetPixelChannels(image))
1682         status=MagickFalse;
1683     }
1684     if (x < (ssize_t) image->columns)
1685       status=MagickFalse;
1686   }
1687   image_view=DestroyCacheView(image_view);
1688   return(status != MagickFalse ? MagickFalse : MagickTrue);
1689 #endif
1690 }
1691 \f
1692 /*
1693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1694 %                                                                             %
1695 %                                                                             %
1696 %                                                                             %
1697 %     I s I m a g e O b j e c t                                               %
1698 %                                                                             %
1699 %                                                                             %
1700 %                                                                             %
1701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1702 %
1703 %  IsImageObject() returns MagickTrue if the image sequence contains a valid
1704 %  set of image objects.
1705 %
1706 %  The format of the IsImageObject method is:
1707 %
1708 %      MagickBooleanType IsImageObject(const Image *image)
1709 %
1710 %  A description of each parameter follows:
1711 %
1712 %    o image: the image.
1713 %
1714 */
1715 MagickExport MagickBooleanType IsImageObject(const Image *image)
1716 {
1717   register const Image
1718     *p;
1719
1720   assert(image != (Image *) NULL);
1721   if (image->debug != MagickFalse)
1722     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1723   for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1724     if (p->signature != MagickSignature)
1725       return(MagickFalse);
1726   return(MagickTrue);
1727 }
1728 \f
1729 /*
1730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1731 %                                                                             %
1732 %                                                                             %
1733 %                                                                             %
1734 %     I s T a i n t I m a g e                                                 %
1735 %                                                                             %
1736 %                                                                             %
1737 %                                                                             %
1738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1739 %
1740 %  IsTaintImage() returns MagickTrue any pixel in the image has been altered
1741 %  since it was first constituted.
1742 %
1743 %  The format of the IsTaintImage method is:
1744 %
1745 %      MagickBooleanType IsTaintImage(const Image *image)
1746 %
1747 %  A description of each parameter follows:
1748 %
1749 %    o image: the image.
1750 %
1751 */
1752 MagickExport MagickBooleanType IsTaintImage(const Image *image)
1753 {
1754   char
1755     magick[MaxTextExtent],
1756     filename[MaxTextExtent];
1757
1758   register const Image
1759     *p;
1760
1761   assert(image != (Image *) NULL);
1762   if (image->debug != MagickFalse)
1763     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1764   assert(image->signature == MagickSignature);
1765   (void) CopyMagickString(magick,image->magick,MaxTextExtent);
1766   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
1767   for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1768   {
1769     if (p->taint != MagickFalse)
1770       return(MagickTrue);
1771     if (LocaleCompare(p->magick,magick) != 0)
1772       return(MagickTrue);
1773     if (LocaleCompare(p->filename,filename) != 0)
1774       return(MagickTrue);
1775   }
1776   return(MagickFalse);
1777 }
1778 \f
1779 /*
1780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781 %                                                                             %
1782 %                                                                             %
1783 %                                                                             %
1784 %   M o d i f y I m a g e                                                     %
1785 %                                                                             %
1786 %                                                                             %
1787 %                                                                             %
1788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1789 %
1790 %  ModifyImage() ensures that there is only a single reference to the image
1791 %  to be modified, updating the provided image pointer to point to a clone of
1792 %  the original image if necessary.
1793 %
1794 %  The format of the ModifyImage method is:
1795 %
1796 %      MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception)
1797 %
1798 %  A description of each parameter follows:
1799 %
1800 %    o image: the image.
1801 %
1802 %    o exception: return any errors or warnings in this structure.
1803 %
1804 */
1805 MagickExport MagickBooleanType ModifyImage(Image **image,
1806   ExceptionInfo *exception)
1807 {
1808   Image
1809     *clone_image;
1810
1811   assert(image != (Image **) NULL);
1812   assert(*image != (Image *) NULL);
1813   assert((*image)->signature == MagickSignature);
1814   if ((*image)->debug != MagickFalse)
1815     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1816   if (GetImageReferenceCount(*image) <= 1)
1817     return(MagickTrue);
1818   clone_image=CloneImage(*image,0,0,MagickTrue,exception);
1819   LockSemaphoreInfo((*image)->semaphore);
1820   (*image)->reference_count--;
1821   UnlockSemaphoreInfo((*image)->semaphore);
1822   *image=clone_image;
1823   return(MagickTrue);
1824 }
1825 \f
1826 /*
1827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1828 %                                                                             %
1829 %                                                                             %
1830 %                                                                             %
1831 %   N e w M a g i c k I m a g e                                               %
1832 %                                                                             %
1833 %                                                                             %
1834 %                                                                             %
1835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1836 %
1837 %  NewMagickImage() creates a blank image canvas of the specified size and
1838 %  background color.
1839 %
1840 %  The format of the NewMagickImage method is:
1841 %
1842 %      Image *NewMagickImage(const ImageInfo *image_info,
1843 %        const size_t width,const size_t height,const PixelInfo *background,
1844 %        ExceptionInfo *exception)
1845 %
1846 %  A description of each parameter follows:
1847 %
1848 %    o image: the image.
1849 %
1850 %    o width: the image width.
1851 %
1852 %    o height: the image height.
1853 %
1854 %    o background: the image color.
1855 %
1856 %    o exception: return any errors or warnings in this structure.
1857 %
1858 */
1859 MagickExport Image *NewMagickImage(const ImageInfo *image_info,
1860   const size_t width,const size_t height,const PixelInfo *background,
1861   ExceptionInfo *exception)
1862 {
1863   CacheView
1864     *image_view;
1865
1866   Image
1867     *image;
1868
1869   MagickBooleanType
1870     status;
1871
1872   ssize_t
1873     y;
1874
1875   assert(image_info != (const ImageInfo *) NULL);
1876   if (image_info->debug != MagickFalse)
1877     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1878   assert(image_info->signature == MagickSignature);
1879   assert(background != (const PixelInfo *) NULL);
1880   image=AcquireImage(image_info,exception);
1881   image->columns=width;
1882   image->rows=height;
1883   image->colorspace=background->colorspace;
1884   image->alpha_trait=background->alpha_trait;
1885   image->fuzz=background->fuzz;
1886   image->depth=background->depth;
1887   status=MagickTrue;
1888   image_view=AcquireAuthenticCacheView(image,exception);
1889 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1890   #pragma omp parallel for schedule(static,4) shared(status) \
1891     magick_threads(image,image,image->rows,1)
1892 #endif
1893   for (y=0; y < (ssize_t) image->rows; y++)
1894   {
1895     register Quantum
1896       *restrict q;
1897
1898     register ssize_t
1899       x;
1900
1901     if (status == MagickFalse)
1902       continue;
1903     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1904     if (q == (Quantum *) NULL)
1905       {
1906         status=MagickFalse;
1907         continue;
1908       }
1909     for (x=0; x < (ssize_t) image->columns; x++)
1910     {
1911       SetPixelInfoPixel(image,background,q);
1912       q+=GetPixelChannels(image);
1913     }
1914     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1915       status=MagickFalse;
1916   }
1917   image_view=DestroyCacheView(image_view);
1918   if (status == MagickFalse)
1919     image=DestroyImage(image);
1920   return(image);
1921 }
1922 \f
1923 /*
1924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1925 %                                                                             %
1926 %                                                                             %
1927 %                                                                             %
1928 %   R e f e r e n c e I m a g e                                               %
1929 %                                                                             %
1930 %                                                                             %
1931 %                                                                             %
1932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1933 %
1934 %  ReferenceImage() increments the reference count associated with an image
1935 %  returning a pointer to the image.
1936 %
1937 %  The format of the ReferenceImage method is:
1938 %
1939 %      Image *ReferenceImage(Image *image)
1940 %
1941 %  A description of each parameter follows:
1942 %
1943 %    o image: the image.
1944 %
1945 */
1946 MagickExport Image *ReferenceImage(Image *image)
1947 {
1948   assert(image != (Image *) NULL);
1949   if (image->debug != MagickFalse)
1950     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1951   assert(image->signature == MagickSignature);
1952   LockSemaphoreInfo(image->semaphore);
1953   image->reference_count++;
1954   UnlockSemaphoreInfo(image->semaphore);
1955   return(image);
1956 }
1957 \f
1958 /*
1959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1960 %                                                                             %
1961 %                                                                             %
1962 %                                                                             %
1963 %   R e s e t I m a g e P a g e                                               %
1964 %                                                                             %
1965 %                                                                             %
1966 %                                                                             %
1967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1968 %
1969 %  ResetImagePage() resets the image page canvas and position.
1970 %
1971 %  The format of the ResetImagePage method is:
1972 %
1973 %      MagickBooleanType ResetImagePage(Image *image,const char *page)
1974 %
1975 %  A description of each parameter follows:
1976 %
1977 %    o image: the image.
1978 %
1979 %    o page: the relative page specification.
1980 %
1981 */
1982 MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page)
1983 {
1984   MagickStatusType
1985     flags;
1986
1987   RectangleInfo
1988     geometry;
1989
1990   assert(image != (Image *) NULL);
1991   assert(image->signature == MagickSignature);
1992   if (image->debug != MagickFalse)
1993     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1994   flags=ParseAbsoluteGeometry(page,&geometry);
1995   if ((flags & WidthValue) != 0)
1996     {
1997       if ((flags & HeightValue) == 0)
1998         geometry.height=geometry.width;
1999       image->page.width=geometry.width;
2000       image->page.height=geometry.height;
2001     }
2002   if ((flags & AspectValue) != 0)
2003     {
2004       if ((flags & XValue) != 0)
2005         image->page.x+=geometry.x;
2006       if ((flags & YValue) != 0)
2007         image->page.y+=geometry.y;
2008     }
2009   else
2010     {
2011       if ((flags & XValue) != 0)
2012         {
2013           image->page.x=geometry.x;
2014           if ((image->page.width == 0) && (geometry.x > 0))
2015             image->page.width=image->columns+geometry.x;
2016         }
2017       if ((flags & YValue) != 0)
2018         {
2019           image->page.y=geometry.y;
2020           if ((image->page.height == 0) && (geometry.y > 0))
2021             image->page.height=image->rows+geometry.y;
2022         }
2023     }
2024   return(MagickTrue);
2025 }
2026 \f
2027 /*
2028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2029 %                                                                             %
2030 %                                                                             %
2031 %                                                                             %
2032 %   S e t I m a g e B a c k g r o u n d C o l o r                             %
2033 %                                                                             %
2034 %                                                                             %
2035 %                                                                             %
2036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2037 %
2038 %  SetImageBackgroundColor() initializes the image pixels to the image
2039 %  background color.  The background color is defined by the background_color
2040 %  member of the image structure.
2041 %
2042 %  The format of the SetImage method is:
2043 %
2044 %      MagickBooleanType SetImageBackgroundColor(Image *image,
2045 %        ExceptionInfo *exception)
2046 %
2047 %  A description of each parameter follows:
2048 %
2049 %    o image: the image.
2050 %
2051 %    o exception: return any errors or warnings in this structure.
2052 %
2053 */
2054 MagickExport MagickBooleanType SetImageBackgroundColor(Image *image,
2055   ExceptionInfo *exception)
2056 {
2057   CacheView
2058     *image_view;
2059
2060   MagickBooleanType
2061     status;
2062
2063   ssize_t
2064     y;
2065
2066   assert(image != (Image *) NULL);
2067   if (image->debug != MagickFalse)
2068     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2069   assert(image->signature == MagickSignature);
2070   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2071     return(MagickFalse);
2072   if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
2073       (IsGrayColorspace(image->colorspace) != MagickFalse))
2074     (void) TransformImageColorspace(image,sRGBColorspace,exception);
2075   if ((image->background_color.alpha_trait == BlendPixelTrait) &&
2076       (image->alpha_trait != BlendPixelTrait))
2077     (void) SetImageAlpha(image,OpaqueAlpha,exception);
2078   /*
2079     Set image background color.
2080   */
2081   status=MagickTrue;
2082   image_view=AcquireAuthenticCacheView(image,exception);
2083   for (y=0; y < (ssize_t) image->rows; y++)
2084   {
2085     register Quantum
2086       *restrict q;
2087
2088     register ssize_t
2089       x;
2090
2091     if (status == MagickFalse)
2092       continue;
2093     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2094     if (q == (Quantum *) NULL)
2095       {
2096         status=MagickFalse;
2097         continue;
2098       }
2099     for (x=0; x < (ssize_t) image->columns; x++)
2100     {
2101       SetPixelInfoPixel(image,&image->background_color,q);
2102       q+=GetPixelChannels(image);
2103     }
2104     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2105       status=MagickFalse;
2106   }
2107   image_view=DestroyCacheView(image_view);
2108   return(status);
2109 }
2110 \f
2111 /*
2112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2113 %                                                                             %
2114 %                                                                             %
2115 %                                                                             %
2116 %   S e t I m a g e C h a n n e l M a s k                                     %
2117 %                                                                             %
2118 %                                                                             %
2119 %                                                                             %
2120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2121 %
2122 %  SetImageChannelMask() sets the image channel mask from the specified channel
2123 %  mask.
2124 %
2125 %  The format of the SetImageChannelMask method is:
2126 %
2127 %      ChannelType SetImageChannelMask(Image *image,
2128 %        const ChannelType channel_mask)
2129 %
2130 %  A description of each parameter follows:
2131 %
2132 %    o image: the image.
2133 %
2134 %    o channel_mask: the channel mask.
2135 %
2136 */
2137 MagickExport ChannelType SetImageChannelMask(Image *image,
2138   const ChannelType channel_mask)
2139 {
2140   ChannelType
2141     mask;
2142
2143   mask=image->channel_mask;
2144   image->channel_mask=channel_mask;
2145   SetPixelChannelMask(image,channel_mask);
2146   return(mask);
2147 }
2148 \f
2149 /*
2150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2151 %                                                                             %
2152 %                                                                             %
2153 %                                                                             %
2154 %   S e t I m a g e C o l o r                                                 %
2155 %                                                                             %
2156 %                                                                             %
2157 %                                                                             %
2158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2159 %
2160 %  SetImageColor() set the entire image canvas to the specified color.
2161 %
2162 %  The format of the SetImageColor method is:
2163 %
2164 %      MagickBooleanType SetImageColor(Image *image,const PixelInfo *color,
2165 %        ExeptionInfo *exception)
2166 %
2167 %  A description of each parameter follows:
2168 %
2169 %    o image: the image.
2170 %
2171 %    o background: the image color.
2172 %
2173 %    o exception: return any errors or warnings in this structure.
2174 %
2175 */
2176 MagickExport MagickBooleanType SetImageColor(Image *image,
2177   const PixelInfo *color,ExceptionInfo *exception)
2178 {
2179   CacheView
2180     *image_view;
2181
2182   MagickBooleanType
2183     status;
2184
2185   ssize_t
2186     y;
2187
2188   assert(image != (Image *) NULL);
2189   if (image->debug != MagickFalse)
2190     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2191   assert(image->signature == MagickSignature);
2192   assert(color != (const PixelInfo *) NULL);
2193   image->colorspace=color->colorspace;
2194   image->alpha_trait=color->alpha_trait;
2195   image->fuzz=color->fuzz;
2196   image->depth=color->depth;
2197   status=MagickTrue;
2198   image_view=AcquireAuthenticCacheView(image,exception);
2199 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2200   #pragma omp parallel for schedule(static,4) shared(status) \
2201     magick_threads(image,image,image->rows,1)
2202 #endif
2203   for (y=0; y < (ssize_t) image->rows; y++)
2204   {
2205     register Quantum
2206       *restrict q;
2207
2208     register ssize_t
2209       x;
2210
2211     if (status == MagickFalse)
2212       continue;
2213     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2214     if (q == (Quantum *) NULL)
2215       {
2216         status=MagickFalse;
2217         continue;
2218       }
2219     for (x=0; x < (ssize_t) image->columns; x++)
2220     {
2221       SetPixelInfoPixel(image,color,q);
2222       q+=GetPixelChannels(image);
2223     }
2224     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2225       status=MagickFalse;
2226   }
2227   image_view=DestroyCacheView(image_view);
2228   return(status);
2229 }
2230 \f
2231 /*
2232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2233 %                                                                             %
2234 %                                                                             %
2235 %                                                                             %
2236 %   S e t I m a g e S t o r a g e C l a s s                                   %
2237 %                                                                             %
2238 %                                                                             %
2239 %                                                                             %
2240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2241 %
2242 %  SetImageStorageClass() sets the image class: DirectClass for true color
2243 %  images or PseudoClass for colormapped images.
2244 %
2245 %  The format of the SetImageStorageClass method is:
2246 %
2247 %      MagickBooleanType SetImageStorageClass(Image *image,
2248 %        const ClassType storage_class,ExceptionInfo *exception)
2249 %
2250 %  A description of each parameter follows:
2251 %
2252 %    o image: the image.
2253 %
2254 %    o storage_class:  The image class.
2255 %
2256 %    o exception: return any errors or warnings in this structure.
2257 %
2258 */
2259 MagickExport MagickBooleanType SetImageStorageClass(Image *image,
2260   const ClassType storage_class,ExceptionInfo *exception)
2261 {
2262   image->storage_class=storage_class;
2263   return(SyncImagePixelCache(image,exception));
2264 }
2265 \f
2266 /*
2267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2268 %                                                                             %
2269 %                                                                             %
2270 %                                                                             %
2271 %   S e t I m a g e E x t e n t                                               %
2272 %                                                                             %
2273 %                                                                             %
2274 %                                                                             %
2275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2276 %
2277 %  SetImageExtent() sets the image size (i.e. columns & rows).
2278 %
2279 %  The format of the SetImageExtent method is:
2280 %
2281 %      MagickBooleanType SetImageExtent(Image *image,const size_t columns,
2282 %        const size_t rows,ExceptionInfo *exception)
2283 %
2284 %  A description of each parameter follows:
2285 %
2286 %    o image: the image.
2287 %
2288 %    o columns:  The image width in pixels.
2289 %
2290 %    o rows:  The image height in pixels.
2291 %
2292 %    o exception: return any errors or warnings in this structure.
2293 %
2294 */
2295 MagickExport MagickBooleanType SetImageExtent(Image *image,const size_t columns,
2296   const size_t rows,ExceptionInfo *exception)
2297 {
2298   if ((columns == 0) || (rows == 0))
2299     return(MagickFalse);
2300   image->columns=columns;
2301   image->rows=rows;
2302   return(SyncImagePixelCache(image,exception));
2303 }
2304 \f
2305 /*
2306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2307 %                                                                             %
2308 %                                                                             %
2309 %                                                                             %
2310 +   S e t I m a g e I n f o                                                   %
2311 %                                                                             %
2312 %                                                                             %
2313 %                                                                             %
2314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2315 %
2316 %  SetImageInfo() initializes the 'magick' field of the ImageInfo structure.
2317 %  It is set to a type of image format based on the prefix or suffix of the
2318 %  filename.  For example, 'ps:image' returns PS indicating a Postscript image.
2319 %  JPEG is returned for this filename: 'image.jpg'.  The filename prefix has
2320 %  precendence over the suffix.  Use an optional index enclosed in brackets
2321 %  after a file name to specify a desired scene of a multi-resolution image
2322 %  format like Photo CD (e.g. img0001.pcd[4]).  A True (non-zero) return value
2323 %  indicates success.
2324 %
2325 %  The format of the SetImageInfo method is:
2326 %
2327 %      MagickBooleanType SetImageInfo(ImageInfo *image_info,
2328 %        const unsigned int frames,ExceptionInfo *exception)
2329 %
2330 %  A description of each parameter follows:
2331 %
2332 %    o image_info: the image info.
2333 %
2334 %    o frames: the number of images you intend to write.
2335 %
2336 %    o exception: return any errors or warnings in this structure.
2337 %
2338 */
2339 MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
2340   const unsigned int frames,ExceptionInfo *exception)
2341 {
2342   char
2343     extension[MaxTextExtent],
2344     filename[MaxTextExtent],
2345     magic[MaxTextExtent],
2346     *q,
2347     subimage[MaxTextExtent];
2348
2349   const MagicInfo
2350     *magic_info;
2351
2352   const MagickInfo
2353     *magick_info;
2354
2355   ExceptionInfo
2356     *sans_exception;
2357
2358   Image
2359     *image;
2360
2361   MagickBooleanType
2362     status;
2363
2364   register const char
2365     *p;
2366
2367   ssize_t
2368     count;
2369
2370   unsigned char
2371     magick[2*MaxTextExtent];
2372
2373   /*
2374     Look for 'image.format' in filename.
2375   */
2376   assert(image_info != (ImageInfo *) NULL);
2377   assert(image_info->signature == MagickSignature);
2378   if (image_info->debug != MagickFalse)
2379     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2380       image_info->filename);
2381   *subimage='\0';
2382   if (frames == 0)
2383     {
2384       GetPathComponent(image_info->filename,SubimagePath,subimage);
2385       if (*subimage != '\0')
2386         {
2387           /*
2388             Look for scene specification (e.g. img0001.pcd[4]).
2389           */
2390           if (IsSceneGeometry(subimage,MagickFalse) == MagickFalse)
2391             {
2392               if (IsGeometry(subimage) != MagickFalse)
2393                 (void) CloneString(&image_info->extract,subimage);
2394             }
2395           else
2396             {
2397               size_t
2398                 first,
2399                 last;
2400
2401               (void) CloneString(&image_info->scenes,subimage);
2402               image_info->scene=StringToUnsignedLong(image_info->scenes);
2403               image_info->number_scenes=image_info->scene;
2404               p=image_info->scenes;
2405               for (q=(char *) image_info->scenes; *q != '\0'; p++)
2406               {
2407                 while ((isspace((int) ((unsigned char) *p)) != 0) ||
2408                        (*p == ','))
2409                   p++;
2410                 first=(size_t) strtol(p,&q,10);
2411                 last=first;
2412                 while (isspace((int) ((unsigned char) *q)) != 0)
2413                   q++;
2414                 if (*q == '-')
2415                   last=(size_t) strtol(q+1,&q,10);
2416                 if (first > last)
2417                   Swap(first,last);
2418                 if (first < image_info->scene)
2419                   image_info->scene=first;
2420                 if (last > image_info->number_scenes)
2421                   image_info->number_scenes=last;
2422                 p=q;
2423               }
2424               image_info->number_scenes-=image_info->scene-1;
2425             }
2426         }
2427     }
2428   *extension='\0';
2429   GetPathComponent(image_info->filename,ExtensionPath,extension);
2430 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2431   if (*extension != '\0')
2432     if ((LocaleCompare(extension,"gz") == 0) ||
2433         (LocaleCompare(extension,"Z") == 0) ||
2434         (LocaleCompare(extension,"svgz") == 0) ||
2435         (LocaleCompare(extension,"wmz") == 0))
2436       {
2437         char
2438           path[MaxTextExtent];
2439
2440         (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
2441         path[strlen(path)-strlen(extension)-1]='\0';
2442         GetPathComponent(path,ExtensionPath,extension);
2443       }
2444 #endif
2445 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2446   if (*extension != '\0')
2447     if (LocaleCompare(extension,"bz2") == 0)
2448       {
2449         char
2450           path[MaxTextExtent];
2451
2452         (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
2453         path[strlen(path)-strlen(extension)-1]='\0';
2454         GetPathComponent(path,ExtensionPath,extension);
2455       }
2456 #endif
2457   image_info->affirm=MagickFalse;
2458   sans_exception=AcquireExceptionInfo();
2459   if (*extension != '\0')
2460     {
2461       MagickFormatType
2462         format_type;
2463
2464       register ssize_t
2465         i;
2466
2467       static const char
2468         *format_type_formats[] =
2469         {
2470           "AUTOTRACE",
2471           "BROWSE",
2472           "DCRAW",
2473           "EDIT",
2474           "EPHEMERAL",
2475           "LAUNCH",
2476           "MPEG:DECODE",
2477           "MPEG:ENCODE",
2478           "PRINT",
2479           "PS:ALPHA",
2480           "PS:CMYK",
2481           "PS:COLOR",
2482           "PS:GRAY",
2483           "PS:MONO",
2484           "SCAN",
2485           "SHOW",
2486           "WIN",
2487           (char *) NULL
2488         };
2489
2490       /*
2491         User specified image format.
2492       */
2493       (void) CopyMagickString(magic,extension,MaxTextExtent);
2494       LocaleUpper(magic);
2495       /*
2496         Look for explicit image formats.
2497       */
2498       format_type=UndefinedFormatType;
2499       i=0;
2500       while ((format_type == UndefinedFormatType) &&
2501              (format_type_formats[i] != (char *) NULL))
2502       {
2503         if ((*magic == *format_type_formats[i]) &&
2504             (LocaleCompare(magic,format_type_formats[i]) == 0))
2505           format_type=ExplicitFormatType;
2506         i++;
2507       }
2508       magick_info=GetMagickInfo(magic,sans_exception);
2509       if ((magick_info != (const MagickInfo *) NULL) &&
2510           (magick_info->format_type != UndefinedFormatType))
2511         format_type=magick_info->format_type;
2512       if (format_type == UndefinedFormatType)
2513         (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
2514       else
2515         if (format_type == ExplicitFormatType)
2516           {
2517             image_info->affirm=MagickTrue;
2518             (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
2519           }
2520       if (LocaleCompare(magic,"RGB") == 0)
2521         image_info->affirm=MagickFalse;  /* maybe SGI disguised as RGB */
2522     }
2523   /*
2524     Look for explicit 'format:image' in filename.
2525   */
2526   *magic='\0';
2527   GetPathComponent(image_info->filename,MagickPath,magic);
2528   if (*magic == '\0')
2529     (void) CopyMagickString(magic,image_info->magick,MaxTextExtent);
2530   else
2531     {
2532       /*
2533         User specified image format.
2534       */
2535       LocaleUpper(magic);
2536       if (IsMagickConflict(magic) == MagickFalse)
2537         {
2538           (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
2539           if (LocaleCompare(magic,"EPHEMERAL") != 0)
2540             image_info->affirm=MagickTrue;
2541           else
2542             image_info->temporary=MagickTrue;
2543         }
2544     }
2545   magick_info=GetMagickInfo(magic,sans_exception);
2546   sans_exception=DestroyExceptionInfo(sans_exception);
2547   if ((magick_info == (const MagickInfo *) NULL) ||
2548       (GetMagickEndianSupport(magick_info) == MagickFalse))
2549     image_info->endian=UndefinedEndian;
2550   GetPathComponent(image_info->filename,CanonicalPath,filename);
2551   (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2552   if ((image_info->adjoin != MagickFalse) && (frames > 1))
2553     {
2554       /*
2555         Test for multiple image support (e.g. image%02d.png).
2556       */
2557       (void) InterpretImageFilename(image_info,(Image *) NULL,
2558         image_info->filename,(int) image_info->scene,filename,exception);
2559       if ((LocaleCompare(filename,image_info->filename) != 0) &&
2560           (strchr(filename,'%') == (char *) NULL))
2561         image_info->adjoin=MagickFalse;
2562     }
2563   if ((image_info->adjoin != MagickFalse) && (frames > 0))
2564     {
2565       /*
2566         Some image formats do not support multiple frames per file.
2567       */
2568       magick_info=GetMagickInfo(magic,exception);
2569       if (magick_info != (const MagickInfo *) NULL)
2570         if (GetMagickAdjoin(magick_info) == MagickFalse)
2571           image_info->adjoin=MagickFalse;
2572     }
2573   if (image_info->affirm != MagickFalse)
2574     return(MagickTrue);
2575   if (frames == 0)
2576     {
2577       /*
2578         Determine the image format from the first few bytes of the file.
2579       */
2580       image=AcquireImage(image_info,exception);
2581       (void) CopyMagickString(image->filename,image_info->filename,
2582         MaxTextExtent);
2583       status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2584       if (status == MagickFalse)
2585         {
2586           image=DestroyImage(image);
2587           return(MagickFalse);
2588         }
2589       if ((IsBlobSeekable(image) == MagickFalse) ||
2590           (IsBlobExempt(image) != MagickFalse))
2591         {
2592           /*
2593             Copy standard input or pipe to temporary file.
2594           */
2595           *filename='\0';
2596           status=ImageToFile(image,filename,exception);
2597           (void) CloseBlob(image);
2598           if (status == MagickFalse)
2599             {
2600               image=DestroyImage(image);
2601               return(MagickFalse);
2602             }
2603           SetImageInfoFile(image_info,(FILE *) NULL);
2604           (void) CopyMagickString(image->filename,filename,MaxTextExtent);
2605           status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2606           if (status == MagickFalse)
2607             {
2608               image=DestroyImage(image);
2609               return(MagickFalse);
2610             }
2611           (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2612           image_info->temporary=MagickTrue;
2613         }
2614       (void) ResetMagickMemory(magick,0,sizeof(magick));
2615       count=ReadBlob(image,2*MaxTextExtent,magick);
2616       (void) SeekBlob(image,-((MagickOffsetType) count),SEEK_CUR);
2617       (void) CloseBlob(image);
2618       image=DestroyImage(image);
2619       /*
2620         Check magic.xml configuration file.
2621       */
2622       sans_exception=AcquireExceptionInfo();
2623       magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
2624       if ((magic_info != (const MagicInfo *) NULL) &&
2625           (GetMagicName(magic_info) != (char *) NULL))
2626         {
2627           (void) CopyMagickString(image_info->magick,GetMagicName(magic_info),
2628             MaxTextExtent);
2629           magick_info=GetMagickInfo(image_info->magick,sans_exception);
2630           if ((magick_info == (const MagickInfo *) NULL) ||
2631               (GetMagickEndianSupport(magick_info) == MagickFalse))
2632             image_info->endian=UndefinedEndian;
2633           sans_exception=DestroyExceptionInfo(sans_exception);
2634           return(MagickTrue);
2635         }
2636       magick_info=GetMagickInfo(image_info->magick,sans_exception);
2637       if ((magick_info == (const MagickInfo *) NULL) ||
2638           (GetMagickEndianSupport(magick_info) == MagickFalse))
2639         image_info->endian=UndefinedEndian;
2640       sans_exception=DestroyExceptionInfo(sans_exception);
2641     }
2642   return(MagickTrue);
2643 }
2644 \f
2645 /*
2646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2647 %                                                                             %
2648 %                                                                             %
2649 %                                                                             %
2650 %   S e t I m a g e I n f o B l o b                                           %
2651 %                                                                             %
2652 %                                                                             %
2653 %                                                                             %
2654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2655 %
2656 %  SetImageInfoBlob() sets the image info blob member.
2657 %
2658 %  The format of the SetImageInfoBlob method is:
2659 %
2660 %      void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
2661 %        const size_t length)
2662 %
2663 %  A description of each parameter follows:
2664 %
2665 %    o image_info: the image info.
2666 %
2667 %    o blob: the blob.
2668 %
2669 %    o length: the blob length.
2670 %
2671 */
2672 MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
2673   const size_t length)
2674 {
2675   assert(image_info != (ImageInfo *) NULL);
2676   assert(image_info->signature == MagickSignature);
2677   if (image_info->debug != MagickFalse)
2678     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2679       image_info->filename);
2680   image_info->blob=(void *) blob;
2681   image_info->length=length;
2682 }
2683 \f
2684 /*
2685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2686 %                                                                             %
2687 %                                                                             %
2688 %                                                                             %
2689 %   S e t I m a g e I n f o F i l e                                           %
2690 %                                                                             %
2691 %                                                                             %
2692 %                                                                             %
2693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2694 %
2695 %  SetImageInfoFile() sets the image info file member.
2696 %
2697 %  The format of the SetImageInfoFile method is:
2698 %
2699 %      void SetImageInfoFile(ImageInfo *image_info,FILE *file)
2700 %
2701 %  A description of each parameter follows:
2702 %
2703 %    o image_info: the image info.
2704 %
2705 %    o file: the file.
2706 %
2707 */
2708 MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
2709 {
2710   assert(image_info != (ImageInfo *) NULL);
2711   assert(image_info->signature == MagickSignature);
2712   if (image_info->debug != MagickFalse)
2713     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2714       image_info->filename);
2715   image_info->file=file;
2716 }
2717 \f
2718 /*
2719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2720 %                                                                             %
2721 %                                                                             %
2722 %                                                                             %
2723 %   S e t I m a g e M a s k                                                   %
2724 %                                                                             %
2725 %                                                                             %
2726 %                                                                             %
2727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2728 %
2729 %  SetImageMask() associates a mask with the image.  The mask must be the same
2730 %  dimensions as the image.
2731 %
2732 %  The format of the SetImageMask method is:
2733 %
2734 %      MagickBooleanType SetImageMask(Image *image,const Image *mask,
2735 %        ExceptionInfo *exception)
2736 %
2737 %  A description of each parameter follows:
2738 %
2739 %    o image: the image.
2740 %
2741 %    o mask: the image mask.
2742 %
2743 %    o exception: return any errors or warnings in this structure.
2744 %
2745 */
2746 MagickExport MagickBooleanType SetImageMask(Image *image,const Image *mask,
2747   ExceptionInfo *exception)
2748 {
2749   CacheView
2750     *mask_view,
2751     *image_view;
2752
2753   MagickBooleanType
2754     status;
2755
2756   ssize_t
2757     y;
2758
2759   /*
2760     Set image mask.
2761   */
2762   assert(image != (Image *) NULL);
2763   if (image->debug != MagickFalse)
2764     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2765   assert(image->signature == MagickSignature);
2766   if (mask == (const Image *) NULL)
2767     {
2768       image->read_mask=MagickFalse;
2769       return(SyncImagePixelCache(image,exception));
2770     }
2771   image->read_mask=MagickTrue;
2772   if (SyncImagePixelCache(image,exception) == MagickFalse)
2773     return(MagickFalse);
2774   status=MagickTrue;
2775   mask_view=AcquireVirtualCacheView(mask,exception);
2776   image_view=AcquireAuthenticCacheView(image,exception);
2777 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2778   #pragma omp parallel for schedule(static,4) shared(status) \
2779     magick_threads(mask,image,1,1)
2780 #endif
2781   for (y=0; y < (ssize_t) image->rows; y++)
2782   {
2783     register const Quantum
2784       *restrict p;
2785
2786     register Quantum
2787       *restrict q;
2788
2789     register ssize_t
2790       x;
2791
2792     if (status == MagickFalse)
2793       continue;
2794     p=GetCacheViewVirtualPixels(mask_view,0,y,mask->columns,1,exception);
2795     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2796     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
2797       {
2798         status=MagickFalse;
2799         continue;
2800       }
2801     for (x=0; x < (ssize_t) image->columns; x++)
2802     {
2803       SetPixelReadMask(image,ClampToQuantum(GetPixelIntensity(mask,p)),q);
2804       p+=GetPixelChannels(mask);
2805       q+=GetPixelChannels(image);
2806     }
2807     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2808       status=MagickFalse;
2809   }
2810   mask_view=DestroyCacheView(mask_view);
2811   image_view=DestroyCacheView(image_view);
2812   return(status);
2813 }
2814 \f
2815 /*
2816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2817 %                                                                             %
2818 %                                                                             %
2819 %                                                                             %
2820 %     S e t I m a g e A l p h a                                               %
2821 %                                                                             %
2822 %                                                                             %
2823 %                                                                             %
2824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2825 %
2826 %  SetImageAlpha() sets the alpha levels of the image.
2827 %
2828 %  The format of the SetImageAlpha method is:
2829 %
2830 %      MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha,
2831 %        ExceptionInfo *exception)
2832 %
2833 %  A description of each parameter follows:
2834 %
2835 %    o image: the image.
2836 %
2837 %    o Alpha: the level of transparency: 0 is fully opaque and QuantumRange is
2838 %      fully transparent.
2839 %
2840 */
2841 MagickExport MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha,
2842   ExceptionInfo *exception)
2843 {
2844   CacheView
2845     *image_view;
2846
2847   MagickBooleanType
2848     status;
2849
2850   ssize_t
2851     y;
2852
2853   assert(image != (Image *) NULL);
2854   if (image->debug != MagickFalse)
2855     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2856   assert(image->signature == MagickSignature);
2857   image->alpha_trait=BlendPixelTrait;
2858   status=MagickTrue;
2859   image_view=AcquireAuthenticCacheView(image,exception);
2860 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2861   #pragma omp parallel for schedule(static,4) shared(status) \
2862     magick_threads(image,image,image->rows,1)
2863 #endif
2864   for (y=0; y < (ssize_t) image->rows; y++)
2865   {
2866     register Quantum
2867       *restrict q;
2868
2869     register ssize_t
2870       x;
2871
2872     if (status == MagickFalse)
2873       continue;
2874     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2875     if (q == (Quantum *) NULL)
2876       {
2877         status=MagickFalse;
2878         continue;
2879       }
2880     for (x=0; x < (ssize_t) image->columns; x++)
2881     {
2882       SetPixelAlpha(image,alpha,q);
2883       q+=GetPixelChannels(image);
2884     }
2885     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2886       status=MagickFalse;
2887   }
2888   image_view=DestroyCacheView(image_view);
2889   return(status);
2890 }
2891 \f
2892 /*
2893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894 %                                                                             %
2895 %                                                                             %
2896 %                                                                             %
2897 %   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                       %
2898 %                                                                             %
2899 %                                                                             %
2900 %                                                                             %
2901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902 %
2903 %  SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
2904 %  image and returns the previous setting.  A virtual pixel is any pixel access
2905 %  that is outside the boundaries of the image cache.
2906 %
2907 %  The format of the SetImageVirtualPixelMethod() method is:
2908 %
2909 %      VirtualPixelMethod SetImageVirtualPixelMethod(Image *image,
2910 %        const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
2911 %
2912 %  A description of each parameter follows:
2913 %
2914 %    o image: the image.
2915 %
2916 %    o virtual_pixel_method: choose the type of virtual pixel.
2917 %
2918 %    o exception: return any errors or warnings in this structure.
2919 %
2920 */
2921 MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(Image *image,
2922   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
2923 {
2924   assert(image != (const Image *) NULL);
2925   assert(image->signature == MagickSignature);
2926   if (image->debug != MagickFalse)
2927     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2928   return(SetPixelCacheVirtualMethod(image,virtual_pixel_method,exception));
2929 }
2930 \f
2931 /*
2932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2933 %                                                                             %
2934 %                                                                             %
2935 %                                                                             %
2936 %     S m u s h I m a g e s                                                   %
2937 %                                                                             %
2938 %                                                                             %
2939 %                                                                             %
2940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2941 %
2942 %  SmushImages() takes all images from the current image pointer to the end
2943 %  of the image list and smushes them to each other top-to-bottom if the
2944 %  stack parameter is true, otherwise left-to-right.
2945 %
2946 %  The current gravity setting now effects how the image is justified in the
2947 %  final image.
2948 %
2949 %  The format of the SmushImages method is:
2950 %
2951 %      Image *SmushImages(const Image *images,const MagickBooleanType stack,
2952 %        ExceptionInfo *exception)
2953 %
2954 %  A description of each parameter follows:
2955 %
2956 %    o images: the image sequence.
2957 %
2958 %    o stack: A value other than 0 stacks the images top-to-bottom.
2959 %
2960 %    o offset: minimum distance in pixels between images.
2961 %
2962 %    o exception: return any errors or warnings in this structure.
2963 %
2964 */
2965
2966 static ssize_t SmushXGap(const Image *smush_image,const Image *images,
2967   const ssize_t offset,ExceptionInfo *exception)
2968 {
2969   CacheView
2970     *left_view,
2971     *right_view;
2972
2973   const Image
2974     *left_image,
2975     *right_image;
2976
2977   RectangleInfo
2978     left_geometry,
2979     right_geometry;
2980
2981   register const Quantum
2982     *p;
2983
2984   register ssize_t
2985     i,
2986     y;
2987
2988   size_t
2989     gap;
2990
2991   ssize_t
2992     x;
2993
2994   if (images->previous == (Image *) NULL)
2995     return(0);
2996   right_image=images;
2997   SetGeometry(smush_image,&right_geometry);
2998   GravityAdjustGeometry(right_image->columns,right_image->rows,
2999     right_image->gravity,&right_geometry);
3000   left_image=images->previous;
3001   SetGeometry(smush_image,&left_geometry);
3002   GravityAdjustGeometry(left_image->columns,left_image->rows,
3003     left_image->gravity,&left_geometry);
3004   gap=right_image->columns;
3005   left_view=AcquireVirtualCacheView(left_image,exception);
3006   right_view=AcquireVirtualCacheView(right_image,exception);
3007   for (y=0; y < (ssize_t) smush_image->rows; y++)
3008   {
3009     for (x=(ssize_t) left_image->columns-1; x > 0; x--)
3010     {
3011       p=GetCacheViewVirtualPixels(left_view,x,left_geometry.y+y,1,1,exception);
3012       if ((p == (const Quantum *) NULL) ||
3013           (GetPixelAlpha(left_image,p) != TransparentAlpha) ||
3014           ((left_image->columns-x-1) >= gap))
3015         break;
3016     }
3017     i=(ssize_t) left_image->columns-x-1;
3018     for (x=0; x < (ssize_t) right_image->columns; x++)
3019     {
3020       p=GetCacheViewVirtualPixels(right_view,x,right_geometry.y+y,1,1,
3021         exception);
3022       if ((p == (const Quantum *) NULL) ||
3023           (GetPixelAlpha(right_image,p) != TransparentAlpha) ||
3024           ((x+i) >= (ssize_t) gap))
3025         break;
3026     }
3027     if ((x+i) < (ssize_t) gap)
3028       gap=(size_t) (x+i);
3029   }
3030   right_view=DestroyCacheView(right_view);
3031   left_view=DestroyCacheView(left_view);
3032   if (y < (ssize_t) smush_image->rows)
3033     return(offset);
3034   return((ssize_t) gap-offset);
3035 }
3036
3037 static ssize_t SmushYGap(const Image *smush_image,const Image *images,
3038   const ssize_t offset,ExceptionInfo *exception)
3039 {
3040   CacheView
3041     *bottom_view,
3042     *top_view;
3043
3044   const Image
3045     *bottom_image,
3046     *top_image;
3047
3048   RectangleInfo
3049     bottom_geometry,
3050     top_geometry;
3051
3052   register const Quantum
3053     *p;
3054
3055   register ssize_t
3056     i,
3057     x;
3058
3059   size_t
3060     gap;
3061
3062   ssize_t
3063     y;
3064
3065   if (images->previous == (Image *) NULL)
3066     return(0);
3067   bottom_image=images;
3068   SetGeometry(smush_image,&bottom_geometry);
3069   GravityAdjustGeometry(bottom_image->columns,bottom_image->rows,
3070     bottom_image->gravity,&bottom_geometry);
3071   top_image=images->previous;
3072   SetGeometry(smush_image,&top_geometry);
3073   GravityAdjustGeometry(top_image->columns,top_image->rows,top_image->gravity,
3074     &top_geometry);
3075   gap=bottom_image->rows;
3076   top_view=AcquireVirtualCacheView(top_image,exception);
3077   bottom_view=AcquireVirtualCacheView(bottom_image,exception);
3078   for (x=0; x < (ssize_t) smush_image->columns; x++)
3079   {
3080     for (y=(ssize_t) top_image->rows-1; y > 0; y--)
3081     {
3082       p=GetCacheViewVirtualPixels(top_view,top_geometry.x+x,y,1,1,exception);
3083       if ((p == (const Quantum *) NULL) ||
3084           (GetPixelAlpha(top_image,p) != TransparentAlpha) ||
3085           ((top_image->rows-y-1) >= gap))
3086         break;
3087     }
3088     i=(ssize_t) top_image->rows-y-1;
3089     for (y=0; y < (ssize_t) bottom_image->rows; y++)
3090     {
3091       p=GetCacheViewVirtualPixels(bottom_view,bottom_geometry.x+x,y,1,1,
3092         exception);
3093       if ((p == (const Quantum *) NULL) ||
3094           (GetPixelAlpha(bottom_image,p) != TransparentAlpha) ||
3095           ((y+i) >= (ssize_t) gap))
3096         break;
3097     }
3098     if ((y+i) < (ssize_t) gap)
3099       gap=(size_t) (y+i);
3100   }
3101   bottom_view=DestroyCacheView(bottom_view);
3102   top_view=DestroyCacheView(top_view);
3103   if (x < (ssize_t) smush_image->columns)
3104     return(offset);
3105   return((ssize_t) gap-offset);
3106 }
3107
3108 MagickExport Image *SmushImages(const Image *images,
3109   const MagickBooleanType stack,const ssize_t offset,ExceptionInfo *exception)
3110 {
3111 #define SmushImageTag  "Smush/Image"
3112
3113   const Image
3114     *image;
3115
3116   Image
3117     *smush_image;
3118
3119   MagickBooleanType
3120     proceed,
3121     status;
3122
3123   MagickOffsetType
3124     n;
3125
3126   PixelTrait
3127     alpha_trait;
3128
3129   RectangleInfo
3130     geometry;
3131
3132   register const Image
3133     *next;
3134
3135   size_t
3136     height,
3137     number_images,
3138     width;
3139
3140   ssize_t
3141     x_offset,
3142     y_offset;
3143
3144   /*
3145     Compute maximum area of smushed area.
3146   */
3147   assert(images != (Image *) NULL);
3148   assert(images->signature == MagickSignature);
3149   if (images->debug != MagickFalse)
3150     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3151   assert(exception != (ExceptionInfo *) NULL);
3152   assert(exception->signature == MagickSignature);
3153   image=images;
3154   alpha_trait=image->alpha_trait;
3155   number_images=1;
3156   width=image->columns;
3157   height=image->rows;
3158   next=GetNextImageInList(image);
3159   for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
3160   {
3161     if (next->alpha_trait == BlendPixelTrait)
3162       alpha_trait=BlendPixelTrait;
3163     number_images++;
3164     if (stack != MagickFalse)
3165       {
3166         if (next->columns > width)
3167           width=next->columns;
3168         height+=next->rows;
3169         if (next->previous != (Image *) NULL)
3170           height+=offset;
3171         continue;
3172       }
3173     width+=next->columns;
3174     if (next->previous != (Image *) NULL)
3175       width+=offset;
3176     if (next->rows > height)
3177       height=next->rows;
3178   }
3179   /*
3180     Smush images.
3181   */
3182   smush_image=CloneImage(image,width,height,MagickTrue,exception);
3183   if (smush_image == (Image *) NULL)
3184     return((Image *) NULL);
3185   if (SetImageStorageClass(smush_image,DirectClass,exception) == MagickFalse)
3186     {
3187       smush_image=DestroyImage(smush_image);
3188       return((Image *) NULL);
3189     }
3190   smush_image->alpha_trait=alpha_trait;
3191   (void) SetImageBackgroundColor(smush_image,exception);
3192   status=MagickTrue;
3193   x_offset=0;
3194   y_offset=0;
3195   for (n=0; n < (MagickOffsetType) number_images; n++)
3196   {
3197     SetGeometry(smush_image,&geometry);
3198     GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry);
3199     if (stack != MagickFalse)
3200       {
3201         x_offset-=geometry.x;
3202         y_offset-=SmushYGap(smush_image,image,offset,exception);
3203       }
3204     else
3205       {
3206         x_offset-=SmushXGap(smush_image,image,offset,exception);
3207         y_offset-=geometry.y;
3208       }
3209     status=CompositeImage(smush_image,image,OverCompositeOp,MagickTrue,x_offset,
3210       y_offset,exception);
3211     proceed=SetImageProgress(image,SmushImageTag,n,number_images);
3212     if (proceed == MagickFalse)
3213       break;
3214     if (stack == MagickFalse)
3215       {
3216         x_offset+=(ssize_t) image->columns;
3217         y_offset=0;
3218       }
3219     else
3220       {
3221         x_offset=0;
3222         y_offset+=(ssize_t) image->rows;
3223       }
3224     image=GetNextImageInList(image);
3225   }
3226   if (stack == MagickFalse)
3227     smush_image->columns=(size_t) x_offset;
3228   else
3229     smush_image->rows=(size_t) y_offset;
3230   if (status == MagickFalse)
3231     smush_image=DestroyImage(smush_image);
3232   return(smush_image);
3233 }
3234 \f
3235 /*
3236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3237 %                                                                             %
3238 %                                                                             %
3239 %                                                                             %
3240 %   S t r i p I m a g e                                                       %
3241 %                                                                             %
3242 %                                                                             %
3243 %                                                                             %
3244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3245 %
3246 %  StripImage() strips an image of all profiles and comments.
3247 %
3248 %  The format of the StripImage method is:
3249 %
3250 %      MagickBooleanType StripImage(Image *image,ExceptionInfo *exception)
3251 %
3252 %  A description of each parameter follows:
3253 %
3254 %    o image: the image.
3255 %
3256 %    o exception: return any errors or warnings in this structure.
3257 %
3258 */
3259 MagickExport MagickBooleanType StripImage(Image *image,ExceptionInfo *exception)
3260 {
3261   MagickBooleanType
3262     status;
3263
3264   assert(image != (Image *) NULL);
3265   if (image->debug != MagickFalse)
3266     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3267   (void) exception;
3268   DestroyImageProfiles(image);
3269   (void) DeleteImageProperty(image,"comment");
3270   (void) DeleteImageProperty(image,"date:create");
3271   (void) DeleteImageProperty(image,"date:modify");
3272   status=SetImageArtifact(image,"png:include-chunk","none,trns,gama");
3273   return(status);
3274 }
3275 \f
3276 /*
3277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3278 %                                                                             %
3279 %                                                                             %
3280 %                                                                             %
3281 +   S y n c I m a g e                                                         %
3282 %                                                                             %
3283 %                                                                             %
3284 %                                                                             %
3285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3286 %
3287 %  SyncImage() initializes the red, green, and blue intensities of each pixel
3288 %  as defined by the colormap index.
3289 %
3290 %  The format of the SyncImage method is:
3291 %
3292 %      MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception)
3293 %
3294 %  A description of each parameter follows:
3295 %
3296 %    o image: the image.
3297 %
3298 %    o exception: return any errors or warnings in this structure.
3299 %
3300 */
3301
3302 static inline Quantum PushColormapIndex(Image *image,const Quantum index,
3303   MagickBooleanType *range_exception)
3304 {
3305   if ((size_t) index < image->colors)
3306     return(index);
3307   *range_exception=MagickTrue;
3308   return((Quantum) 0);
3309 }
3310
3311 MagickExport MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception)
3312 {
3313   CacheView
3314     *image_view;
3315
3316   MagickBooleanType
3317     range_exception,
3318     status;
3319
3320   ssize_t
3321     y;
3322
3323   assert(image != (Image *) NULL);
3324   if (image->debug != MagickFalse)
3325     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3326   assert(image->signature == MagickSignature);
3327   if (image->storage_class == DirectClass)
3328     return(MagickFalse);
3329   range_exception=MagickFalse;
3330   status=MagickTrue;
3331   image_view=AcquireAuthenticCacheView(image,exception);
3332 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3333   #pragma omp parallel for schedule(static,4) shared(range_exception,status) \
3334     magick_threads(image,image,image->rows,1)
3335 #endif
3336   for (y=0; y < (ssize_t) image->rows; y++)
3337   {
3338     Quantum
3339       index;
3340
3341     register Quantum
3342       *restrict q;
3343
3344     register ssize_t
3345       x;
3346
3347     if (status == MagickFalse)
3348       continue;
3349     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3350     if (q == (Quantum *) NULL)
3351       {
3352         status=MagickFalse;
3353         continue;
3354       }
3355     for (x=0; x < (ssize_t) image->columns; x++)
3356     {
3357       index=PushColormapIndex(image,GetPixelIndex(image,q),&range_exception);
3358       SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
3359       q+=GetPixelChannels(image);
3360     }
3361     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3362       status=MagickFalse;
3363   }
3364   image_view=DestroyCacheView(image_view);
3365   if ((image->ping == MagickFalse) && (range_exception != MagickFalse))
3366     (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
3367       "InvalidColormapIndex","`%s'",image->filename);
3368   return(status);
3369 }
3370 \f
3371 /*
3372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3373 %                                                                             %
3374 %                                                                             %
3375 %                                                                             %
3376 %   S y n c I m a g e S e t t i n g s                                         %
3377 %                                                                             %
3378 %                                                                             %
3379 %                                                                             %
3380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3381 %
3382 %  SyncImageSettings() syncs any image_info global options into per-image
3383 %  attributes.
3384 %
3385 %  Note: in IMv6 free form 'options' were always mapped into 'artifacts', so
3386 %  that operations and coders can find such settings.  In IMv7 if a desired
3387 %  per-image artifact is not set, then it will directly look for a global
3388 %  option as a fallback, as such this copy is no longer needed, only the
3389 %  link set up.
3390 %
3391 %  The format of the SyncImageSettings method is:
3392 %
3393 %      MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3394 %        Image *image,ExceptionInfo *exception)
3395 %      MagickBooleanType SyncImagesSettings(const ImageInfo *image_info,
3396 %        Image *image,ExceptionInfo *exception)
3397 %
3398 %  A description of each parameter follows:
3399 %
3400 %    o image_info: the image info.
3401 %
3402 %    o image: the image.
3403 %
3404 %    o exception: return any errors or warnings in this structure.
3405 %
3406 */
3407
3408 MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info,
3409   Image *images,ExceptionInfo *exception)
3410 {
3411   Image
3412     *image;
3413
3414   assert(image_info != (const ImageInfo *) NULL);
3415   assert(image_info->signature == MagickSignature);
3416   assert(images != (Image *) NULL);
3417   assert(images->signature == MagickSignature);
3418   if (images->debug != MagickFalse)
3419     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3420   image=images;
3421   for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
3422     (void) SyncImageSettings(image_info,image,exception);
3423   (void) DeleteImageOption(image_info,"page");
3424   return(MagickTrue);
3425 }
3426
3427 MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3428   Image *image,ExceptionInfo *exception)
3429 {
3430   const char
3431     *option;
3432
3433   GeometryInfo
3434     geometry_info;
3435
3436   MagickStatusType
3437     flags;
3438
3439   ResolutionType
3440     units;
3441
3442   /*
3443     Sync image options.
3444   */
3445   assert(image_info != (const ImageInfo *) NULL);
3446   assert(image_info->signature == MagickSignature);
3447   assert(image != (Image *) NULL);
3448   assert(image->signature == MagickSignature);
3449   if (image->debug != MagickFalse)
3450     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3451   option=GetImageOption(image_info,"background");
3452   if (option != (const char *) NULL)
3453     (void) QueryColorCompliance(option,AllCompliance,&image->background_color,
3454       exception);
3455   option=GetImageOption(image_info,"black-point-compensation");
3456   if (option != (const char *) NULL)
3457     image->black_point_compensation=(MagickBooleanType) ParseCommandOption(
3458       MagickBooleanOptions,MagickFalse,option);
3459   option=GetImageOption(image_info,"blue-primary");
3460   if (option != (const char *) NULL)
3461     {
3462       flags=ParseGeometry(option,&geometry_info);
3463       image->chromaticity.blue_primary.x=geometry_info.rho;
3464       image->chromaticity.blue_primary.y=geometry_info.sigma;
3465       if ((flags & SigmaValue) == 0)
3466         image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x;
3467     }
3468   option=GetImageOption(image_info,"bordercolor");
3469   if (option != (const char *) NULL)
3470     (void) QueryColorCompliance(option,AllCompliance,&image->border_color,
3471       exception);
3472   option=GetImageOption(image_info,"channel");
3473   if (option != (const char *) NULL)
3474     (void) SetPixelChannelMask(image,(ChannelType)
3475       ParseChannelOption(option));
3476   /* FUTURE: do not sync compose to per-image compose setting here */
3477   option=GetImageOption(image_info,"compose");
3478   if (option != (const char *) NULL)
3479     image->compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3480       MagickFalse,option);
3481   /* -- */
3482   option=GetImageOption(image_info,"compress");
3483   if (option != (const char *) NULL)
3484     image->compression=(CompressionType) ParseCommandOption(
3485       MagickCompressOptions,MagickFalse,option);
3486   option=GetImageOption(image_info,"debug");
3487   if (option != (const char *) NULL)
3488     image->debug=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions,
3489       MagickFalse,option);
3490   option=GetImageOption(image_info,"density");
3491   if (option != (const char *) NULL)
3492     {
3493       GeometryInfo
3494         geometry_info;
3495
3496       flags=ParseGeometry(option,&geometry_info);
3497       image->resolution.x=geometry_info.rho;
3498       image->resolution.y=geometry_info.sigma;
3499       if ((flags & SigmaValue) == 0)
3500         image->resolution.y=image->resolution.x;
3501     }
3502   option=GetImageOption(image_info,"depth");
3503   if (option != (const char *) NULL)
3504     image->depth=StringToUnsignedLong(option);
3505   option=GetImageOption(image_info,"endian");
3506   if (option != (const char *) NULL)
3507     image->endian=(EndianType) ParseCommandOption(MagickEndianOptions,
3508       MagickFalse,option);
3509   option=GetImageOption(image_info,"filter");
3510   if (option != (const char *) NULL)
3511     image->filter=(FilterTypes) ParseCommandOption(MagickFilterOptions,
3512       MagickFalse,option);
3513   option=GetImageOption(image_info,"fuzz");
3514   if (option != (const char *) NULL)
3515     image->fuzz=StringToDoubleInterval(option,(double) QuantumRange+1.0);
3516   option=GetImageOption(image_info,"gravity");
3517   if (option != (const char *) NULL)
3518     image->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
3519       MagickFalse,option);
3520   option=GetImageOption(image_info,"green-primary");
3521   if (option != (const char *) NULL)
3522     {
3523       flags=ParseGeometry(option,&geometry_info);
3524       image->chromaticity.green_primary.x=geometry_info.rho;
3525       image->chromaticity.green_primary.y=geometry_info.sigma;
3526       if ((flags & SigmaValue) == 0)
3527         image->chromaticity.green_primary.y=image->chromaticity.green_primary.x;
3528     }
3529   option=GetImageOption(image_info,"intent");
3530   if (option != (const char *) NULL)
3531     image->rendering_intent=(RenderingIntent) ParseCommandOption(
3532       MagickIntentOptions,MagickFalse,option);
3533   option=GetImageOption(image_info,"intensity");
3534   if (option != (const char *) NULL)
3535     image->intensity=(PixelIntensityMethod) ParseCommandOption(
3536       MagickPixelIntensityOptions,MagickFalse,option);
3537   option=GetImageOption(image_info,"interlace");
3538   if (option != (const char *) NULL)
3539     image->interlace=(InterlaceType) ParseCommandOption(MagickInterlaceOptions,
3540       MagickFalse,option);
3541   option=GetImageOption(image_info,"interpolate");
3542   if (option != (const char *) NULL)
3543     image->interpolate=(PixelInterpolateMethod) ParseCommandOption(
3544       MagickInterpolateOptions,MagickFalse,option);
3545   option=GetImageOption(image_info,"loop");
3546   if (option != (const char *) NULL)
3547     image->iterations=StringToUnsignedLong(option);
3548   option=GetImageOption(image_info,"mattecolor");
3549   if (option != (const char *) NULL)
3550     (void) QueryColorCompliance(option,AllCompliance,&image->matte_color,
3551       exception);
3552   option=GetImageOption(image_info,"orient");
3553   if (option != (const char *) NULL)
3554     image->orientation=(OrientationType) ParseCommandOption(
3555       MagickOrientationOptions,MagickFalse,option);
3556   option=GetImageOption(image_info,"quality");
3557   if (option != (const char *) NULL)
3558     image->quality=StringToUnsignedLong(option);
3559   option=GetImageOption(image_info,"red-primary");
3560   if (option != (const char *) NULL)
3561     {
3562       flags=ParseGeometry(option,&geometry_info);
3563       image->chromaticity.red_primary.x=geometry_info.rho;
3564       image->chromaticity.red_primary.y=geometry_info.sigma;
3565       if ((flags & SigmaValue) == 0)
3566         image->chromaticity.red_primary.y=image->chromaticity.red_primary.x;
3567     }
3568   if (image_info->quality != UndefinedCompressionQuality)
3569     image->quality=image_info->quality;
3570   option=GetImageOption(image_info,"scene");
3571   if (option != (const char *) NULL)
3572     image->scene=StringToUnsignedLong(option);
3573   option=GetImageOption(image_info,"taint");
3574   if (option != (const char *) NULL)
3575     image->taint=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions,
3576       MagickFalse,option);
3577   option=GetImageOption(image_info,"tile-offset");
3578   if (option != (const char *) NULL)
3579     {
3580       char
3581         *geometry;
3582
3583       geometry=GetPageGeometry(option);
3584       flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
3585       geometry=DestroyString(geometry);
3586     }
3587   option=GetImageOption(image_info,"transparent-color");
3588   if (option != (const char *) NULL)
3589     (void) QueryColorCompliance(option,AllCompliance,&image->transparent_color,
3590       exception);
3591   option=GetImageOption(image_info,"type");
3592   if (option != (const char *) NULL)
3593     image->type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
3594       option);
3595   option=GetImageOption(image_info,"units");
3596   units=image_info->units;
3597   if (option != (const char *) NULL)
3598     units=(ResolutionType) ParseCommandOption(MagickResolutionOptions,
3599       MagickFalse,option);
3600   if (units != UndefinedResolution)
3601     {
3602       if (image->units != units)
3603         switch (image->units)
3604         {
3605           case PixelsPerInchResolution:
3606           {
3607             if (units == PixelsPerCentimeterResolution)
3608               {
3609                 image->resolution.x/=2.54;
3610                 image->resolution.y/=2.54;
3611               }
3612             break;
3613           }
3614           case PixelsPerCentimeterResolution:
3615           {
3616             if (units == PixelsPerInchResolution)
3617               {
3618                 image->resolution.x=(double) ((size_t) (100.0*2.54*
3619                   image->resolution.x+0.5))/100.0;
3620                 image->resolution.y=(double) ((size_t) (100.0*2.54*
3621                   image->resolution.y+0.5))/100.0;
3622               }
3623             break;
3624           }
3625           default:
3626             break;
3627         }
3628       image->units=units;
3629     }
3630   option=GetImageOption(image_info,"virtual-pixel");
3631   if (option != (const char *) NULL)
3632     (void) SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
3633       ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,option),
3634       exception);
3635   option=GetImageOption(image_info,"white-point");
3636   if (option != (const char *) NULL)
3637     {
3638       flags=ParseGeometry(option,&geometry_info);
3639       image->chromaticity.white_point.x=geometry_info.rho;
3640       image->chromaticity.white_point.y=geometry_info.sigma;
3641       if ((flags & SigmaValue) == 0)
3642         image->chromaticity.white_point.y=image->chromaticity.white_point.x;
3643     }
3644   ResetImageOptionIterator(image_info);
3645 #if 0
3646   {
3647     /* IMv6: Copy freeform global options into per-image artifacts, so
3648      * various operations and coders can access them.
3649      *
3650      * This has a problem, as per-image artefacts may have been set in
3651      * parenthesis, but may not be unset when parenthesis ends.
3652      */
3653     char
3654       property[MaxTextExtent];
3655
3656     const char
3657       *value;
3658
3659     for (option=GetNextImageOption(image_info); option != (const char *) NULL; )
3660     {
3661       value=GetImageOption(image_info,option);
3662       if (value != (const char *) NULL)
3663         {
3664           (void) FormatLocaleString(property,MaxTextExtent,"%s",option);
3665           (void) SetImageArtifact(image,property,value);
3666         }
3667       option=GetNextImageOption(image_info);
3668     }
3669   }
3670 #else
3671   /* IMv7: pointer to allow the lookup of pre-image artefact will fallback to
3672      a global option setting/define.  This saves a lot of duplication of
3673      global options into per-image artifacts, while ensuring only specifically
3674      set per-image artifacts are preverved when parenthesis ends.
3675
3676      This pointer is never explictally freed, as it is only used as a back
3677      reference, not as the main pointer to the image_info structure.  Images
3678      being removed from a image_info image list (or yet to be added to such),
3679      should have this pointer reset to NULL.
3680   */
3681   image->image_info=image_info;
3682 #endif
3683   return(MagickTrue);
3684 }