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