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