]> granicus.if.org Git - imagemagick/blob - MagickCore/image.c
(no commit message)
[imagemagick] / MagickCore / image.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                     IIIII  M   M   AAA    GGGG  EEEEE                       %
7 %                       I    MM MM  A   A  G      E                           %
8 %                       I    M M M  AAAAA  G  GG  EEE                         %
9 %                       I    M   M  A   A  G   G  E                           %
10 %                     IIIII  M   M  A   A   GGGG  EEEEE                       %
11 %                                                                             %
12 %                                                                             %
13 %                           MagickCore Image Methods                          %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-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=AcquireSemaphoreInfo();
212   image->signature=MagickSignature;
213   if (image_info == (ImageInfo *) NULL)
214     return(image);
215   /*
216     Transfer image info.
217   */
218   SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue :
219     MagickFalse);
220   (void) CopyMagickString(image->filename,image_info->filename,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=AcquireSemaphoreInfo();
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     RelinquishSemaphoreInfo(&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   GetPathComponent(image_info->filename,SubimagePath,subimage);
2383   if (*subimage != '\0')
2384     {
2385       /*
2386         Look for scene specification (e.g. img0001.pcd[4]).
2387       */
2388       if (IsSceneGeometry(subimage,MagickFalse) == MagickFalse)
2389         {
2390           if (IsGeometry(subimage) != MagickFalse)
2391             (void) CloneString(&image_info->extract,subimage);
2392         }
2393       else
2394         {
2395           size_t
2396             first,
2397             last;
2398
2399           (void) CloneString(&image_info->scenes,subimage);
2400           image_info->scene=StringToUnsignedLong(image_info->scenes);
2401           image_info->number_scenes=image_info->scene;
2402           p=image_info->scenes;
2403           for (q=(char *) image_info->scenes; *q != '\0'; p++)
2404           {
2405             while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
2406               p++;
2407             first=(size_t) strtol(p,&q,10);
2408             last=first;
2409             while (isspace((int) ((unsigned char) *q)) != 0)
2410               q++;
2411             if (*q == '-')
2412               last=(size_t) strtol(q+1,&q,10);
2413             if (first > last)
2414               Swap(first,last);
2415             if (first < image_info->scene)
2416               image_info->scene=first;
2417             if (last > image_info->number_scenes)
2418               image_info->number_scenes=last;
2419             p=q;
2420           }
2421           image_info->number_scenes-=image_info->scene-1;
2422         }
2423     }
2424   *extension='\0';
2425   GetPathComponent(image_info->filename,ExtensionPath,extension);
2426 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2427   if (*extension != '\0')
2428     if ((LocaleCompare(extension,"gz") == 0) ||
2429         (LocaleCompare(extension,"Z") == 0) ||
2430         (LocaleCompare(extension,"svgz") == 0) ||
2431         (LocaleCompare(extension,"wmz") == 0))
2432       {
2433         char
2434           path[MaxTextExtent];
2435
2436         (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
2437         path[strlen(path)-strlen(extension)-1]='\0';
2438         GetPathComponent(path,ExtensionPath,extension);
2439       }
2440 #endif
2441 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2442   if (*extension != '\0')
2443     if (LocaleCompare(extension,"bz2") == 0)
2444       {
2445         char
2446           path[MaxTextExtent];
2447
2448         (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
2449         path[strlen(path)-strlen(extension)-1]='\0';
2450         GetPathComponent(path,ExtensionPath,extension);
2451       }
2452 #endif
2453   image_info->affirm=MagickFalse;
2454   sans_exception=AcquireExceptionInfo();
2455   if (*extension != '\0')
2456     {
2457       MagickFormatType
2458         format_type;
2459
2460       register ssize_t
2461         i;
2462
2463       static const char
2464         *format_type_formats[] =
2465         {
2466           "AUTOTRACE",
2467           "BROWSE",
2468           "DCRAW",
2469           "EDIT",
2470           "EPHEMERAL",
2471           "LAUNCH",
2472           "MPEG:DECODE",
2473           "MPEG:ENCODE",
2474           "PRINT",
2475           "PS:ALPHA",
2476           "PS:CMYK",
2477           "PS:COLOR",
2478           "PS:GRAY",
2479           "PS:MONO",
2480           "SCAN",
2481           "SHOW",
2482           "WIN",
2483           (char *) NULL
2484         };
2485
2486       /*
2487         User specified image format.
2488       */
2489       (void) CopyMagickString(magic,extension,MaxTextExtent);
2490       LocaleUpper(magic);
2491       /*
2492         Look for explicit image formats.
2493       */
2494       format_type=UndefinedFormatType;
2495       i=0;
2496       while ((format_type == UndefinedFormatType) &&
2497              (format_type_formats[i] != (char *) NULL))
2498       {
2499         if ((*magic == *format_type_formats[i]) &&
2500             (LocaleCompare(magic,format_type_formats[i]) == 0))
2501           format_type=ExplicitFormatType;
2502         i++;
2503       }
2504       magick_info=GetMagickInfo(magic,sans_exception);
2505       if ((magick_info != (const MagickInfo *) NULL) &&
2506           (magick_info->format_type != UndefinedFormatType))
2507         format_type=magick_info->format_type;
2508       if (format_type == UndefinedFormatType)
2509         (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
2510       else
2511         if (format_type == ExplicitFormatType)
2512           {
2513             image_info->affirm=MagickTrue;
2514             (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
2515           }
2516       if (LocaleCompare(magic,"RGB") == 0)
2517         image_info->affirm=MagickFalse;  /* maybe SGI disguised as RGB */
2518     }
2519   /*
2520     Look for explicit 'format:image' in filename.
2521   */
2522   *magic='\0';
2523   GetPathComponent(image_info->filename,MagickPath,magic);
2524   if (*magic == '\0')
2525     (void) CopyMagickString(magic,image_info->magick,MaxTextExtent);
2526   else
2527     {
2528       /*
2529         User specified image format.
2530       */
2531       LocaleUpper(magic);
2532       if (IsMagickConflict(magic) == MagickFalse)
2533         {
2534           (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
2535           if (LocaleCompare(magic,"EPHEMERAL") != 0)
2536             image_info->affirm=MagickTrue;
2537           else
2538             image_info->temporary=MagickTrue;
2539         }
2540     }
2541   magick_info=GetMagickInfo(magic,sans_exception);
2542   sans_exception=DestroyExceptionInfo(sans_exception);
2543   if ((magick_info == (const MagickInfo *) NULL) ||
2544       (GetMagickEndianSupport(magick_info) == MagickFalse))
2545     image_info->endian=UndefinedEndian;
2546   GetPathComponent(image_info->filename,CanonicalPath,filename);
2547   (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2548   if ((image_info->adjoin != MagickFalse) && (frames > 1))
2549     {
2550       /*
2551         Test for multiple image support (e.g. image%02d.png).
2552       */
2553       (void) InterpretImageFilename(image_info,(Image *) NULL,
2554         image_info->filename,(int) image_info->scene,filename,exception);
2555       if ((LocaleCompare(filename,image_info->filename) != 0) &&
2556           (strchr(filename,'%') == (char *) NULL))
2557         image_info->adjoin=MagickFalse;
2558     }
2559   if ((image_info->adjoin != MagickFalse) && (frames > 0))
2560     {
2561       /*
2562         Some image formats do not support multiple frames per file.
2563       */
2564       magick_info=GetMagickInfo(magic,exception);
2565       if (magick_info != (const MagickInfo *) NULL)
2566         if (GetMagickAdjoin(magick_info) == MagickFalse)
2567           image_info->adjoin=MagickFalse;
2568     }
2569   if (image_info->affirm != MagickFalse)
2570     return(MagickTrue);
2571   if (frames == 0)
2572     {
2573       /*
2574         Determine the image format from the first few bytes of the file.
2575       */
2576       image=AcquireImage(image_info,exception);
2577       (void) CopyMagickString(image->filename,image_info->filename,
2578         MaxTextExtent);
2579       status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2580       if (status == MagickFalse)
2581         {
2582           image=DestroyImage(image);
2583           return(MagickFalse);
2584         }
2585       if ((IsBlobSeekable(image) == MagickFalse) ||
2586           (IsBlobExempt(image) != MagickFalse))
2587         {
2588           /*
2589             Copy standard input or pipe to temporary file.
2590           */
2591           *filename='\0';
2592           status=ImageToFile(image,filename,exception);
2593           (void) CloseBlob(image);
2594           if (status == MagickFalse)
2595             {
2596               image=DestroyImage(image);
2597               return(MagickFalse);
2598             }
2599           SetImageInfoFile(image_info,(FILE *) NULL);
2600           (void) CopyMagickString(image->filename,filename,MaxTextExtent);
2601           status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2602           if (status == MagickFalse)
2603             {
2604               image=DestroyImage(image);
2605               return(MagickFalse);
2606             }
2607           (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2608           image_info->temporary=MagickTrue;
2609         }
2610       (void) ResetMagickMemory(magick,0,sizeof(magick));
2611       count=ReadBlob(image,2*MaxTextExtent,magick);
2612       (void) SeekBlob(image,-((MagickOffsetType) count),SEEK_CUR);
2613       (void) CloseBlob(image);
2614       image=DestroyImage(image);
2615       /*
2616         Check magic.xml configuration file.
2617       */
2618       sans_exception=AcquireExceptionInfo();
2619       magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
2620       if ((magic_info != (const MagicInfo *) NULL) &&
2621           (GetMagicName(magic_info) != (char *) NULL))
2622         {
2623           (void) CopyMagickString(image_info->magick,GetMagicName(magic_info),
2624             MaxTextExtent);
2625           magick_info=GetMagickInfo(image_info->magick,sans_exception);
2626           if ((magick_info == (const MagickInfo *) NULL) ||
2627               (GetMagickEndianSupport(magick_info) == MagickFalse))
2628             image_info->endian=UndefinedEndian;
2629           sans_exception=DestroyExceptionInfo(sans_exception);
2630           return(MagickTrue);
2631         }
2632       magick_info=GetMagickInfo(image_info->magick,sans_exception);
2633       if ((magick_info == (const MagickInfo *) NULL) ||
2634           (GetMagickEndianSupport(magick_info) == MagickFalse))
2635         image_info->endian=UndefinedEndian;
2636       sans_exception=DestroyExceptionInfo(sans_exception);
2637     }
2638   return(MagickTrue);
2639 }
2640 \f
2641 /*
2642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2643 %                                                                             %
2644 %                                                                             %
2645 %                                                                             %
2646 %   S e t I m a g e I n f o B l o b                                           %
2647 %                                                                             %
2648 %                                                                             %
2649 %                                                                             %
2650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2651 %
2652 %  SetImageInfoBlob() sets the image info blob member.
2653 %
2654 %  The format of the SetImageInfoBlob method is:
2655 %
2656 %      void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
2657 %        const size_t length)
2658 %
2659 %  A description of each parameter follows:
2660 %
2661 %    o image_info: the image info.
2662 %
2663 %    o blob: the blob.
2664 %
2665 %    o length: the blob length.
2666 %
2667 */
2668 MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
2669   const size_t length)
2670 {
2671   assert(image_info != (ImageInfo *) NULL);
2672   assert(image_info->signature == MagickSignature);
2673   if (image_info->debug != MagickFalse)
2674     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2675       image_info->filename);
2676   image_info->blob=(void *) blob;
2677   image_info->length=length;
2678 }
2679 \f
2680 /*
2681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2682 %                                                                             %
2683 %                                                                             %
2684 %                                                                             %
2685 %   S e t I m a g e I n f o F i l e                                           %
2686 %                                                                             %
2687 %                                                                             %
2688 %                                                                             %
2689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2690 %
2691 %  SetImageInfoFile() sets the image info file member.
2692 %
2693 %  The format of the SetImageInfoFile method is:
2694 %
2695 %      void SetImageInfoFile(ImageInfo *image_info,FILE *file)
2696 %
2697 %  A description of each parameter follows:
2698 %
2699 %    o image_info: the image info.
2700 %
2701 %    o file: the file.
2702 %
2703 */
2704 MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
2705 {
2706   assert(image_info != (ImageInfo *) NULL);
2707   assert(image_info->signature == MagickSignature);
2708   if (image_info->debug != MagickFalse)
2709     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2710       image_info->filename);
2711   image_info->file=file;
2712 }
2713 \f
2714 /*
2715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2716 %                                                                             %
2717 %                                                                             %
2718 %                                                                             %
2719 %   S e t I m a g e M a s k                                                   %
2720 %                                                                             %
2721 %                                                                             %
2722 %                                                                             %
2723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2724 %
2725 %  SetImageMask() associates a mask with the image.  The mask must be the same
2726 %  dimensions as the image.
2727 %
2728 %  The format of the SetImageMask method is:
2729 %
2730 %      MagickBooleanType SetImageMask(Image *image,const Image *mask,
2731 %        ExceptionInfo *exception)
2732 %
2733 %  A description of each parameter follows:
2734 %
2735 %    o image: the image.
2736 %
2737 %    o mask: the image mask.
2738 %
2739 %    o exception: return any errors or warnings in this structure.
2740 %
2741 */
2742 MagickExport MagickBooleanType SetImageMask(Image *image,const Image *mask,
2743   ExceptionInfo *exception)
2744 {
2745   CacheView
2746     *mask_view,
2747     *image_view;
2748
2749   MagickBooleanType
2750     status;
2751
2752   ssize_t
2753     y;
2754
2755   /*
2756     Set image mask.
2757   */
2758   assert(image != (Image *) NULL);
2759   if (image->debug != MagickFalse)
2760     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2761   assert(image->signature == MagickSignature);
2762   if (mask == (const Image *) NULL)
2763     {
2764       image->read_mask=MagickFalse;
2765       return(SyncImagePixelCache(image,exception));
2766     }
2767   image->read_mask=MagickTrue;
2768   if (SyncImagePixelCache(image,exception) == MagickFalse)
2769     return(MagickFalse);
2770   status=MagickTrue;
2771   mask_view=AcquireVirtualCacheView(mask,exception);
2772   image_view=AcquireAuthenticCacheView(image,exception);
2773 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2774   #pragma omp parallel for schedule(static,4) shared(status) \
2775     magick_threads(mask,image,1,1)
2776 #endif
2777   for (y=0; y < (ssize_t) image->rows; y++)
2778   {
2779     register const Quantum
2780       *restrict p;
2781
2782     register Quantum
2783       *restrict q;
2784
2785     register ssize_t
2786       x;
2787
2788     if (status == MagickFalse)
2789       continue;
2790     p=GetCacheViewVirtualPixels(mask_view,0,y,mask->columns,1,exception);
2791     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2792     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
2793       {
2794         status=MagickFalse;
2795         continue;
2796       }
2797     for (x=0; x < (ssize_t) image->columns; x++)
2798     {
2799       SetPixelReadMask(image,ClampToQuantum(GetPixelIntensity(mask,p)),q);
2800       p+=GetPixelChannels(mask);
2801       q+=GetPixelChannels(image);
2802     }
2803     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2804       status=MagickFalse;
2805   }
2806   mask_view=DestroyCacheView(mask_view);
2807   image_view=DestroyCacheView(image_view);
2808   return(status);
2809 }
2810 \f
2811 /*
2812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2813 %                                                                             %
2814 %                                                                             %
2815 %                                                                             %
2816 %     S e t I m a g e A l p h a                                               %
2817 %                                                                             %
2818 %                                                                             %
2819 %                                                                             %
2820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2821 %
2822 %  SetImageAlpha() sets the alpha levels of the image.
2823 %
2824 %  The format of the SetImageAlpha method is:
2825 %
2826 %      MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha,
2827 %        ExceptionInfo *exception)
2828 %
2829 %  A description of each parameter follows:
2830 %
2831 %    o image: the image.
2832 %
2833 %    o Alpha: the level of transparency: 0 is fully opaque and QuantumRange is
2834 %      fully transparent.
2835 %
2836 */
2837 MagickExport MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha,
2838   ExceptionInfo *exception)
2839 {
2840   CacheView
2841     *image_view;
2842
2843   MagickBooleanType
2844     status;
2845
2846   ssize_t
2847     y;
2848
2849   assert(image != (Image *) NULL);
2850   if (image->debug != MagickFalse)
2851     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2852   assert(image->signature == MagickSignature);
2853   image->alpha_trait=BlendPixelTrait;
2854   status=MagickTrue;
2855   image_view=AcquireAuthenticCacheView(image,exception);
2856 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2857   #pragma omp parallel for schedule(static,4) shared(status) \
2858     magick_threads(image,image,image->rows,1)
2859 #endif
2860   for (y=0; y < (ssize_t) image->rows; y++)
2861   {
2862     register Quantum
2863       *restrict q;
2864
2865     register ssize_t
2866       x;
2867
2868     if (status == MagickFalse)
2869       continue;
2870     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2871     if (q == (Quantum *) NULL)
2872       {
2873         status=MagickFalse;
2874         continue;
2875       }
2876     for (x=0; x < (ssize_t) image->columns; x++)
2877     {
2878       SetPixelAlpha(image,alpha,q);
2879       q+=GetPixelChannels(image);
2880     }
2881     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2882       status=MagickFalse;
2883   }
2884   image_view=DestroyCacheView(image_view);
2885   return(status);
2886 }
2887 \f
2888 /*
2889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2890 %                                                                             %
2891 %                                                                             %
2892 %                                                                             %
2893 %   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                       %
2894 %                                                                             %
2895 %                                                                             %
2896 %                                                                             %
2897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2898 %
2899 %  SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
2900 %  image and returns the previous setting.  A virtual pixel is any pixel access
2901 %  that is outside the boundaries of the image cache.
2902 %
2903 %  The format of the SetImageVirtualPixelMethod() method is:
2904 %
2905 %      VirtualPixelMethod SetImageVirtualPixelMethod(Image *image,
2906 %        const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
2907 %
2908 %  A description of each parameter follows:
2909 %
2910 %    o image: the image.
2911 %
2912 %    o virtual_pixel_method: choose the type of virtual pixel.
2913 %
2914 %    o exception: return any errors or warnings in this structure.
2915 %
2916 */
2917 MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(Image *image,
2918   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
2919 {
2920   assert(image != (const Image *) NULL);
2921   assert(image->signature == MagickSignature);
2922   if (image->debug != MagickFalse)
2923     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2924   return(SetPixelCacheVirtualMethod(image,virtual_pixel_method,exception));
2925 }
2926 \f
2927 /*
2928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2929 %                                                                             %
2930 %                                                                             %
2931 %                                                                             %
2932 %     S m u s h I m a g e s                                                   %
2933 %                                                                             %
2934 %                                                                             %
2935 %                                                                             %
2936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2937 %
2938 %  SmushImages() takes all images from the current image pointer to the end
2939 %  of the image list and smushes them to each other top-to-bottom if the
2940 %  stack parameter is true, otherwise left-to-right.
2941 %
2942 %  The current gravity setting now effects how the image is justified in the
2943 %  final image.
2944 %
2945 %  The format of the SmushImages method is:
2946 %
2947 %      Image *SmushImages(const Image *images,const MagickBooleanType stack,
2948 %        ExceptionInfo *exception)
2949 %
2950 %  A description of each parameter follows:
2951 %
2952 %    o images: the image sequence.
2953 %
2954 %    o stack: A value other than 0 stacks the images top-to-bottom.
2955 %
2956 %    o offset: minimum distance in pixels between images.
2957 %
2958 %    o exception: return any errors or warnings in this structure.
2959 %
2960 */
2961
2962 static ssize_t SmushXGap(const Image *smush_image,const Image *images,
2963   const ssize_t offset,ExceptionInfo *exception)
2964 {
2965   CacheView
2966     *left_view,
2967     *right_view;
2968
2969   const Image
2970     *left_image,
2971     *right_image;
2972
2973   RectangleInfo
2974     left_geometry,
2975     right_geometry;
2976
2977   register const Quantum
2978     *p;
2979
2980   register ssize_t
2981     i,
2982     y;
2983
2984   size_t
2985     gap;
2986
2987   ssize_t
2988     x;
2989
2990   if (images->previous == (Image *) NULL)
2991     return(0);
2992   right_image=images;
2993   SetGeometry(smush_image,&right_geometry);
2994   GravityAdjustGeometry(right_image->columns,right_image->rows,
2995     right_image->gravity,&right_geometry);
2996   left_image=images->previous;
2997   SetGeometry(smush_image,&left_geometry);
2998   GravityAdjustGeometry(left_image->columns,left_image->rows,
2999     left_image->gravity,&left_geometry);
3000   gap=right_image->columns;
3001   left_view=AcquireVirtualCacheView(left_image,exception);
3002   right_view=AcquireVirtualCacheView(right_image,exception);
3003   for (y=0; y < (ssize_t) smush_image->rows; y++)
3004   {
3005     for (x=(ssize_t) left_image->columns-1; x > 0; x--)
3006     {
3007       p=GetCacheViewVirtualPixels(left_view,x,left_geometry.y+y,1,1,exception);
3008       if ((p == (const Quantum *) NULL) ||
3009           (GetPixelAlpha(left_image,p) != TransparentAlpha) ||
3010           ((left_image->columns-x-1) >= gap))
3011         break;
3012     }
3013     i=(ssize_t) left_image->columns-x-1;
3014     for (x=0; x < (ssize_t) right_image->columns; x++)
3015     {
3016       p=GetCacheViewVirtualPixels(right_view,x,right_geometry.y+y,1,1,
3017         exception);
3018       if ((p == (const Quantum *) NULL) ||
3019           (GetPixelAlpha(right_image,p) != TransparentAlpha) ||
3020           ((x+i) >= (ssize_t) gap))
3021         break;
3022     }
3023     if ((x+i) < (ssize_t) gap)
3024       gap=(size_t) (x+i);
3025   }
3026   right_view=DestroyCacheView(right_view);
3027   left_view=DestroyCacheView(left_view);
3028   if (y < (ssize_t) smush_image->rows)
3029     return(offset);
3030   return((ssize_t) gap-offset);
3031 }
3032
3033 static ssize_t SmushYGap(const Image *smush_image,const Image *images,
3034   const ssize_t offset,ExceptionInfo *exception)
3035 {
3036   CacheView
3037     *bottom_view,
3038     *top_view;
3039
3040   const Image
3041     *bottom_image,
3042     *top_image;
3043
3044   RectangleInfo
3045     bottom_geometry,
3046     top_geometry;
3047
3048   register const Quantum
3049     *p;
3050
3051   register ssize_t
3052     i,
3053     x;
3054
3055   size_t
3056     gap;
3057
3058   ssize_t
3059     y;
3060
3061   if (images->previous == (Image *) NULL)
3062     return(0);
3063   bottom_image=images;
3064   SetGeometry(smush_image,&bottom_geometry);
3065   GravityAdjustGeometry(bottom_image->columns,bottom_image->rows,
3066     bottom_image->gravity,&bottom_geometry);
3067   top_image=images->previous;
3068   SetGeometry(smush_image,&top_geometry);
3069   GravityAdjustGeometry(top_image->columns,top_image->rows,top_image->gravity,
3070     &top_geometry);
3071   gap=bottom_image->rows;
3072   top_view=AcquireVirtualCacheView(top_image,exception);
3073   bottom_view=AcquireVirtualCacheView(bottom_image,exception);
3074   for (x=0; x < (ssize_t) smush_image->columns; x++)
3075   {
3076     for (y=(ssize_t) top_image->rows-1; y > 0; y--)
3077     {
3078       p=GetCacheViewVirtualPixels(top_view,top_geometry.x+x,y,1,1,exception);
3079       if ((p == (const Quantum *) NULL) ||
3080           (GetPixelAlpha(top_image,p) != TransparentAlpha) ||
3081           ((top_image->rows-y-1) >= gap))
3082         break;
3083     }
3084     i=(ssize_t) top_image->rows-y-1;
3085     for (y=0; y < (ssize_t) bottom_image->rows; y++)
3086     {
3087       p=GetCacheViewVirtualPixels(bottom_view,bottom_geometry.x+x,y,1,1,
3088         exception);
3089       if ((p == (const Quantum *) NULL) ||
3090           (GetPixelAlpha(bottom_image,p) != TransparentAlpha) ||
3091           ((y+i) >= (ssize_t) gap))
3092         break;
3093     }
3094     if ((y+i) < (ssize_t) gap)
3095       gap=(size_t) (y+i);
3096   }
3097   bottom_view=DestroyCacheView(bottom_view);
3098   top_view=DestroyCacheView(top_view);
3099   if (x < (ssize_t) smush_image->columns)
3100     return(offset);
3101   return((ssize_t) gap-offset);
3102 }
3103
3104 MagickExport Image *SmushImages(const Image *images,
3105   const MagickBooleanType stack,const ssize_t offset,ExceptionInfo *exception)
3106 {
3107 #define SmushImageTag  "Smush/Image"
3108
3109   const Image
3110     *image;
3111
3112   Image
3113     *smush_image;
3114
3115   MagickBooleanType
3116     proceed,
3117     status;
3118
3119   MagickOffsetType
3120     n;
3121
3122   PixelTrait
3123     alpha_trait;
3124
3125   RectangleInfo
3126     geometry;
3127
3128   register const Image
3129     *next;
3130
3131   size_t
3132     height,
3133     number_images,
3134     width;
3135
3136   ssize_t
3137     x_offset,
3138     y_offset;
3139
3140   /*
3141     Compute maximum area of smushed area.
3142   */
3143   assert(images != (Image *) NULL);
3144   assert(images->signature == MagickSignature);
3145   if (images->debug != MagickFalse)
3146     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3147   assert(exception != (ExceptionInfo *) NULL);
3148   assert(exception->signature == MagickSignature);
3149   image=images;
3150   alpha_trait=image->alpha_trait;
3151   number_images=1;
3152   width=image->columns;
3153   height=image->rows;
3154   next=GetNextImageInList(image);
3155   for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
3156   {
3157     if (next->alpha_trait == BlendPixelTrait)
3158       alpha_trait=BlendPixelTrait;
3159     number_images++;
3160     if (stack != MagickFalse)
3161       {
3162         if (next->columns > width)
3163           width=next->columns;
3164         height+=next->rows;
3165         if (next->previous != (Image *) NULL)
3166           height+=offset;
3167         continue;
3168       }
3169     width+=next->columns;
3170     if (next->previous != (Image *) NULL)
3171       width+=offset;
3172     if (next->rows > height)
3173       height=next->rows;
3174   }
3175   /*
3176     Smush images.
3177   */
3178   smush_image=CloneImage(image,width,height,MagickTrue,exception);
3179   if (smush_image == (Image *) NULL)
3180     return((Image *) NULL);
3181   if (SetImageStorageClass(smush_image,DirectClass,exception) == MagickFalse)
3182     {
3183       smush_image=DestroyImage(smush_image);
3184       return((Image *) NULL);
3185     }
3186   smush_image->alpha_trait=alpha_trait;
3187   (void) SetImageBackgroundColor(smush_image,exception);
3188   status=MagickTrue;
3189   x_offset=0;
3190   y_offset=0;
3191   for (n=0; n < (MagickOffsetType) number_images; n++)
3192   {
3193     SetGeometry(smush_image,&geometry);
3194     GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry);
3195     if (stack != MagickFalse)
3196       {
3197         x_offset-=geometry.x;
3198         y_offset-=SmushYGap(smush_image,image,offset,exception);
3199       }
3200     else
3201       {
3202         x_offset-=SmushXGap(smush_image,image,offset,exception);
3203         y_offset-=geometry.y;
3204       }
3205     status=CompositeImage(smush_image,image,OverCompositeOp,MagickTrue,x_offset,
3206       y_offset,exception);
3207     proceed=SetImageProgress(image,SmushImageTag,n,number_images);
3208     if (proceed == MagickFalse)
3209       break;
3210     if (stack == MagickFalse)
3211       {
3212         x_offset+=(ssize_t) image->columns;
3213         y_offset=0;
3214       }
3215     else
3216       {
3217         x_offset=0;
3218         y_offset+=(ssize_t) image->rows;
3219       }
3220     image=GetNextImageInList(image);
3221   }
3222   if (stack == MagickFalse)
3223     smush_image->columns=(size_t) x_offset;
3224   else
3225     smush_image->rows=(size_t) y_offset;
3226   if (status == MagickFalse)
3227     smush_image=DestroyImage(smush_image);
3228   return(smush_image);
3229 }
3230 \f
3231 /*
3232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3233 %                                                                             %
3234 %                                                                             %
3235 %                                                                             %
3236 %   S t r i p I m a g e                                                       %
3237 %                                                                             %
3238 %                                                                             %
3239 %                                                                             %
3240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3241 %
3242 %  StripImage() strips an image of all profiles and comments.
3243 %
3244 %  The format of the StripImage method is:
3245 %
3246 %      MagickBooleanType StripImage(Image *image,ExceptionInfo *exception)
3247 %
3248 %  A description of each parameter follows:
3249 %
3250 %    o image: the image.
3251 %
3252 %    o exception: return any errors or warnings in this structure.
3253 %
3254 */
3255 MagickExport MagickBooleanType StripImage(Image *image,ExceptionInfo *exception)
3256 {
3257   MagickBooleanType
3258     status;
3259
3260   assert(image != (Image *) NULL);
3261   if (image->debug != MagickFalse)
3262     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3263   (void) exception;
3264   DestroyImageProfiles(image);
3265   (void) DeleteImageProperty(image,"comment");
3266   (void) DeleteImageProperty(image,"date:create");
3267   (void) DeleteImageProperty(image,"date:modify");
3268   status=SetImageArtifact(image,"png:include-chunk","none,trns,gama");
3269   return(status);
3270 }
3271 \f
3272 /*
3273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3274 %                                                                             %
3275 %                                                                             %
3276 %                                                                             %
3277 +   S y n c I m a g e                                                         %
3278 %                                                                             %
3279 %                                                                             %
3280 %                                                                             %
3281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3282 %
3283 %  SyncImage() initializes the red, green, and blue intensities of each pixel
3284 %  as defined by the colormap index.
3285 %
3286 %  The format of the SyncImage method is:
3287 %
3288 %      MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception)
3289 %
3290 %  A description of each parameter follows:
3291 %
3292 %    o image: the image.
3293 %
3294 %    o exception: return any errors or warnings in this structure.
3295 %
3296 */
3297
3298 static inline Quantum PushColormapIndex(Image *image,const Quantum index,
3299   MagickBooleanType *range_exception)
3300 {
3301   if ((size_t) index < image->colors)
3302     return(index);
3303   *range_exception=MagickTrue;
3304   return((Quantum) 0);
3305 }
3306
3307 MagickExport MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception)
3308 {
3309   CacheView
3310     *image_view;
3311
3312   MagickBooleanType
3313     range_exception,
3314     status;
3315
3316   ssize_t
3317     y;
3318
3319   assert(image != (Image *) NULL);
3320   if (image->debug != MagickFalse)
3321     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3322   assert(image->signature == MagickSignature);
3323   if (image->storage_class == DirectClass)
3324     return(MagickFalse);
3325   range_exception=MagickFalse;
3326   status=MagickTrue;
3327   image_view=AcquireAuthenticCacheView(image,exception);
3328 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3329   #pragma omp parallel for schedule(static,4) shared(range_exception,status) \
3330     magick_threads(image,image,image->rows,1)
3331 #endif
3332   for (y=0; y < (ssize_t) image->rows; y++)
3333   {
3334     Quantum
3335       index;
3336
3337     register Quantum
3338       *restrict q;
3339
3340     register ssize_t
3341       x;
3342
3343     if (status == MagickFalse)
3344       continue;
3345     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3346     if (q == (Quantum *) NULL)
3347       {
3348         status=MagickFalse;
3349         continue;
3350       }
3351     for (x=0; x < (ssize_t) image->columns; x++)
3352     {
3353       index=PushColormapIndex(image,GetPixelIndex(image,q),&range_exception);
3354       SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
3355       q+=GetPixelChannels(image);
3356     }
3357     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3358       status=MagickFalse;
3359   }
3360   image_view=DestroyCacheView(image_view);
3361   if ((image->ping == MagickFalse) && (range_exception != MagickFalse))
3362     (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
3363       "InvalidColormapIndex","`%s'",image->filename);
3364   return(status);
3365 }
3366 \f
3367 /*
3368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3369 %                                                                             %
3370 %                                                                             %
3371 %                                                                             %
3372 %   S y n c I m a g e S e t t i n g s                                         %
3373 %                                                                             %
3374 %                                                                             %
3375 %                                                                             %
3376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3377 %
3378 %  SyncImageSettings() syncs any image_info global options into per-image
3379 %  attributes.
3380 %
3381 %  Note: in IMv6 free form 'options' were always mapped into 'artifacts', so
3382 %  that operations and coders can find such settings.  In IMv7 if a desired
3383 %  per-image artifact is not set, then it will directly look for a global
3384 %  option as a fallback, as such this copy is no longer needed, only the
3385 %  link set up.
3386 %
3387 %  The format of the SyncImageSettings method is:
3388 %
3389 %      MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3390 %        Image *image,ExceptionInfo *exception)
3391 %      MagickBooleanType SyncImagesSettings(const ImageInfo *image_info,
3392 %        Image *image,ExceptionInfo *exception)
3393 %
3394 %  A description of each parameter follows:
3395 %
3396 %    o image_info: the image info.
3397 %
3398 %    o image: the image.
3399 %
3400 %    o exception: return any errors or warnings in this structure.
3401 %
3402 */
3403
3404 MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info,
3405   Image *images,ExceptionInfo *exception)
3406 {
3407   Image
3408     *image;
3409
3410   assert(image_info != (const ImageInfo *) NULL);
3411   assert(image_info->signature == MagickSignature);
3412   assert(images != (Image *) NULL);
3413   assert(images->signature == MagickSignature);
3414   if (images->debug != MagickFalse)
3415     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3416   image=images;
3417   for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
3418     (void) SyncImageSettings(image_info,image,exception);
3419   (void) DeleteImageOption(image_info,"page");
3420   return(MagickTrue);
3421 }
3422
3423 MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3424   Image *image,ExceptionInfo *exception)
3425 {
3426   const char
3427     *option;
3428
3429   GeometryInfo
3430     geometry_info;
3431
3432   MagickStatusType
3433     flags;
3434
3435   ResolutionType
3436     units;
3437
3438   /*
3439     Sync image options.
3440   */
3441   assert(image_info != (const ImageInfo *) NULL);
3442   assert(image_info->signature == MagickSignature);
3443   assert(image != (Image *) NULL);
3444   assert(image->signature == MagickSignature);
3445   if (image->debug != MagickFalse)
3446     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3447   option=GetImageOption(image_info,"background");
3448   if (option != (const char *) NULL)
3449     (void) QueryColorCompliance(option,AllCompliance,&image->background_color,
3450       exception);
3451   option=GetImageOption(image_info,"black-point-compensation");
3452   if (option != (const char *) NULL)
3453     image->black_point_compensation=(MagickBooleanType) ParseCommandOption(
3454       MagickBooleanOptions,MagickFalse,option);
3455   option=GetImageOption(image_info,"blue-primary");
3456   if (option != (const char *) NULL)
3457     {
3458       flags=ParseGeometry(option,&geometry_info);
3459       image->chromaticity.blue_primary.x=geometry_info.rho;
3460       image->chromaticity.blue_primary.y=geometry_info.sigma;
3461       if ((flags & SigmaValue) == 0)
3462         image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x;
3463     }
3464   option=GetImageOption(image_info,"bordercolor");
3465   if (option != (const char *) NULL)
3466     (void) QueryColorCompliance(option,AllCompliance,&image->border_color,
3467       exception);
3468   option=GetImageOption(image_info,"channel");
3469   if (option != (const char *) NULL)
3470     (void) SetPixelChannelMask(image,(ChannelType)
3471       ParseChannelOption(option));
3472   /* FUTURE: do not sync compose to per-image compose setting here */
3473   option=GetImageOption(image_info,"compose");
3474   if (option != (const char *) NULL)
3475     image->compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3476       MagickFalse,option);
3477   /* -- */
3478   option=GetImageOption(image_info,"compress");
3479   if (option != (const char *) NULL)
3480     image->compression=(CompressionType) ParseCommandOption(
3481       MagickCompressOptions,MagickFalse,option);
3482   option=GetImageOption(image_info,"debug");
3483   if (option != (const char *) NULL)
3484     image->debug=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions,
3485       MagickFalse,option);
3486   option=GetImageOption(image_info,"density");
3487   if (option != (const char *) NULL)
3488     {
3489       GeometryInfo
3490         geometry_info;
3491
3492       flags=ParseGeometry(option,&geometry_info);
3493       image->resolution.x=geometry_info.rho;
3494       image->resolution.y=geometry_info.sigma;
3495       if ((flags & SigmaValue) == 0)
3496         image->resolution.y=image->resolution.x;
3497     }
3498   option=GetImageOption(image_info,"depth");
3499   if (option != (const char *) NULL)
3500     image->depth=StringToUnsignedLong(option);
3501   option=GetImageOption(image_info,"endian");
3502   if (option != (const char *) NULL)
3503     image->endian=(EndianType) ParseCommandOption(MagickEndianOptions,
3504       MagickFalse,option);
3505   option=GetImageOption(image_info,"filter");
3506   if (option != (const char *) NULL)
3507     image->filter=(FilterTypes) ParseCommandOption(MagickFilterOptions,
3508       MagickFalse,option);
3509   option=GetImageOption(image_info,"fuzz");
3510   if (option != (const char *) NULL)
3511     image->fuzz=StringToDoubleInterval(option,(double) QuantumRange+1.0);
3512   option=GetImageOption(image_info,"gravity");
3513   if (option != (const char *) NULL)
3514     image->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
3515       MagickFalse,option);
3516   option=GetImageOption(image_info,"green-primary");
3517   if (option != (const char *) NULL)
3518     {
3519       flags=ParseGeometry(option,&geometry_info);
3520       image->chromaticity.green_primary.x=geometry_info.rho;
3521       image->chromaticity.green_primary.y=geometry_info.sigma;
3522       if ((flags & SigmaValue) == 0)
3523         image->chromaticity.green_primary.y=image->chromaticity.green_primary.x;
3524     }
3525   option=GetImageOption(image_info,"intent");
3526   if (option != (const char *) NULL)
3527     image->rendering_intent=(RenderingIntent) ParseCommandOption(
3528       MagickIntentOptions,MagickFalse,option);
3529   option=GetImageOption(image_info,"intensity");
3530   if (option != (const char *) NULL)
3531     image->intensity=(PixelIntensityMethod) ParseCommandOption(
3532       MagickPixelIntensityOptions,MagickFalse,option);
3533   option=GetImageOption(image_info,"interlace");
3534   if (option != (const char *) NULL)
3535     image->interlace=(InterlaceType) ParseCommandOption(MagickInterlaceOptions,
3536       MagickFalse,option);
3537   option=GetImageOption(image_info,"interpolate");
3538   if (option != (const char *) NULL)
3539     image->interpolate=(PixelInterpolateMethod) ParseCommandOption(
3540       MagickInterpolateOptions,MagickFalse,option);
3541   option=GetImageOption(image_info,"loop");
3542   if (option != (const char *) NULL)
3543     image->iterations=StringToUnsignedLong(option);
3544   option=GetImageOption(image_info,"mattecolor");
3545   if (option != (const char *) NULL)
3546     (void) QueryColorCompliance(option,AllCompliance,&image->matte_color,
3547       exception);
3548   option=GetImageOption(image_info,"orient");
3549   if (option != (const char *) NULL)
3550     image->orientation=(OrientationType) ParseCommandOption(
3551       MagickOrientationOptions,MagickFalse,option);
3552   option=GetImageOption(image_info,"page");
3553   if (option != (const char *) NULL)
3554     {
3555       char
3556         *geometry;
3557
3558       geometry=GetPageGeometry(option);
3559       flags=ParseAbsoluteGeometry(geometry,&image->page);
3560       geometry=DestroyString(geometry);
3561     }
3562   option=GetImageOption(image_info,"quality");
3563   if (option != (const char *) NULL)
3564     image->quality=StringToUnsignedLong(option);
3565   option=GetImageOption(image_info,"red-primary");
3566   if (option != (const char *) NULL)
3567     {
3568       flags=ParseGeometry(option,&geometry_info);
3569       image->chromaticity.red_primary.x=geometry_info.rho;
3570       image->chromaticity.red_primary.y=geometry_info.sigma;
3571       if ((flags & SigmaValue) == 0)
3572         image->chromaticity.red_primary.y=image->chromaticity.red_primary.x;
3573     }
3574   if (image_info->quality != UndefinedCompressionQuality)
3575     image->quality=image_info->quality;
3576   option=GetImageOption(image_info,"scene");
3577   if (option != (const char *) NULL)
3578     image->scene=StringToUnsignedLong(option);
3579   option=GetImageOption(image_info,"taint");
3580   if (option != (const char *) NULL)
3581     image->taint=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions,
3582       MagickFalse,option);
3583   option=GetImageOption(image_info,"tile-offset");
3584   if (option != (const char *) NULL)
3585     {
3586       char
3587         *geometry;
3588
3589       geometry=GetPageGeometry(option);
3590       flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
3591       geometry=DestroyString(geometry);
3592     }
3593   option=GetImageOption(image_info,"transparent-color");
3594   if (option != (const char *) NULL)
3595     (void) QueryColorCompliance(option,AllCompliance,&image->transparent_color,
3596       exception);
3597   option=GetImageOption(image_info,"type");
3598   if (option != (const char *) NULL)
3599     image->type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
3600       option);
3601   option=GetImageOption(image_info,"units");
3602   units=image_info->units;
3603   if (option != (const char *) NULL)
3604     units=(ResolutionType) ParseCommandOption(MagickResolutionOptions,
3605       MagickFalse,option);
3606   if (units != UndefinedResolution)
3607     {
3608       if (image->units != units)
3609         switch (image->units)
3610         {
3611           case PixelsPerInchResolution:
3612           {
3613             if (units == PixelsPerCentimeterResolution)
3614               {
3615                 image->resolution.x/=2.54;
3616                 image->resolution.y/=2.54;
3617               }
3618             break;
3619           }
3620           case PixelsPerCentimeterResolution:
3621           {
3622             if (units == PixelsPerInchResolution)
3623               {
3624                 image->resolution.x=(double) ((size_t) (100.0*2.54*
3625                   image->resolution.x+0.5))/100.0;
3626                 image->resolution.y=(double) ((size_t) (100.0*2.54*
3627                   image->resolution.y+0.5))/100.0;
3628               }
3629             break;
3630           }
3631           default:
3632             break;
3633         }
3634       image->units=units;
3635     }
3636   option=GetImageOption(image_info,"virtual-pixel");
3637   if (option != (const char *) NULL)
3638     (void) SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
3639       ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,option),
3640       exception);
3641   option=GetImageOption(image_info,"white-point");
3642   if (option != (const char *) NULL)
3643     {
3644       flags=ParseGeometry(option,&geometry_info);
3645       image->chromaticity.white_point.x=geometry_info.rho;
3646       image->chromaticity.white_point.y=geometry_info.sigma;
3647       if ((flags & SigmaValue) == 0)
3648         image->chromaticity.white_point.y=image->chromaticity.white_point.x;
3649     }
3650   ResetImageOptionIterator(image_info);
3651 #if 0
3652   {
3653     /* IMv6: Copy freeform global options into per-image artifacts, so
3654      * various operations and coders can access them.
3655      *
3656      * This has a problem, as per-image artefacts may have been set in
3657      * parenthesis, but may not be unset when parenthesis ends.
3658      */
3659     char
3660       property[MaxTextExtent];
3661
3662     const char
3663       *value;
3664
3665     for (option=GetNextImageOption(image_info); option != (const char *) NULL; )
3666     {
3667       value=GetImageOption(image_info,option);
3668       if (value != (const char *) NULL)
3669         {
3670           (void) FormatLocaleString(property,MaxTextExtent,"%s",option);
3671           (void) SetImageArtifact(image,property,value);
3672         }
3673       option=GetNextImageOption(image_info);
3674     }
3675   }
3676 #else
3677   /* IMv7: pointer to allow the lookup of pre-image artefact will fallback to
3678      a global option setting/define.  This saves a lot of duplication of
3679      global options into per-image artifacts, while ensuring only specifically
3680      set per-image artifacts are preverved when parenthesis ends.
3681
3682      This pointer is never explictally freed, as it is only used as a back
3683      reference, not as the main pointer to the image_info structure.  Images
3684      being removed from a image_info image list (or yet to be added to such),
3685      should have this pointer reset to NULL.
3686   */
3687   image->image_info=image_info;
3688 #endif
3689   return(MagickTrue);
3690 }