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