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