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