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