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