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