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