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