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