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