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