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