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