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