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