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