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