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