Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                      CCCC   AAA    CCCC  H   H  EEEEE                       %
      7 %                     C      A   A  C      H   H  E                           %
      8 %                     C      AAAAA  C      HHHHH  EEE                         %
      9 %                     C      A   A  C      H   H  E                           %
     10 %                      CCCC  A   A   CCCC  H   H  EEEEE                       %
     11 %                                                                             %
     12 %                                                                             %
     13 %                       MagickCore Pixel Cache Methods                        %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                                 July 1999                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    https://imagemagick.org/script/license.php                               %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %
     37 %
     38 */
     39 
     40 /*
     42   Include declarations.
     43 */
     44 #include "MagickCore/studio.h"
     45 #include "MagickCore/blob.h"
     46 #include "MagickCore/blob-private.h"
     47 #include "MagickCore/cache.h"
     48 #include "MagickCore/cache-private.h"
     49 #include "MagickCore/color-private.h"
     50 #include "MagickCore/colorspace-private.h"
     51 #include "MagickCore/composite-private.h"
     52 #include "MagickCore/distribute-cache-private.h"
     53 #include "MagickCore/exception.h"
     54 #include "MagickCore/exception-private.h"
     55 #include "MagickCore/geometry.h"
     56 #include "MagickCore/list.h"
     57 #include "MagickCore/log.h"
     58 #include "MagickCore/magick.h"
     59 #include "MagickCore/memory_.h"
     60 #include "MagickCore/memory-private.h"
     61 #include "MagickCore/nt-base-private.h"
     62 #include "MagickCore/option.h"
     63 #include "MagickCore/pixel.h"
     64 #include "MagickCore/pixel-accessor.h"
     65 #include "MagickCore/policy.h"
     66 #include "MagickCore/quantum.h"
     67 #include "MagickCore/random_.h"
     68 #include "MagickCore/registry.h"
     69 #include "MagickCore/resource_.h"
     70 #include "MagickCore/semaphore.h"
     71 #include "MagickCore/splay-tree.h"
     72 #include "MagickCore/string_.h"
     73 #include "MagickCore/string-private.h"
     74 #include "MagickCore/thread-private.h"
     75 #include "MagickCore/utility.h"
     76 #include "MagickCore/utility-private.h"
     77 #if defined(MAGICKCORE_ZLIB_DELEGATE)
     78 #include "zlib.h"
     79 #endif
     80 
     81 /*
     83   Define declarations.
     84 */
     85 #define CacheTick(offset,extent)  QuantumTick((MagickOffsetType) offset,extent)
     86 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
     87   GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
     88 
     89 /*
     91   Typedef declarations.
     92 */
     93 typedef struct _MagickModulo
     94 {
     95   ssize_t
     96     quotient,
     97     remainder;
     98 } MagickModulo;
     99 
    100 /*
    102   Forward declarations.
    103 */
    104 #if defined(__cplusplus) || defined(c_plusplus)
    105 extern "C" {
    106 #endif
    107 
    108 static Cache
    109   GetImagePixelCache(Image *,const MagickBooleanType,ExceptionInfo *)
    110     magick_hot_spot;
    111 
    112 static const Quantum
    113   *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
    114     const ssize_t,const size_t,const size_t,ExceptionInfo *),
    115   *GetVirtualPixelsCache(const Image *);
    116 
    117 static const void
    118   *GetVirtualMetacontentFromCache(const Image *);
    119 
    120 static MagickBooleanType
    121   GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,Quantum *,
    122     ExceptionInfo *),
    123   GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
    124     const ssize_t,const ssize_t,Quantum *,ExceptionInfo *),
    125   OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
    126   OpenPixelCacheOnDisk(CacheInfo *,const MapMode),
    127   ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
    128     ExceptionInfo *),
    129   ReadPixelCacheMetacontent(CacheInfo *magick_restrict,
    130     NexusInfo *magick_restrict,ExceptionInfo *),
    131   SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
    132   WritePixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
    133     ExceptionInfo *),
    134   WritePixelCacheMetacontent(CacheInfo *,NexusInfo *magick_restrict,
    135     ExceptionInfo *);
    136 
    137 static Quantum
    138   *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
    139     const size_t,ExceptionInfo *),
    140   *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
    141     const size_t,ExceptionInfo *),
    142   *SetPixelCacheNexusPixels(const CacheInfo *,const MapMode,
    143     const RectangleInfo *,const MagickBooleanType,NexusInfo *,ExceptionInfo *)
    144     magick_hot_spot;
    145 
    146 #if defined(MAGICKCORE_OPENCL_SUPPORT)
    147 static void
    148   CopyOpenCLBuffer(CacheInfo *magick_restrict);
    149 #endif
    150 
    151 #if defined(__cplusplus) || defined(c_plusplus)
    152 }
    153 #endif
    154 
    155 /*
    157   Global declarations.
    158 */
    159 static SemaphoreInfo
    160   *cache_semaphore = (SemaphoreInfo *) NULL;
    161 
    162 static ssize_t
    163   cache_anonymous_memory = (-1);
    164 
    165 static time_t
    166   cache_epoch = 0;
    167 
    168 /*
    170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    171 %                                                                             %
    172 %                                                                             %
    173 %                                                                             %
    174 +   A c q u i r e P i x e l C a c h e                                         %
    175 %                                                                             %
    176 %                                                                             %
    177 %                                                                             %
    178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    179 %
    180 %  AcquirePixelCache() acquires a pixel cache.
    181 %
    182 %  The format of the AcquirePixelCache() method is:
    183 %
    184 %      Cache AcquirePixelCache(const size_t number_threads)
    185 %
    186 %  A description of each parameter follows:
    187 %
    188 %    o number_threads: the number of nexus threads.
    189 %
    190 */
    191 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
    192 {
    193   CacheInfo
    194     *magick_restrict cache_info;
    195 
    196   char
    197     *value;
    198 
    199   cache_info=(CacheInfo *) AcquireAlignedMemory(1,sizeof(*cache_info));
    200   if (cache_info == (CacheInfo *) NULL)
    201     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    202   (void) memset(cache_info,0,sizeof(*cache_info));
    203   cache_info->type=UndefinedCache;
    204   cache_info->mode=IOMode;
    205   cache_info->disk_mode=IOMode;
    206   cache_info->colorspace=sRGBColorspace;
    207   cache_info->file=(-1);
    208   cache_info->id=GetMagickThreadId();
    209   cache_info->number_threads=number_threads;
    210   if (GetOpenMPMaximumThreads() > cache_info->number_threads)
    211     cache_info->number_threads=GetOpenMPMaximumThreads();
    212   if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
    213     cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
    214   if (cache_info->number_threads == 0)
    215     cache_info->number_threads=1;
    216   cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
    217   if (cache_info->nexus_info == (NexusInfo **) NULL)
    218     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    219   value=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
    220   if (value != (const char *) NULL)
    221     {
    222       cache_info->synchronize=IsStringTrue(value);
    223       value=DestroyString(value);
    224     }
    225   value=GetPolicyValue("cache:synchronize");
    226   if (value != (const char *) NULL)
    227     {
    228       cache_info->synchronize=IsStringTrue(value);
    229       value=DestroyString(value);
    230     }
    231   cache_info->semaphore=AcquireSemaphoreInfo();
    232   cache_info->reference_count=1;
    233   cache_info->file_semaphore=AcquireSemaphoreInfo();
    234   cache_info->debug=IsEventLogging();
    235   cache_info->signature=MagickCoreSignature;
    236   return((Cache ) cache_info);
    237 }
    238 
    239 /*
    241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    242 %                                                                             %
    243 %                                                                             %
    244 %                                                                             %
    245 %   A c q u i r e P i x e l C a c h e N e x u s                               %
    246 %                                                                             %
    247 %                                                                             %
    248 %                                                                             %
    249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    250 %
    251 %  AcquirePixelCacheNexus() allocates the NexusInfo structure.
    252 %
    253 %  The format of the AcquirePixelCacheNexus method is:
    254 %
    255 %      NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
    256 %
    257 %  A description of each parameter follows:
    258 %
    259 %    o number_threads: the number of nexus threads.
    260 %
    261 */
    262 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
    263 {
    264   NexusInfo
    265     **magick_restrict nexus_info;
    266 
    267   register ssize_t
    268     i;
    269 
    270   nexus_info=(NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(
    271     number_threads,sizeof(*nexus_info)));
    272   if (nexus_info == (NexusInfo **) NULL)
    273     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    274   nexus_info[0]=(NexusInfo *) AcquireQuantumMemory(number_threads,
    275     sizeof(**nexus_info));
    276   if (nexus_info[0] == (NexusInfo *) NULL)
    277     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    278   (void) memset(nexus_info[0],0,number_threads*sizeof(**nexus_info));
    279   for (i=0; i < (ssize_t) number_threads; i++)
    280   {
    281     nexus_info[i]=(&nexus_info[0][i]);
    282     nexus_info[i]->signature=MagickCoreSignature;
    283   }
    284   return(nexus_info);
    285 }
    286 
    287 /*
    289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    290 %                                                                             %
    291 %                                                                             %
    292 %                                                                             %
    293 %   A c q u i r e P i x e l C a c h e P i x e l s                             %
    294 %                                                                             %
    295 %                                                                             %
    296 %                                                                             %
    297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    298 %
    299 %  AcquirePixelCachePixels() returns the pixels associated with the specified
    300 %  image.
    301 %
    302 %  The format of the AcquirePixelCachePixels() method is:
    303 %
    304 %      void *AcquirePixelCachePixels(const Image *image,size_t *length,
    305 %        ExceptionInfo *exception)
    306 %
    307 %  A description of each parameter follows:
    308 %
    309 %    o image: the image.
    310 %
    311 %    o length: the pixel cache length.
    312 %
    313 %    o exception: return any errors or warnings in this structure.
    314 %
    315 */
    316 MagickExport void *AcquirePixelCachePixels(const Image *image,size_t *length,
    317   ExceptionInfo *exception)
    318 {
    319   CacheInfo
    320     *magick_restrict cache_info;
    321 
    322   assert(image != (const Image *) NULL);
    323   assert(image->signature == MagickCoreSignature);
    324   assert(exception != (ExceptionInfo *) NULL);
    325   assert(exception->signature == MagickCoreSignature);
    326   assert(image->cache != (Cache) NULL);
    327   cache_info=(CacheInfo *) image->cache;
    328   assert(cache_info->signature == MagickCoreSignature);
    329   *length=0;
    330   if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
    331     return((void *) NULL);
    332   *length=(size_t) cache_info->length;
    333   return(cache_info->pixels);
    334 }
    335 
    336 /*
    338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    339 %                                                                             %
    340 %                                                                             %
    341 %                                                                             %
    342 +   C a c h e C o m p o n e n t G e n e s i s                                 %
    343 %                                                                             %
    344 %                                                                             %
    345 %                                                                             %
    346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    347 %
    348 %  CacheComponentGenesis() instantiates the cache component.
    349 %
    350 %  The format of the CacheComponentGenesis method is:
    351 %
    352 %      MagickBooleanType CacheComponentGenesis(void)
    353 %
    354 */
    355 MagickPrivate MagickBooleanType CacheComponentGenesis(void)
    356 {
    357   if (cache_semaphore == (SemaphoreInfo *) NULL)
    358     cache_semaphore=AcquireSemaphoreInfo();
    359   return(MagickTrue);
    360 }
    361 
    362 /*
    364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    365 %                                                                             %
    366 %                                                                             %
    367 %                                                                             %
    368 +   C a c h e C o m p o n e n t T e r m i n u s                               %
    369 %                                                                             %
    370 %                                                                             %
    371 %                                                                             %
    372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    373 %
    374 %  CacheComponentTerminus() destroys the cache component.
    375 %
    376 %  The format of the CacheComponentTerminus() method is:
    377 %
    378 %      CacheComponentTerminus(void)
    379 %
    380 */
    381 MagickPrivate void CacheComponentTerminus(void)
    382 {
    383   if (cache_semaphore == (SemaphoreInfo *) NULL)
    384     ActivateSemaphoreInfo(&cache_semaphore);
    385   /* no op-- nothing to destroy */
    386   RelinquishSemaphoreInfo(&cache_semaphore);
    387 }
    388 
    389 /*
    391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    392 %                                                                             %
    393 %                                                                             %
    394 %                                                                             %
    395 +   C l i p P i x e l C a c h e N e x u s                                     %
    396 %                                                                             %
    397 %                                                                             %
    398 %                                                                             %
    399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    400 %
    401 %  ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
    402 %  mask.  The method returns MagickTrue if the pixel region is clipped,
    403 %  otherwise MagickFalse.
    404 %
    405 %  The format of the ClipPixelCacheNexus() method is:
    406 %
    407 %      MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
    408 %        ExceptionInfo *exception)
    409 %
    410 %  A description of each parameter follows:
    411 %
    412 %    o image: the image.
    413 %
    414 %    o nexus_info: the cache nexus to clip.
    415 %
    416 %    o exception: return any errors or warnings in this structure.
    417 %
    418 */
    419 static MagickBooleanType ClipPixelCacheNexus(Image *image,
    420   NexusInfo *nexus_info,ExceptionInfo *exception)
    421 {
    422   CacheInfo
    423     *magick_restrict cache_info;
    424 
    425   MagickSizeType
    426     number_pixels;
    427 
    428   NexusInfo
    429     **magick_restrict image_nexus;
    430 
    431   register Quantum
    432     *magick_restrict p,
    433     *magick_restrict q;
    434 
    435   register ssize_t
    436     n;
    437 
    438   /*
    439     Apply clip mask.
    440   */
    441   if (image->debug != MagickFalse)
    442     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    443   if ((image->channels & WriteMaskChannel) == 0)
    444     return(MagickTrue);
    445   cache_info=(CacheInfo *) image->cache;
    446   if (cache_info == (Cache) NULL)
    447     return(MagickFalse);
    448   image_nexus=AcquirePixelCacheNexus(1);
    449   p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
    450     nexus_info->region.width,nexus_info->region.height,image_nexus[0],
    451     exception);
    452   q=nexus_info->pixels;
    453   number_pixels=(MagickSizeType) nexus_info->region.width*
    454     nexus_info->region.height;
    455   for (n=0; n < (ssize_t) number_pixels; n++)
    456   {
    457     double
    458       mask_alpha;
    459 
    460     register ssize_t
    461       i;
    462 
    463     if (p == (Quantum *) NULL)
    464       break;
    465     mask_alpha=QuantumScale*GetPixelWriteMask(image,p);
    466     if (fabs(mask_alpha) >= MagickEpsilon)
    467       {
    468         for (i=0; i < (ssize_t) image->number_channels; i++)
    469         {
    470           PixelChannel channel = GetPixelChannelChannel(image,i);
    471           PixelTrait traits = GetPixelChannelTraits(image,channel);
    472           if ((traits & UpdatePixelTrait) == 0)
    473             continue;
    474           q[i]=ClampToQuantum(MagickOver_((double) p[i],mask_alpha*
    475             GetPixelAlpha(image,p),(double) q[i],(double)
    476             GetPixelAlpha(image,q)));
    477         }
    478         SetPixelAlpha(image,GetPixelAlpha(image,p),q);
    479       }
    480     p+=GetPixelChannels(image);
    481     q+=GetPixelChannels(image);
    482   }
    483   image_nexus=DestroyPixelCacheNexus(image_nexus,1);
    484   if (n < (ssize_t) number_pixels)
    485     return(MagickFalse);
    486   return(MagickTrue);
    487 }
    488 
    489 /*
    491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    492 %                                                                             %
    493 %                                                                             %
    494 %                                                                             %
    495 +   C l o n e P i x e l C a c h e                                             %
    496 %                                                                             %
    497 %                                                                             %
    498 %                                                                             %
    499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    500 %
    501 %  ClonePixelCache() clones a pixel cache.
    502 %
    503 %  The format of the ClonePixelCache() method is:
    504 %
    505 %      Cache ClonePixelCache(const Cache cache)
    506 %
    507 %  A description of each parameter follows:
    508 %
    509 %    o cache: the pixel cache.
    510 %
    511 */
    512 MagickPrivate Cache ClonePixelCache(const Cache cache)
    513 {
    514   CacheInfo
    515     *magick_restrict clone_info;
    516 
    517   const CacheInfo
    518     *magick_restrict cache_info;
    519 
    520   assert(cache != NULL);
    521   cache_info=(const CacheInfo *) cache;
    522   assert(cache_info->signature == MagickCoreSignature);
    523   if (cache_info->debug != MagickFalse)
    524     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    525       cache_info->filename);
    526   clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
    527   clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
    528   return((Cache ) clone_info);
    529 }
    530 
    531 /*
    533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    534 %                                                                             %
    535 %                                                                             %
    536 %                                                                             %
    537 +   C l o n e P i x e l C a c h e M e t h o d s                               %
    538 %                                                                             %
    539 %                                                                             %
    540 %                                                                             %
    541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    542 %
    543 %  ClonePixelCacheMethods() clones the pixel cache methods from one cache to
    544 %  another.
    545 %
    546 %  The format of the ClonePixelCacheMethods() method is:
    547 %
    548 %      void ClonePixelCacheMethods(Cache clone,const Cache cache)
    549 %
    550 %  A description of each parameter follows:
    551 %
    552 %    o clone: Specifies a pointer to a Cache structure.
    553 %
    554 %    o cache: the pixel cache.
    555 %
    556 */
    557 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
    558 {
    559   CacheInfo
    560     *magick_restrict cache_info,
    561     *magick_restrict source_info;
    562 
    563   assert(clone != (Cache) NULL);
    564   source_info=(CacheInfo *) clone;
    565   assert(source_info->signature == MagickCoreSignature);
    566   if (source_info->debug != MagickFalse)
    567     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    568       source_info->filename);
    569   assert(cache != (Cache) NULL);
    570   cache_info=(CacheInfo *) cache;
    571   assert(cache_info->signature == MagickCoreSignature);
    572   source_info->methods=cache_info->methods;
    573 }
    574 
    575 /*
    577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    578 %                                                                             %
    579 %                                                                             %
    580 %                                                                             %
    581 +   C l o n e P i x e l C a c h e R e p o s i t o r y                         %
    582 %                                                                             %
    583 %                                                                             %
    584 %                                                                             %
    585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    586 %
    587 %  ClonePixelCacheRepository() clones the source pixel cache to the destination
    588 %  cache.
    589 %
    590 %  The format of the ClonePixelCacheRepository() method is:
    591 %
    592 %      MagickBooleanType ClonePixelCacheRepository(CacheInfo *cache_info,
    593 %        CacheInfo *source_info,ExceptionInfo *exception)
    594 %
    595 %  A description of each parameter follows:
    596 %
    597 %    o cache_info: the pixel cache.
    598 %
    599 %    o source_info: the source pixel cache.
    600 %
    601 %    o exception: return any errors or warnings in this structure.
    602 %
    603 */
    604 
    605 static MagickBooleanType ClonePixelCacheOnDisk(
    606   CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
    607 {
    608   MagickSizeType
    609     extent;
    610 
    611   size_t
    612     quantum;
    613 
    614   ssize_t
    615     count;
    616 
    617   struct stat
    618     file_stats;
    619 
    620   unsigned char
    621     *buffer;
    622 
    623   /*
    624     Clone pixel cache on disk with identical morphology.
    625   */
    626   if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
    627       (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
    628     return(MagickFalse);
    629   if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
    630       (lseek(clone_info->file,0,SEEK_SET) < 0))
    631     return(MagickFalse);
    632   quantum=(size_t) MagickMaxBufferExtent;
    633   if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
    634     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
    635   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
    636   if (buffer == (unsigned char *) NULL)
    637     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    638   extent=0;
    639   while ((count=read(cache_info->file,buffer,quantum)) > 0)
    640   {
    641     ssize_t
    642       number_bytes;
    643 
    644     number_bytes=write(clone_info->file,buffer,(size_t) count);
    645     if (number_bytes != count)
    646       break;
    647     extent+=number_bytes;
    648   }
    649   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    650   if (extent != cache_info->length)
    651     return(MagickFalse);
    652   return(MagickTrue);
    653 }
    654 
    655 static MagickBooleanType ClonePixelCacheRepository(
    656   CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
    657   ExceptionInfo *exception)
    658 {
    659 #define MaxCacheThreads  ((size_t) GetMagickResourceLimit(ThreadResource))
    660 #define cache_number_threads(source,destination,chunk,multithreaded) \
    661   num_threads((multithreaded) == 0 ? 1 : \
    662     (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
    663     (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
    664     MagickMax(MagickMin(GetMagickResourceLimit(ThreadResource),2),1) : \
    665     MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
    666 
    667   MagickBooleanType
    668     optimize,
    669     status;
    670 
    671   NexusInfo
    672     **magick_restrict cache_nexus,
    673     **magick_restrict clone_nexus;
    674 
    675   size_t
    676     length;
    677 
    678   ssize_t
    679     y;
    680 
    681   assert(cache_info != (CacheInfo *) NULL);
    682   assert(clone_info != (CacheInfo *) NULL);
    683   assert(exception != (ExceptionInfo *) NULL);
    684   if (cache_info->type == PingCache)
    685     return(MagickTrue);
    686   length=cache_info->number_channels*sizeof(*cache_info->channel_map);
    687   if ((cache_info->storage_class == clone_info->storage_class) &&
    688       (cache_info->colorspace == clone_info->colorspace) &&
    689       (cache_info->alpha_trait == clone_info->alpha_trait) &&
    690       (cache_info->channels == clone_info->channels) &&
    691       (cache_info->columns == clone_info->columns) &&
    692       (cache_info->rows == clone_info->rows) &&
    693       (cache_info->number_channels == clone_info->number_channels) &&
    694       (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
    695       (cache_info->metacontent_extent == clone_info->metacontent_extent))
    696     {
    697       /*
    698         Identical pixel cache morphology.
    699       */
    700       if (((cache_info->type == MemoryCache) ||
    701            (cache_info->type == MapCache)) &&
    702           ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
    703         {
    704           (void) memcpy(clone_info->pixels,cache_info->pixels,
    705             cache_info->number_channels*cache_info->columns*cache_info->rows*
    706             sizeof(*cache_info->pixels));
    707           if ((cache_info->metacontent_extent != 0) &&
    708               (clone_info->metacontent_extent != 0))
    709             (void) memcpy(clone_info->metacontent,cache_info->metacontent,
    710               cache_info->columns*cache_info->rows*
    711               clone_info->metacontent_extent*sizeof(unsigned char));
    712           return(MagickTrue);
    713         }
    714       if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
    715         return(ClonePixelCacheOnDisk(cache_info,clone_info));
    716     }
    717   /*
    718     Mismatched pixel cache morphology.
    719   */
    720   cache_nexus=AcquirePixelCacheNexus(MaxCacheThreads);
    721   clone_nexus=AcquirePixelCacheNexus(MaxCacheThreads);
    722   length=cache_info->number_channels*sizeof(*cache_info->channel_map);
    723   optimize=(cache_info->number_channels == clone_info->number_channels) &&
    724     (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
    725     MagickTrue : MagickFalse;
    726   length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
    727     clone_info->number_channels*clone_info->columns);
    728   status=MagickTrue;
    729 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    730   #pragma omp parallel for schedule(static) shared(status) \
    731     cache_number_threads(cache_info,clone_info,cache_info->rows,1)
    732 #endif
    733   for (y=0; y < (ssize_t) cache_info->rows; y++)
    734   {
    735     const int
    736       id = GetOpenMPThreadId();
    737 
    738     Quantum
    739       *pixels;
    740 
    741     RectangleInfo
    742       region;
    743 
    744     register ssize_t
    745       x;
    746 
    747     if (status == MagickFalse)
    748       continue;
    749     if (y >= (ssize_t) clone_info->rows)
    750       continue;
    751     region.width=cache_info->columns;
    752     region.height=1;
    753     region.x=0;
    754     region.y=y;
    755     pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,MagickFalse,
    756       cache_nexus[id],exception);
    757     if (pixels == (Quantum *) NULL)
    758       continue;
    759     status=ReadPixelCachePixels(cache_info,cache_nexus[id],exception);
    760     if (status == MagickFalse)
    761       continue;
    762     region.width=clone_info->columns;
    763     pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,&region,MagickFalse,
    764       clone_nexus[id],exception);
    765     if (pixels == (Quantum *) NULL)
    766       continue;
    767     (void) memset(clone_nexus[id]->pixels,0,(size_t) clone_nexus[id]->length);
    768     if (optimize != MagickFalse)
    769       (void) memcpy(clone_nexus[id]->pixels,cache_nexus[id]->pixels,length*
    770         sizeof(Quantum));
    771     else
    772       {
    773         register const Quantum
    774           *magick_restrict p;
    775 
    776         register Quantum
    777           *magick_restrict q;
    778 
    779         /*
    780           Mismatched pixel channel map.
    781         */
    782         p=cache_nexus[id]->pixels;
    783         q=clone_nexus[id]->pixels;
    784         for (x=0; x < (ssize_t) cache_info->columns; x++)
    785         {
    786           register ssize_t
    787             i;
    788 
    789           if (x == (ssize_t) clone_info->columns)
    790             break;
    791           for (i=0; i < (ssize_t) clone_info->number_channels; i++)
    792           {
    793             PixelChannel
    794               channel;
    795 
    796             PixelTrait
    797               traits;
    798 
    799             channel=clone_info->channel_map[i].channel;
    800             traits=cache_info->channel_map[channel].traits;
    801             if (traits != UndefinedPixelTrait)
    802               *q=*(p+cache_info->channel_map[channel].offset);
    803             q++;
    804           }
    805           p+=cache_info->number_channels;
    806         }
    807       }
    808     status=WritePixelCachePixels(clone_info,clone_nexus[id],exception);
    809   }
    810   if ((cache_info->metacontent_extent != 0) &&
    811       (clone_info->metacontent_extent != 0))
    812     {
    813       /*
    814         Clone metacontent.
    815       */
    816       length=(size_t) MagickMin(cache_info->metacontent_extent,
    817         clone_info->metacontent_extent);
    818 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    819       #pragma omp parallel for schedule(static) shared(status) \
    820         cache_number_threads(cache_info,clone_info,cache_info->rows,1)
    821 #endif
    822       for (y=0; y < (ssize_t) cache_info->rows; y++)
    823       {
    824         const int
    825           id = GetOpenMPThreadId();
    826 
    827         Quantum
    828           *pixels;
    829 
    830         RectangleInfo
    831           region;
    832 
    833         if (status == MagickFalse)
    834           continue;
    835         if (y >= (ssize_t) clone_info->rows)
    836           continue;
    837         region.width=cache_info->columns;
    838         region.height=1;
    839         region.x=0;
    840         region.y=y;
    841         pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,MagickFalse,
    842           cache_nexus[id],exception);
    843         if (pixels == (Quantum *) NULL)
    844           continue;
    845         status=ReadPixelCacheMetacontent(cache_info,cache_nexus[id],exception);
    846         if (status == MagickFalse)
    847           continue;
    848         region.width=clone_info->columns;
    849         pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,&region,
    850           MagickFalse,clone_nexus[id],exception);
    851         if (pixels == (Quantum *) NULL)
    852           continue;
    853         if ((clone_nexus[id]->metacontent != (void *) NULL) &&
    854             (cache_nexus[id]->metacontent != (void *) NULL))
    855           (void) memcpy(clone_nexus[id]->metacontent,
    856             cache_nexus[id]->metacontent,length*sizeof(unsigned char));
    857         status=WritePixelCacheMetacontent(clone_info,clone_nexus[id],exception);
    858       }
    859     }
    860   cache_nexus=DestroyPixelCacheNexus(cache_nexus,MaxCacheThreads);
    861   clone_nexus=DestroyPixelCacheNexus(clone_nexus,MaxCacheThreads);
    862   if (cache_info->debug != MagickFalse)
    863     {
    864       char
    865         message[MagickPathExtent];
    866 
    867       (void) FormatLocaleString(message,MagickPathExtent,"%s => %s",
    868         CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
    869         CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
    870       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
    871     }
    872   return(status);
    873 }
    874 
    875 /*
    877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    878 %                                                                             %
    879 %                                                                             %
    880 %                                                                             %
    881 +   D e s t r o y I m a g e P i x e l C a c h e                               %
    882 %                                                                             %
    883 %                                                                             %
    884 %                                                                             %
    885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    886 %
    887 %  DestroyImagePixelCache() deallocates memory associated with the pixel cache.
    888 %
    889 %  The format of the DestroyImagePixelCache() method is:
    890 %
    891 %      void DestroyImagePixelCache(Image *image)
    892 %
    893 %  A description of each parameter follows:
    894 %
    895 %    o image: the image.
    896 %
    897 */
    898 static void DestroyImagePixelCache(Image *image)
    899 {
    900   assert(image != (Image *) NULL);
    901   assert(image->signature == MagickCoreSignature);
    902   if (image->debug != MagickFalse)
    903     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    904   if (image->cache != (void *) NULL)
    905     image->cache=DestroyPixelCache(image->cache);
    906 }
    907 
    908 /*
    910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    911 %                                                                             %
    912 %                                                                             %
    913 %                                                                             %
    914 +   D e s t r o y I m a g e P i x e l s                                       %
    915 %                                                                             %
    916 %                                                                             %
    917 %                                                                             %
    918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    919 %
    920 %  DestroyImagePixels() deallocates memory associated with the pixel cache.
    921 %
    922 %  The format of the DestroyImagePixels() method is:
    923 %
    924 %      void DestroyImagePixels(Image *image)
    925 %
    926 %  A description of each parameter follows:
    927 %
    928 %    o image: the image.
    929 %
    930 */
    931 MagickExport void DestroyImagePixels(Image *image)
    932 {
    933   CacheInfo
    934     *magick_restrict cache_info;
    935 
    936   assert(image != (const Image *) NULL);
    937   assert(image->signature == MagickCoreSignature);
    938   if (image->debug != MagickFalse)
    939     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    940   assert(image->cache != (Cache) NULL);
    941   cache_info=(CacheInfo *) image->cache;
    942   assert(cache_info->signature == MagickCoreSignature);
    943   if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
    944     {
    945       cache_info->methods.destroy_pixel_handler(image);
    946       return;
    947     }
    948   image->cache=DestroyPixelCache(image->cache);
    949 }
    950 
    951 /*
    953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    954 %                                                                             %
    955 %                                                                             %
    956 %                                                                             %
    957 +   D e s t r o y P i x e l C a c h e                                         %
    958 %                                                                             %
    959 %                                                                             %
    960 %                                                                             %
    961 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    962 %
    963 %  DestroyPixelCache() deallocates memory associated with the pixel cache.
    964 %
    965 %  The format of the DestroyPixelCache() method is:
    966 %
    967 %      Cache DestroyPixelCache(Cache cache)
    968 %
    969 %  A description of each parameter follows:
    970 %
    971 %    o cache: the pixel cache.
    972 %
    973 */
    974 
    975 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
    976 {
    977   int
    978     status;
    979 
    980   status=(-1);
    981   if (cache_info->file != -1)
    982     {
    983       status=close(cache_info->file);
    984       cache_info->file=(-1);
    985       RelinquishMagickResource(FileResource,1);
    986     }
    987   return(status == -1 ? MagickFalse : MagickTrue);
    988 }
    989 
    990 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
    991 {
    992   switch (cache_info->type)
    993   {
    994     case MemoryCache:
    995     {
    996 #if defined(MAGICKCORE_OPENCL_SUPPORT)
    997       if (cache_info->opencl != (MagickCLCacheInfo) NULL)
    998         {
    999           cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
   1000             MagickTrue);
   1001           cache_info->pixels=(Quantum *) NULL;
   1002           break;
   1003         }
   1004 #endif
   1005       if (cache_info->mapped == MagickFalse)
   1006         cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
   1007           cache_info->pixels);
   1008       else
   1009         (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
   1010       RelinquishMagickResource(MemoryResource,cache_info->length);
   1011       break;
   1012     }
   1013     case MapCache:
   1014     {
   1015       (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
   1016       cache_info->pixels=(Quantum *) NULL;
   1017       if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
   1018         (void) RelinquishUniqueFileResource(cache_info->cache_filename);
   1019       *cache_info->cache_filename='\0';
   1020       RelinquishMagickResource(MapResource,cache_info->length);
   1021     }
   1022     case DiskCache:
   1023     {
   1024       if (cache_info->file != -1)
   1025         (void) ClosePixelCacheOnDisk(cache_info);
   1026       if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
   1027         (void) RelinquishUniqueFileResource(cache_info->cache_filename);
   1028       *cache_info->cache_filename='\0';
   1029       RelinquishMagickResource(DiskResource,cache_info->length);
   1030       break;
   1031     }
   1032     case DistributedCache:
   1033     {
   1034       *cache_info->cache_filename='\0';
   1035       (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
   1036         cache_info->server_info);
   1037       break;
   1038     }
   1039     default:
   1040       break;
   1041   }
   1042   cache_info->type=UndefinedCache;
   1043   cache_info->mapped=MagickFalse;
   1044   cache_info->metacontent=(void *) NULL;
   1045 }
   1046 
   1047 MagickPrivate Cache DestroyPixelCache(Cache cache)
   1048 {
   1049   CacheInfo
   1050     *magick_restrict cache_info;
   1051 
   1052   assert(cache != (Cache) NULL);
   1053   cache_info=(CacheInfo *) cache;
   1054   assert(cache_info->signature == MagickCoreSignature);
   1055   if (cache_info->debug != MagickFalse)
   1056     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   1057       cache_info->filename);
   1058   LockSemaphoreInfo(cache_info->semaphore);
   1059   cache_info->reference_count--;
   1060   if (cache_info->reference_count != 0)
   1061     {
   1062       UnlockSemaphoreInfo(cache_info->semaphore);
   1063       return((Cache) NULL);
   1064     }
   1065   UnlockSemaphoreInfo(cache_info->semaphore);
   1066   if (cache_info->debug != MagickFalse)
   1067     {
   1068       char
   1069         message[MagickPathExtent];
   1070 
   1071       (void) FormatLocaleString(message,MagickPathExtent,"destroy %s",
   1072         cache_info->filename);
   1073       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
   1074     }
   1075   RelinquishPixelCachePixels(cache_info);
   1076   if (cache_info->server_info != (DistributeCacheInfo *) NULL)
   1077     cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
   1078       cache_info->server_info);
   1079   if (cache_info->nexus_info != (NexusInfo **) NULL)
   1080     cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
   1081       cache_info->number_threads);
   1082   if (cache_info->random_info != (RandomInfo *) NULL)
   1083     cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
   1084   if (cache_info->file_semaphore != (SemaphoreInfo *) NULL)
   1085     RelinquishSemaphoreInfo(&cache_info->file_semaphore);
   1086   if (cache_info->semaphore != (SemaphoreInfo *) NULL)
   1087     RelinquishSemaphoreInfo(&cache_info->semaphore);
   1088   cache_info->signature=(~MagickCoreSignature);
   1089   cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
   1090   cache=(Cache) NULL;
   1091   return(cache);
   1092 }
   1093 
   1094 /*
   1096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1097 %                                                                             %
   1098 %                                                                             %
   1099 %                                                                             %
   1100 +   D e s t r o y P i x e l C a c h e N e x u s                               %
   1101 %                                                                             %
   1102 %                                                                             %
   1103 %                                                                             %
   1104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1105 %
   1106 %  DestroyPixelCacheNexus() destroys a pixel cache nexus.
   1107 %
   1108 %  The format of the DestroyPixelCacheNexus() method is:
   1109 %
   1110 %      NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
   1111 %        const size_t number_threads)
   1112 %
   1113 %  A description of each parameter follows:
   1114 %
   1115 %    o nexus_info: the nexus to destroy.
   1116 %
   1117 %    o number_threads: the number of nexus threads.
   1118 %
   1119 */
   1120 
   1121 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
   1122 {
   1123   if (nexus_info->mapped == MagickFalse)
   1124     (void) RelinquishAlignedMemory(nexus_info->cache);
   1125   else
   1126     (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
   1127   nexus_info->cache=(Quantum *) NULL;
   1128   nexus_info->pixels=(Quantum *) NULL;
   1129   nexus_info->metacontent=(void *) NULL;
   1130   nexus_info->length=0;
   1131   nexus_info->mapped=MagickFalse;
   1132 }
   1133 
   1134 MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
   1135   const size_t number_threads)
   1136 {
   1137   register ssize_t
   1138     i;
   1139 
   1140   assert(nexus_info != (NexusInfo **) NULL);
   1141   for (i=0; i < (ssize_t) number_threads; i++)
   1142   {
   1143     if (nexus_info[i]->cache != (Quantum *) NULL)
   1144       RelinquishCacheNexusPixels(nexus_info[i]);
   1145     nexus_info[i]->signature=(~MagickCoreSignature);
   1146   }
   1147   nexus_info[0]=(NexusInfo *) RelinquishMagickMemory(nexus_info[0]);
   1148   nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
   1149   return(nexus_info);
   1150 }
   1151 
   1152 /*
   1154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1155 %                                                                             %
   1156 %                                                                             %
   1157 %                                                                             %
   1158 %   G e t A u t h e n t i c M e t a c o n t e n t                             %
   1159 %                                                                             %
   1160 %                                                                             %
   1161 %                                                                             %
   1162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1163 %
   1164 %  GetAuthenticMetacontent() returns the authentic metacontent corresponding
   1165 %  with the last call to QueueAuthenticPixels() or GetVirtualPixels().  NULL is
   1166 %  returned if the associated pixels are not available.
   1167 %
   1168 %  The format of the GetAuthenticMetacontent() method is:
   1169 %
   1170 %      void *GetAuthenticMetacontent(const Image *image)
   1171 %
   1172 %  A description of each parameter follows:
   1173 %
   1174 %    o image: the image.
   1175 %
   1176 */
   1177 MagickExport void *GetAuthenticMetacontent(const Image *image)
   1178 {
   1179   CacheInfo
   1180     *magick_restrict cache_info;
   1181 
   1182   const int
   1183     id = GetOpenMPThreadId();
   1184 
   1185   assert(image != (const Image *) NULL);
   1186   assert(image->signature == MagickCoreSignature);
   1187   assert(image->cache != (Cache) NULL);
   1188   cache_info=(CacheInfo *) image->cache;
   1189   assert(cache_info->signature == MagickCoreSignature);
   1190   if (cache_info->methods.get_authentic_metacontent_from_handler !=
   1191       (GetAuthenticMetacontentFromHandler) NULL)
   1192     {
   1193       void
   1194         *metacontent;
   1195 
   1196       metacontent=cache_info->methods.
   1197         get_authentic_metacontent_from_handler(image);
   1198       return(metacontent);
   1199     }
   1200   assert(id < (int) cache_info->number_threads);
   1201   return(cache_info->nexus_info[id]->metacontent);
   1202 }
   1203 
   1204 /*
   1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1207 %                                                                             %
   1208 %                                                                             %
   1209 %                                                                             %
   1210 +   G e t A u t h e n t i c M e t a c o n t e n t F r o m C a c h e           %
   1211 %                                                                             %
   1212 %                                                                             %
   1213 %                                                                             %
   1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1215 %
   1216 %  GetAuthenticMetacontentFromCache() returns the meta-content corresponding
   1217 %  with the last call to QueueAuthenticPixelsCache() or
   1218 %  GetAuthenticPixelsCache().
   1219 %
   1220 %  The format of the GetAuthenticMetacontentFromCache() method is:
   1221 %
   1222 %      void *GetAuthenticMetacontentFromCache(const Image *image)
   1223 %
   1224 %  A description of each parameter follows:
   1225 %
   1226 %    o image: the image.
   1227 %
   1228 */
   1229 static void *GetAuthenticMetacontentFromCache(const Image *image)
   1230 {
   1231   CacheInfo
   1232     *magick_restrict cache_info;
   1233 
   1234   const int
   1235     id = GetOpenMPThreadId();
   1236 
   1237   assert(image != (const Image *) NULL);
   1238   assert(image->signature == MagickCoreSignature);
   1239   assert(image->cache != (Cache) NULL);
   1240   cache_info=(CacheInfo *) image->cache;
   1241   assert(cache_info->signature == MagickCoreSignature);
   1242   assert(id < (int) cache_info->number_threads);
   1243   return(cache_info->nexus_info[id]->metacontent);
   1244 }
   1245 
   1246 #if defined(MAGICKCORE_OPENCL_SUPPORT)
   1247 /*
   1248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1249 %                                                                             %
   1250 %                                                                             %
   1251 %                                                                             %
   1252 +   G e t A u t h e n t i c O p e n C L B u f f e r                           %
   1253 %                                                                             %
   1254 %                                                                             %
   1255 %                                                                             %
   1256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1257 %
   1258 %  GetAuthenticOpenCLBuffer() returns an OpenCL buffer used to execute OpenCL
   1259 %  operations.
   1260 %
   1261 %  The format of the GetAuthenticOpenCLBuffer() method is:
   1262 %
   1263 %      cl_mem GetAuthenticOpenCLBuffer(const Image *image,
   1264 %        MagickCLDevice device,ExceptionInfo *exception)
   1265 %
   1266 %  A description of each parameter follows:
   1267 %
   1268 %    o image: the image.
   1269 %
   1270 %    o device: the device to use.
   1271 %
   1272 %    o exception: return any errors or warnings in this structure.
   1273 %
   1274 */
   1275 MagickPrivate cl_mem GetAuthenticOpenCLBuffer(const Image *image,
   1276   MagickCLDevice device,ExceptionInfo *exception)
   1277 {
   1278   CacheInfo
   1279     *magick_restrict cache_info;
   1280 
   1281   assert(image != (const Image *) NULL);
   1282   assert(device != (const MagickCLDevice) NULL);
   1283   cache_info=(CacheInfo *) image->cache;
   1284   if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
   1285     {
   1286       SyncImagePixelCache((Image *) image,exception);
   1287       cache_info=(CacheInfo *) image->cache;
   1288     }
   1289   if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
   1290     return((cl_mem) NULL);
   1291   LockSemaphoreInfo(cache_info->semaphore);
   1292   if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
   1293       (cache_info->opencl->device->context != device->context))
   1294     cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
   1295   if (cache_info->opencl == (MagickCLCacheInfo) NULL)
   1296     {
   1297       assert(cache_info->pixels != (Quantum *) NULL);
   1298       cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
   1299         cache_info->length);
   1300     }
   1301   if (cache_info->opencl != (MagickCLCacheInfo) NULL)
   1302     RetainOpenCLMemObject(cache_info->opencl->buffer);
   1303   UnlockSemaphoreInfo(cache_info->semaphore);
   1304   if (cache_info->opencl == (MagickCLCacheInfo) NULL)
   1305     return((cl_mem) NULL);
   1306   assert(cache_info->opencl->pixels == cache_info->pixels);
   1307   return(cache_info->opencl->buffer);
   1308 }
   1309 #endif
   1310 
   1311 /*
   1313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1314 %                                                                             %
   1315 %                                                                             %
   1316 %                                                                             %
   1317 +   G e t A u t h e n t i c P i x e l C a c h e N e x u s                     %
   1318 %                                                                             %
   1319 %                                                                             %
   1320 %                                                                             %
   1321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1322 %
   1323 %  GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
   1324 %  disk pixel cache as defined by the geometry parameters.   A pointer to the
   1325 %  pixels is returned if the pixels are transferred, otherwise a NULL is
   1326 %  returned.
   1327 %
   1328 %  The format of the GetAuthenticPixelCacheNexus() method is:
   1329 %
   1330 %      Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
   1331 %        const ssize_t y,const size_t columns,const size_t rows,
   1332 %        NexusInfo *nexus_info,ExceptionInfo *exception)
   1333 %
   1334 %  A description of each parameter follows:
   1335 %
   1336 %    o image: the image.
   1337 %
   1338 %    o x,y,columns,rows:  These values define the perimeter of a region of
   1339 %      pixels.
   1340 %
   1341 %    o nexus_info: the cache nexus to return.
   1342 %
   1343 %    o exception: return any errors or warnings in this structure.
   1344 %
   1345 */
   1346 
   1347 MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
   1348   const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
   1349   ExceptionInfo *exception)
   1350 {
   1351   CacheInfo
   1352     *magick_restrict cache_info;
   1353 
   1354   Quantum
   1355     *magick_restrict pixels;
   1356 
   1357   /*
   1358     Transfer pixels from the cache.
   1359   */
   1360   assert(image != (Image *) NULL);
   1361   assert(image->signature == MagickCoreSignature);
   1362   pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
   1363     nexus_info,exception);
   1364   if (pixels == (Quantum *) NULL)
   1365     return((Quantum *) NULL);
   1366   cache_info=(CacheInfo *) image->cache;
   1367   assert(cache_info->signature == MagickCoreSignature);
   1368   if (nexus_info->authentic_pixel_cache != MagickFalse)
   1369     return(pixels);
   1370   if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
   1371     return((Quantum *) NULL);
   1372   if (cache_info->metacontent_extent != 0)
   1373     if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
   1374       return((Quantum *) NULL);
   1375   return(pixels);
   1376 }
   1377 
   1378 /*
   1380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1381 %                                                                             %
   1382 %                                                                             %
   1383 %                                                                             %
   1384 +   G e t A u t h e n t i c P i x e l s F r o m C a c h e                     %
   1385 %                                                                             %
   1386 %                                                                             %
   1387 %                                                                             %
   1388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1389 %
   1390 %  GetAuthenticPixelsFromCache() returns the pixels associated with the last
   1391 %  call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
   1392 %
   1393 %  The format of the GetAuthenticPixelsFromCache() method is:
   1394 %
   1395 %      Quantum *GetAuthenticPixelsFromCache(const Image image)
   1396 %
   1397 %  A description of each parameter follows:
   1398 %
   1399 %    o image: the image.
   1400 %
   1401 */
   1402 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
   1403 {
   1404   CacheInfo
   1405     *magick_restrict cache_info;
   1406 
   1407   const int
   1408     id = GetOpenMPThreadId();
   1409 
   1410   assert(image != (const Image *) NULL);
   1411   assert(image->signature == MagickCoreSignature);
   1412   assert(image->cache != (Cache) NULL);
   1413   cache_info=(CacheInfo *) image->cache;
   1414   assert(cache_info->signature == MagickCoreSignature);
   1415   assert(id < (int) cache_info->number_threads);
   1416   return(cache_info->nexus_info[id]->pixels);
   1417 }
   1418 
   1419 /*
   1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1422 %                                                                             %
   1423 %                                                                             %
   1424 %                                                                             %
   1425 %   G e t A u t h e n t i c P i x e l Q u e u e                               %
   1426 %                                                                             %
   1427 %                                                                             %
   1428 %                                                                             %
   1429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1430 %
   1431 %  GetAuthenticPixelQueue() returns the authentic pixels associated
   1432 %  corresponding with the last call to QueueAuthenticPixels() or
   1433 %  GetAuthenticPixels().
   1434 %
   1435 %  The format of the GetAuthenticPixelQueue() method is:
   1436 %
   1437 %      Quantum *GetAuthenticPixelQueue(const Image image)
   1438 %
   1439 %  A description of each parameter follows:
   1440 %
   1441 %    o image: the image.
   1442 %
   1443 */
   1444 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
   1445 {
   1446   CacheInfo
   1447     *magick_restrict cache_info;
   1448 
   1449   const int
   1450     id = GetOpenMPThreadId();
   1451 
   1452   assert(image != (const Image *) NULL);
   1453   assert(image->signature == MagickCoreSignature);
   1454   assert(image->cache != (Cache) NULL);
   1455   cache_info=(CacheInfo *) image->cache;
   1456   assert(cache_info->signature == MagickCoreSignature);
   1457   if (cache_info->methods.get_authentic_pixels_from_handler !=
   1458        (GetAuthenticPixelsFromHandler) NULL)
   1459     return(cache_info->methods.get_authentic_pixels_from_handler(image));
   1460   assert(id < (int) cache_info->number_threads);
   1461   return(cache_info->nexus_info[id]->pixels);
   1462 }
   1463 
   1464 /*
   1466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1467 %                                                                             %
   1468 %                                                                             %
   1469 %                                                                             %
   1470 %   G e t A u t h e n t i c P i x e l s                                       %
   1471 %                                                                             %
   1472 %                                                                             %
   1473 %                                                                             %
   1474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1475 %
   1476 %  GetAuthenticPixels() obtains a pixel region for read/write access. If the
   1477 %  region is successfully accessed, a pointer to a Quantum array
   1478 %  representing the region is returned, otherwise NULL is returned.
   1479 %
   1480 %  The returned pointer may point to a temporary working copy of the pixels
   1481 %  or it may point to the original pixels in memory. Performance is maximized
   1482 %  if the selected region is part of one row, or one or more full rows, since
   1483 %  then there is opportunity to access the pixels in-place (without a copy)
   1484 %  if the image is in memory, or in a memory-mapped file. The returned pointer
   1485 %  must *never* be deallocated by the user.
   1486 %
   1487 %  Pixels accessed via the returned pointer represent a simple array of type
   1488 %  Quantum.  If the image has corresponding metacontent,call
   1489 %  GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
   1490 %  meta-content corresponding to the region.  Once the Quantum array has
   1491 %  been updated, the changes must be saved back to the underlying image using
   1492 %  SyncAuthenticPixels() or they may be lost.
   1493 %
   1494 %  The format of the GetAuthenticPixels() method is:
   1495 %
   1496 %      Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
   1497 %        const ssize_t y,const size_t columns,const size_t rows,
   1498 %        ExceptionInfo *exception)
   1499 %
   1500 %  A description of each parameter follows:
   1501 %
   1502 %    o image: the image.
   1503 %
   1504 %    o x,y,columns,rows:  These values define the perimeter of a region of
   1505 %      pixels.
   1506 %
   1507 %    o exception: return any errors or warnings in this structure.
   1508 %
   1509 */
   1510 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
   1511   const ssize_t y,const size_t columns,const size_t rows,
   1512   ExceptionInfo *exception)
   1513 {
   1514   CacheInfo
   1515     *magick_restrict cache_info;
   1516 
   1517   const int
   1518     id = GetOpenMPThreadId();
   1519 
   1520   Quantum
   1521     *pixels;
   1522 
   1523   assert(image != (Image *) NULL);
   1524   assert(image->signature == MagickCoreSignature);
   1525   assert(image->cache != (Cache) NULL);
   1526   cache_info=(CacheInfo *) image->cache;
   1527   assert(cache_info->signature == MagickCoreSignature);
   1528   if (cache_info->methods.get_authentic_pixels_handler !=
   1529       (GetAuthenticPixelsHandler) NULL)
   1530     {
   1531       pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
   1532         rows,exception);
   1533       return(pixels);
   1534     }
   1535   assert(id < (int) cache_info->number_threads);
   1536   pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
   1537     cache_info->nexus_info[id],exception);
   1538   return(pixels);
   1539 }
   1540 
   1541 /*
   1543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1544 %                                                                             %
   1545 %                                                                             %
   1546 %                                                                             %
   1547 +   G e t A u t h e n t i c P i x e l s C a c h e                             %
   1548 %                                                                             %
   1549 %                                                                             %
   1550 %                                                                             %
   1551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1552 %
   1553 %  GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
   1554 %  as defined by the geometry parameters.   A pointer to the pixels is returned
   1555 %  if the pixels are transferred, otherwise a NULL is returned.
   1556 %
   1557 %  The format of the GetAuthenticPixelsCache() method is:
   1558 %
   1559 %      Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
   1560 %        const ssize_t y,const size_t columns,const size_t rows,
   1561 %        ExceptionInfo *exception)
   1562 %
   1563 %  A description of each parameter follows:
   1564 %
   1565 %    o image: the image.
   1566 %
   1567 %    o x,y,columns,rows:  These values define the perimeter of a region of
   1568 %      pixels.
   1569 %
   1570 %    o exception: return any errors or warnings in this structure.
   1571 %
   1572 */
   1573 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
   1574   const ssize_t y,const size_t columns,const size_t rows,
   1575   ExceptionInfo *exception)
   1576 {
   1577   CacheInfo
   1578     *magick_restrict cache_info;
   1579 
   1580   const int
   1581     id = GetOpenMPThreadId();
   1582 
   1583   Quantum
   1584     *magick_restrict pixels;
   1585 
   1586   assert(image != (const Image *) NULL);
   1587   assert(image->signature == MagickCoreSignature);
   1588   assert(image->cache != (Cache) NULL);
   1589   cache_info=(CacheInfo *) image->cache;
   1590   if (cache_info == (Cache) NULL)
   1591     return((Quantum *) NULL);
   1592   assert(cache_info->signature == MagickCoreSignature);
   1593   assert(id < (int) cache_info->number_threads);
   1594   pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
   1595     cache_info->nexus_info[id],exception);
   1596   return(pixels);
   1597 }
   1598 
   1599 /*
   1601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1602 %                                                                             %
   1603 %                                                                             %
   1604 %                                                                             %
   1605 +   G e t I m a g e E x t e n t                                               %
   1606 %                                                                             %
   1607 %                                                                             %
   1608 %                                                                             %
   1609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1610 %
   1611 %  GetImageExtent() returns the extent of the pixels associated corresponding
   1612 %  with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
   1613 %
   1614 %  The format of the GetImageExtent() method is:
   1615 %
   1616 %      MagickSizeType GetImageExtent(const Image *image)
   1617 %
   1618 %  A description of each parameter follows:
   1619 %
   1620 %    o image: the image.
   1621 %
   1622 */
   1623 MagickExport MagickSizeType GetImageExtent(const Image *image)
   1624 {
   1625   CacheInfo
   1626     *magick_restrict cache_info;
   1627 
   1628   const int
   1629     id = GetOpenMPThreadId();
   1630 
   1631   assert(image != (Image *) NULL);
   1632   assert(image->signature == MagickCoreSignature);
   1633   if (image->debug != MagickFalse)
   1634     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   1635   assert(image->cache != (Cache) NULL);
   1636   cache_info=(CacheInfo *) image->cache;
   1637   assert(cache_info->signature == MagickCoreSignature);
   1638   assert(id < (int) cache_info->number_threads);
   1639   return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
   1640 }
   1641 
   1642 /*
   1644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1645 %                                                                             %
   1646 %                                                                             %
   1647 %                                                                             %
   1648 +   G e t I m a g e P i x e l C a c h e                                       %
   1649 %                                                                             %
   1650 %                                                                             %
   1651 %                                                                             %
   1652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1653 %
   1654 %  GetImagePixelCache() ensures that there is only a single reference to the
   1655 %  pixel cache to be modified, updating the provided cache pointer to point to
   1656 %  a clone of the original pixel cache if necessary.
   1657 %
   1658 %  The format of the GetImagePixelCache method is:
   1659 %
   1660 %      Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
   1661 %        ExceptionInfo *exception)
   1662 %
   1663 %  A description of each parameter follows:
   1664 %
   1665 %    o image: the image.
   1666 %
   1667 %    o clone: any value other than MagickFalse clones the cache pixels.
   1668 %
   1669 %    o exception: return any errors or warnings in this structure.
   1670 %
   1671 */
   1672 
   1673 static inline MagickBooleanType ValidatePixelCacheMorphology(
   1674   const Image *magick_restrict image)
   1675 {
   1676   const CacheInfo
   1677     *magick_restrict cache_info;
   1678 
   1679   const PixelChannelMap
   1680     *magick_restrict p,
   1681     *magick_restrict q;
   1682 
   1683   /*
   1684     Does the image match the pixel cache morphology?
   1685   */
   1686   cache_info=(CacheInfo *) image->cache;
   1687   p=image->channel_map;
   1688   q=cache_info->channel_map;
   1689   if ((image->storage_class != cache_info->storage_class) ||
   1690       (image->colorspace != cache_info->colorspace) ||
   1691       (image->alpha_trait != cache_info->alpha_trait) ||
   1692       (image->channels != cache_info->channels) ||
   1693       (image->columns != cache_info->columns) ||
   1694       (image->rows != cache_info->rows) ||
   1695       (image->number_channels != cache_info->number_channels) ||
   1696       (memcmp(p,q,image->number_channels*sizeof(*p)) != 0) ||
   1697       (image->metacontent_extent != cache_info->metacontent_extent) ||
   1698       (cache_info->nexus_info == (NexusInfo **) NULL))
   1699     return(MagickFalse);
   1700   return(MagickTrue);
   1701 }
   1702 
   1703 static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
   1704   ExceptionInfo *exception)
   1705 {
   1706   CacheInfo
   1707     *magick_restrict cache_info;
   1708 
   1709   MagickBooleanType
   1710     destroy,
   1711     status;
   1712 
   1713   static MagickSizeType
   1714     cache_timelimit = MagickResourceInfinity,
   1715     cpu_throttle = MagickResourceInfinity,
   1716     cycles = 0;
   1717 
   1718   status=MagickTrue;
   1719   if (cpu_throttle == MagickResourceInfinity)
   1720     cpu_throttle=GetMagickResourceLimit(ThrottleResource);
   1721   if ((cpu_throttle != 0) && ((cycles++ % 32) == 0))
   1722     MagickDelay(cpu_throttle);
   1723   if (cache_epoch == 0)
   1724     {
   1725       /*
   1726         Set the expire time in seconds.
   1727       */
   1728       cache_timelimit=GetMagickResourceLimit(TimeResource);
   1729       cache_epoch=time((time_t *) NULL);
   1730     }
   1731   if ((cache_timelimit != MagickResourceInfinity) &&
   1732       ((MagickSizeType) (time((time_t *) NULL)-cache_epoch) >= cache_timelimit))
   1733     {
   1734 #if defined(ECANCELED)
   1735       errno=ECANCELED;
   1736 #endif
   1737       cache_info=(CacheInfo *) image->cache;
   1738       if (cache_info->file != -1)
   1739         (void) ClosePixelCacheOnDisk(cache_info);
   1740       ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
   1741     }
   1742   LockSemaphoreInfo(image->semaphore);
   1743   assert(image->cache != (Cache) NULL);
   1744   cache_info=(CacheInfo *) image->cache;
   1745 #if defined(MAGICKCORE_OPENCL_SUPPORT)
   1746   CopyOpenCLBuffer(cache_info);
   1747 #endif
   1748   destroy=MagickFalse;
   1749   if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
   1750     {
   1751       LockSemaphoreInfo(cache_info->semaphore);
   1752       if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
   1753         {
   1754           CacheInfo
   1755             *clone_info;
   1756 
   1757           Image
   1758             clone_image;
   1759 
   1760           /*
   1761             Clone pixel cache.
   1762           */
   1763           clone_image=(*image);
   1764           clone_image.semaphore=AcquireSemaphoreInfo();
   1765           clone_image.reference_count=1;
   1766           clone_image.cache=ClonePixelCache(cache_info);
   1767           clone_info=(CacheInfo *) clone_image.cache;
   1768           status=OpenPixelCache(&clone_image,IOMode,exception);
   1769           if (status == MagickFalse)
   1770             clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
   1771           else
   1772             {
   1773               if (clone != MagickFalse)
   1774                 status=ClonePixelCacheRepository(clone_info,cache_info,
   1775                   exception);
   1776               if (status == MagickFalse)
   1777                 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
   1778               else
   1779                 {
   1780                   destroy=MagickTrue;
   1781                   image->cache=clone_info;
   1782                 }
   1783             }
   1784           RelinquishSemaphoreInfo(&clone_image.semaphore);
   1785         }
   1786       UnlockSemaphoreInfo(cache_info->semaphore);
   1787     }
   1788   if (destroy != MagickFalse)
   1789     cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
   1790   if (status != MagickFalse)
   1791     {
   1792       /*
   1793         Ensure the image matches the pixel cache morphology.
   1794       */
   1795       image->type=UndefinedType;
   1796       if (ValidatePixelCacheMorphology(image) == MagickFalse)
   1797         {
   1798           status=OpenPixelCache(image,IOMode,exception);
   1799           cache_info=(CacheInfo *) image->cache;
   1800           if (cache_info->file != -1)
   1801             (void) ClosePixelCacheOnDisk(cache_info);
   1802         }
   1803     }
   1804   UnlockSemaphoreInfo(image->semaphore);
   1805   if (status == MagickFalse)
   1806     return((Cache) NULL);
   1807   return(image->cache);
   1808 }
   1809 
   1810 /*
   1812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1813 %                                                                             %
   1814 %                                                                             %
   1815 %                                                                             %
   1816 +   G e t I m a g e P i x e l C a c h e T y p e                               %
   1817 %                                                                             %
   1818 %                                                                             %
   1819 %                                                                             %
   1820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1821 %
   1822 %  GetImagePixelCacheType() returns the pixel cache type: UndefinedCache,
   1823 %  DiskCache, MemoryCache, MapCache, or PingCache.
   1824 %
   1825 %  The format of the GetImagePixelCacheType() method is:
   1826 %
   1827 %      CacheType GetImagePixelCacheType(const Image *image)
   1828 %
   1829 %  A description of each parameter follows:
   1830 %
   1831 %    o image: the image.
   1832 %
   1833 */
   1834 MagickExport CacheType GetImagePixelCacheType(const Image *image)
   1835 {
   1836   CacheInfo
   1837     *magick_restrict cache_info;
   1838 
   1839   assert(image != (Image *) NULL);
   1840   assert(image->signature == MagickCoreSignature);
   1841   assert(image->cache != (Cache) NULL);
   1842   cache_info=(CacheInfo *) image->cache;
   1843   assert(cache_info->signature == MagickCoreSignature);
   1844   return(cache_info->type);
   1845 }
   1846 
   1847 /*
   1849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1850 %                                                                             %
   1851 %                                                                             %
   1852 %                                                                             %
   1853 %   G e t O n e A u t h e n t i c P i x e l                                   %
   1854 %                                                                             %
   1855 %                                                                             %
   1856 %                                                                             %
   1857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1858 %
   1859 %  GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
   1860 %  location.  The image background color is returned if an error occurs.
   1861 %
   1862 %  The format of the GetOneAuthenticPixel() method is:
   1863 %
   1864 %      MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
   1865 %        const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
   1866 %
   1867 %  A description of each parameter follows:
   1868 %
   1869 %    o image: the image.
   1870 %
   1871 %    o x,y:  These values define the location of the pixel to return.
   1872 %
   1873 %    o pixel: return a pixel at the specified (x,y) location.
   1874 %
   1875 %    o exception: return any errors or warnings in this structure.
   1876 %
   1877 */
   1878 
   1879 static inline MagickBooleanType CopyPixel(const Image *image,
   1880   const Quantum *source,Quantum *destination)
   1881 {
   1882   register ssize_t
   1883     i;
   1884 
   1885   if (source == (const Quantum *) NULL)
   1886     {
   1887       destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
   1888       destination[GreenPixelChannel]=ClampToQuantum(
   1889         image->background_color.green);
   1890       destination[BluePixelChannel]=ClampToQuantum(
   1891         image->background_color.blue);
   1892       destination[BlackPixelChannel]=ClampToQuantum(
   1893         image->background_color.black);
   1894       destination[AlphaPixelChannel]=ClampToQuantum(
   1895         image->background_color.alpha);
   1896       return(MagickFalse);
   1897     }
   1898   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
   1899   {
   1900     PixelChannel channel = GetPixelChannelChannel(image,i);
   1901     destination[channel]=source[i];
   1902   }
   1903   return(MagickTrue);
   1904 }
   1905 
   1906 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
   1907   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
   1908 {
   1909   CacheInfo
   1910     *magick_restrict cache_info;
   1911 
   1912   register Quantum
   1913     *magick_restrict q;
   1914 
   1915   assert(image != (Image *) NULL);
   1916   assert(image->signature == MagickCoreSignature);
   1917   assert(image->cache != (Cache) NULL);
   1918   cache_info=(CacheInfo *) image->cache;
   1919   assert(cache_info->signature == MagickCoreSignature);
   1920   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
   1921   if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
   1922     return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
   1923   q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
   1924   return(CopyPixel(image,q,pixel));
   1925 }
   1926 
   1927 /*
   1929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1930 %                                                                             %
   1931 %                                                                             %
   1932 %                                                                             %
   1933 +   G e t O n e A u t h e n t i c P i x e l F r o m C a c h e                 %
   1934 %                                                                             %
   1935 %                                                                             %
   1936 %                                                                             %
   1937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1938 %
   1939 %  GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
   1940 %  location.  The image background color is returned if an error occurs.
   1941 %
   1942 %  The format of the GetOneAuthenticPixelFromCache() method is:
   1943 %
   1944 %      MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
   1945 %        const ssize_t x,const ssize_t y,Quantum *pixel,
   1946 %        ExceptionInfo *exception)
   1947 %
   1948 %  A description of each parameter follows:
   1949 %
   1950 %    o image: the image.
   1951 %
   1952 %    o x,y:  These values define the location of the pixel to return.
   1953 %
   1954 %    o pixel: return a pixel at the specified (x,y) location.
   1955 %
   1956 %    o exception: return any errors or warnings in this structure.
   1957 %
   1958 */
   1959 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
   1960   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
   1961 {
   1962   CacheInfo
   1963     *magick_restrict cache_info;
   1964 
   1965   const int
   1966     id = GetOpenMPThreadId();
   1967 
   1968   register Quantum
   1969     *magick_restrict q;
   1970 
   1971   assert(image != (const Image *) NULL);
   1972   assert(image->signature == MagickCoreSignature);
   1973   assert(image->cache != (Cache) NULL);
   1974   cache_info=(CacheInfo *) image->cache;
   1975   assert(cache_info->signature == MagickCoreSignature);
   1976   assert(id < (int) cache_info->number_threads);
   1977   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
   1978   q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
   1979     exception);
   1980   return(CopyPixel(image,q,pixel));
   1981 }
   1982 
   1983 /*
   1985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1986 %                                                                             %
   1987 %                                                                             %
   1988 %                                                                             %
   1989 %   G e t O n e V i r t u a l P i x e l                                       %
   1990 %                                                                             %
   1991 %                                                                             %
   1992 %                                                                             %
   1993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1994 %
   1995 %  GetOneVirtualPixel() returns a single virtual pixel at the specified
   1996 %  (x,y) location.  The image background color is returned if an error occurs.
   1997 %  If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
   1998 %
   1999 %  The format of the GetOneVirtualPixel() method is:
   2000 %
   2001 %      MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
   2002 %        const ssize_t y,Quantum *pixel,ExceptionInfo exception)
   2003 %
   2004 %  A description of each parameter follows:
   2005 %
   2006 %    o image: the image.
   2007 %
   2008 %    o x,y:  These values define the location of the pixel to return.
   2009 %
   2010 %    o pixel: return a pixel at the specified (x,y) location.
   2011 %
   2012 %    o exception: return any errors or warnings in this structure.
   2013 %
   2014 */
   2015 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
   2016   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
   2017 {
   2018   CacheInfo
   2019     *magick_restrict cache_info;
   2020 
   2021   const int
   2022     id = GetOpenMPThreadId();
   2023 
   2024   const Quantum
   2025     *p;
   2026 
   2027   assert(image != (const Image *) NULL);
   2028   assert(image->signature == MagickCoreSignature);
   2029   assert(image->cache != (Cache) NULL);
   2030   cache_info=(CacheInfo *) image->cache;
   2031   assert(cache_info->signature == MagickCoreSignature);
   2032   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
   2033   if (cache_info->methods.get_one_virtual_pixel_from_handler !=
   2034        (GetOneVirtualPixelFromHandler) NULL)
   2035     return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
   2036       GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
   2037   assert(id < (int) cache_info->number_threads);
   2038   p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
   2039     1UL,1UL,cache_info->nexus_info[id],exception);
   2040   return(CopyPixel(image,p,pixel));
   2041 }
   2042 
   2043 /*
   2045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2046 %                                                                             %
   2047 %                                                                             %
   2048 %                                                                             %
   2049 +   G e t O n e V i r t u a l P i x e l F r o m C a c h e                     %
   2050 %                                                                             %
   2051 %                                                                             %
   2052 %                                                                             %
   2053 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2054 %
   2055 %  GetOneVirtualPixelFromCache() returns a single virtual pixel at the
   2056 %  specified (x,y) location.  The image background color is returned if an
   2057 %  error occurs.
   2058 %
   2059 %  The format of the GetOneVirtualPixelFromCache() method is:
   2060 %
   2061 %      MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
   2062 %        const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
   2063 %        Quantum *pixel,ExceptionInfo *exception)
   2064 %
   2065 %  A description of each parameter follows:
   2066 %
   2067 %    o image: the image.
   2068 %
   2069 %    o virtual_pixel_method: the virtual pixel method.
   2070 %
   2071 %    o x,y:  These values define the location of the pixel to return.
   2072 %
   2073 %    o pixel: return a pixel at the specified (x,y) location.
   2074 %
   2075 %    o exception: return any errors or warnings in this structure.
   2076 %
   2077 */
   2078 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
   2079   const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
   2080   Quantum *pixel,ExceptionInfo *exception)
   2081 {
   2082   CacheInfo
   2083     *magick_restrict cache_info;
   2084 
   2085   const int
   2086     id = GetOpenMPThreadId();
   2087 
   2088   const Quantum
   2089     *p;
   2090 
   2091   assert(image != (const Image *) NULL);
   2092   assert(image->signature == MagickCoreSignature);
   2093   assert(image->cache != (Cache) NULL);
   2094   cache_info=(CacheInfo *) image->cache;
   2095   assert(cache_info->signature == MagickCoreSignature);
   2096   assert(id < (int) cache_info->number_threads);
   2097   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
   2098   p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
   2099     cache_info->nexus_info[id],exception);
   2100   return(CopyPixel(image,p,pixel));
   2101 }
   2102 
   2103 /*
   2105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2106 %                                                                             %
   2107 %                                                                             %
   2108 %                                                                             %
   2109 %   G e t O n e V i r t u a l P i x e l I n f o                               %
   2110 %                                                                             %
   2111 %                                                                             %
   2112 %                                                                             %
   2113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2114 %
   2115 %  GetOneVirtualPixelInfo() returns a single pixel at the specified (x,y)
   2116 %  location.  The image background color is returned if an error occurs.  If
   2117 %  you plan to modify the pixel, use GetOneAuthenticPixel() instead.
   2118 %
   2119 %  The format of the GetOneVirtualPixelInfo() method is:
   2120 %
   2121 %      MagickBooleanType GetOneVirtualPixelInfo(const Image image,
   2122 %        const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
   2123 %        const ssize_t y,PixelInfo *pixel,ExceptionInfo exception)
   2124 %
   2125 %  A description of each parameter follows:
   2126 %
   2127 %    o image: the image.
   2128 %
   2129 %    o virtual_pixel_method: the virtual pixel method.
   2130 %
   2131 %    o x,y:  these values define the location of the pixel to return.
   2132 %
   2133 %    o pixel: return a pixel at the specified (x,y) location.
   2134 %
   2135 %    o exception: return any errors or warnings in this structure.
   2136 %
   2137 */
   2138 MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
   2139   const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
   2140   PixelInfo *pixel,ExceptionInfo *exception)
   2141 {
   2142   CacheInfo
   2143     *magick_restrict cache_info;
   2144 
   2145   const int
   2146     id = GetOpenMPThreadId();
   2147 
   2148   register const Quantum
   2149     *magick_restrict p;
   2150 
   2151   assert(image != (const Image *) NULL);
   2152   assert(image->signature == MagickCoreSignature);
   2153   assert(image->cache != (Cache) NULL);
   2154   cache_info=(CacheInfo *) image->cache;
   2155   assert(cache_info->signature == MagickCoreSignature);
   2156   assert(id < (int) cache_info->number_threads);
   2157   GetPixelInfo(image,pixel);
   2158   p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
   2159     cache_info->nexus_info[id],exception);
   2160   if (p == (const Quantum *) NULL)
   2161     return(MagickFalse);
   2162   GetPixelInfoPixel(image,p,pixel);
   2163   return(MagickTrue);
   2164 }
   2165 
   2166 /*
   2168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2169 %                                                                             %
   2170 %                                                                             %
   2171 %                                                                             %
   2172 +   G e t P i x e l C a c h e C o l o r s p a c e                             %
   2173 %                                                                             %
   2174 %                                                                             %
   2175 %                                                                             %
   2176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2177 %
   2178 %  GetPixelCacheColorspace() returns the class type of the pixel cache.
   2179 %
   2180 %  The format of the GetPixelCacheColorspace() method is:
   2181 %
   2182 %      Colorspace GetPixelCacheColorspace(Cache cache)
   2183 %
   2184 %  A description of each parameter follows:
   2185 %
   2186 %    o cache: the pixel cache.
   2187 %
   2188 */
   2189 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
   2190 {
   2191   CacheInfo
   2192     *magick_restrict cache_info;
   2193 
   2194   assert(cache != (Cache) NULL);
   2195   cache_info=(CacheInfo *) cache;
   2196   assert(cache_info->signature == MagickCoreSignature);
   2197   if (cache_info->debug != MagickFalse)
   2198     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   2199       cache_info->filename);
   2200   return(cache_info->colorspace);
   2201 }
   2202 
   2203 /*
   2205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2206 %                                                                             %
   2207 %                                                                             %
   2208 %                                                                             %
   2209 +   G e t P i x e l C a c h e F i l e n a m e                                 %
   2210 %                                                                             %
   2211 %                                                                             %
   2212 %                                                                             %
   2213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2214 %
   2215 %  GetPixelCacheFilename() returns the filename associated with the pixel
   2216 %  cache.
   2217 %
   2218 %  The format of the GetPixelCacheFilename() method is:
   2219 %
   2220 %      const char *GetPixelCacheFilename(const Image *image)
   2221 %
   2222 %  A description of each parameter follows:
   2223 %
   2224 %    o image: the image.
   2225 %
   2226 */
   2227 MagickExport const char *GetPixelCacheFilename(const Image *image)
   2228 {
   2229   CacheInfo
   2230     *magick_restrict cache_info;
   2231 
   2232   assert(image != (const Image *) NULL);
   2233   assert(image->signature == MagickCoreSignature);
   2234   assert(image->cache != (Cache) NULL);
   2235   cache_info=(CacheInfo *) image->cache;
   2236   assert(cache_info->signature == MagickCoreSignature);
   2237   return(cache_info->cache_filename);
   2238 }
   2239 
   2240 /*
   2242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2243 %                                                                             %
   2244 %                                                                             %
   2245 %                                                                             %
   2246 +   G e t P i x e l C a c h e M e t h o d s                                   %
   2247 %                                                                             %
   2248 %                                                                             %
   2249 %                                                                             %
   2250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2251 %
   2252 %  GetPixelCacheMethods() initializes the CacheMethods structure.
   2253 %
   2254 %  The format of the GetPixelCacheMethods() method is:
   2255 %
   2256 %      void GetPixelCacheMethods(CacheMethods *cache_methods)
   2257 %
   2258 %  A description of each parameter follows:
   2259 %
   2260 %    o cache_methods: Specifies a pointer to a CacheMethods structure.
   2261 %
   2262 */
   2263 MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
   2264 {
   2265   assert(cache_methods != (CacheMethods *) NULL);
   2266   (void) memset(cache_methods,0,sizeof(*cache_methods));
   2267   cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
   2268   cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
   2269   cache_methods->get_virtual_metacontent_from_handler=
   2270     GetVirtualMetacontentFromCache;
   2271   cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
   2272   cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
   2273   cache_methods->get_authentic_metacontent_from_handler=
   2274     GetAuthenticMetacontentFromCache;
   2275   cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
   2276   cache_methods->get_one_authentic_pixel_from_handler=
   2277     GetOneAuthenticPixelFromCache;
   2278   cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
   2279   cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
   2280   cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
   2281 }
   2282 
   2283 /*
   2285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2286 %                                                                             %
   2287 %                                                                             %
   2288 %                                                                             %
   2289 +   G e t P i x e l C a c h e N e x u s E x t e n t                           %
   2290 %                                                                             %
   2291 %                                                                             %
   2292 %                                                                             %
   2293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2294 %
   2295 %  GetPixelCacheNexusExtent() returns the extent of the pixels associated
   2296 %  corresponding with the last call to SetPixelCacheNexusPixels() or
   2297 %  GetPixelCacheNexusPixels().
   2298 %
   2299 %  The format of the GetPixelCacheNexusExtent() method is:
   2300 %
   2301 %      MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
   2302 %        NexusInfo *nexus_info)
   2303 %
   2304 %  A description of each parameter follows:
   2305 %
   2306 %    o nexus_info: the nexus info.
   2307 %
   2308 */
   2309 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
   2310   NexusInfo *magick_restrict nexus_info)
   2311 {
   2312   CacheInfo
   2313     *magick_restrict cache_info;
   2314 
   2315   MagickSizeType
   2316     extent;
   2317 
   2318   assert(cache != NULL);
   2319   cache_info=(CacheInfo *) cache;
   2320   assert(cache_info->signature == MagickCoreSignature);
   2321   extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
   2322   if (extent == 0)
   2323     return((MagickSizeType) cache_info->columns*cache_info->rows);
   2324   return(extent);
   2325 }
   2326 
   2327 /*
   2329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2330 %                                                                             %
   2331 %                                                                             %
   2332 %                                                                             %
   2333 +   G e t P i x e l C a c h e P i x e l s                                     %
   2334 %                                                                             %
   2335 %                                                                             %
   2336 %                                                                             %
   2337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2338 %
   2339 %  GetPixelCachePixels() returns the pixels associated with the specified image.
   2340 %
   2341 %  The format of the GetPixelCachePixels() method is:
   2342 %
   2343 %      void *GetPixelCachePixels(Image *image,MagickSizeType *length,
   2344 %        ExceptionInfo *exception)
   2345 %
   2346 %  A description of each parameter follows:
   2347 %
   2348 %    o image: the image.
   2349 %
   2350 %    o length: the pixel cache length.
   2351 %
   2352 %    o exception: return any errors or warnings in this structure.
   2353 %
   2354 */
   2355 MagickExport void *GetPixelCachePixels(Image *image,MagickSizeType *length,
   2356   ExceptionInfo *exception)
   2357 {
   2358   CacheInfo
   2359     *magick_restrict cache_info;
   2360 
   2361   assert(image != (const Image *) NULL);
   2362   assert(image->signature == MagickCoreSignature);
   2363   assert(image->cache != (Cache) NULL);
   2364   assert(length != (MagickSizeType *) NULL);
   2365   assert(exception != (ExceptionInfo *) NULL);
   2366   assert(exception->signature == MagickCoreSignature);
   2367   cache_info=(CacheInfo *) image->cache;
   2368   assert(cache_info->signature == MagickCoreSignature);
   2369   *length=cache_info->length;
   2370   if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
   2371     return((void *) NULL);
   2372   return((void *) cache_info->pixels);
   2373 }
   2374 
   2375 /*
   2377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2378 %                                                                             %
   2379 %                                                                             %
   2380 %                                                                             %
   2381 +   G e t P i x e l C a c h e S t o r a g e C l a s s                         %
   2382 %                                                                             %
   2383 %                                                                             %
   2384 %                                                                             %
   2385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2386 %
   2387 %  GetPixelCacheStorageClass() returns the class type of the pixel cache.
   2388 %
   2389 %  The format of the GetPixelCacheStorageClass() method is:
   2390 %
   2391 %      ClassType GetPixelCacheStorageClass(Cache cache)
   2392 %
   2393 %  A description of each parameter follows:
   2394 %
   2395 %    o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
   2396 %
   2397 %    o cache: the pixel cache.
   2398 %
   2399 */
   2400 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
   2401 {
   2402   CacheInfo
   2403     *magick_restrict cache_info;
   2404 
   2405   assert(cache != (Cache) NULL);
   2406   cache_info=(CacheInfo *) cache;
   2407   assert(cache_info->signature == MagickCoreSignature);
   2408   if (cache_info->debug != MagickFalse)
   2409     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   2410       cache_info->filename);
   2411   return(cache_info->storage_class);
   2412 }
   2413 
   2414 /*
   2416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2417 %                                                                             %
   2418 %                                                                             %
   2419 %                                                                             %
   2420 +   G e t P i x e l C a c h e T i l e S i z e                                 %
   2421 %                                                                             %
   2422 %                                                                             %
   2423 %                                                                             %
   2424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2425 %
   2426 %  GetPixelCacheTileSize() returns the pixel cache tile size.
   2427 %
   2428 %  The format of the GetPixelCacheTileSize() method is:
   2429 %
   2430 %      void GetPixelCacheTileSize(const Image *image,size_t *width,
   2431 %        size_t *height)
   2432 %
   2433 %  A description of each parameter follows:
   2434 %
   2435 %    o image: the image.
   2436 %
   2437 %    o width: the optimized cache tile width in pixels.
   2438 %
   2439 %    o height: the optimized cache tile height in pixels.
   2440 %
   2441 */
   2442 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
   2443   size_t *height)
   2444 {
   2445   CacheInfo
   2446     *magick_restrict cache_info;
   2447 
   2448   assert(image != (Image *) NULL);
   2449   assert(image->signature == MagickCoreSignature);
   2450   if (image->debug != MagickFalse)
   2451     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   2452   cache_info=(CacheInfo *) image->cache;
   2453   assert(cache_info->signature == MagickCoreSignature);
   2454   *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
   2455   if (GetImagePixelCacheType(image) == DiskCache)
   2456     *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
   2457   *height=(*width);
   2458 }
   2459 
   2460 /*
   2462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2463 %                                                                             %
   2464 %                                                                             %
   2465 %                                                                             %
   2466 +   G e t P i x e l C a c h e V i r t u a l M e t h o d                       %
   2467 %                                                                             %
   2468 %                                                                             %
   2469 %                                                                             %
   2470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2471 %
   2472 %  GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
   2473 %  pixel cache.  A virtual pixel is any pixel access that is outside the
   2474 %  boundaries of the image cache.
   2475 %
   2476 %  The format of the GetPixelCacheVirtualMethod() method is:
   2477 %
   2478 %      VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
   2479 %
   2480 %  A description of each parameter follows:
   2481 %
   2482 %    o image: the image.
   2483 %
   2484 */
   2485 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
   2486 {
   2487   CacheInfo
   2488     *magick_restrict cache_info;
   2489 
   2490   assert(image != (Image *) NULL);
   2491   assert(image->signature == MagickCoreSignature);
   2492   assert(image->cache != (Cache) NULL);
   2493   cache_info=(CacheInfo *) image->cache;
   2494   assert(cache_info->signature == MagickCoreSignature);
   2495   return(cache_info->virtual_pixel_method);
   2496 }
   2497 
   2498 /*
   2500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2501 %                                                                             %
   2502 %                                                                             %
   2503 %                                                                             %
   2504 +   G e t V i r t u a l M e t a c o n t e n t F r o m C a c h e               %
   2505 %                                                                             %
   2506 %                                                                             %
   2507 %                                                                             %
   2508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2509 %
   2510 %  GetVirtualMetacontentFromCache() returns the meta-content corresponding with
   2511 %  the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
   2512 %
   2513 %  The format of the GetVirtualMetacontentFromCache() method is:
   2514 %
   2515 %      void *GetVirtualMetacontentFromCache(const Image *image)
   2516 %
   2517 %  A description of each parameter follows:
   2518 %
   2519 %    o image: the image.
   2520 %
   2521 */
   2522 static const void *GetVirtualMetacontentFromCache(const Image *image)
   2523 {
   2524   CacheInfo
   2525     *magick_restrict cache_info;
   2526 
   2527   const int
   2528     id = GetOpenMPThreadId();
   2529 
   2530   const void
   2531     *magick_restrict metacontent;
   2532 
   2533   assert(image != (const Image *) NULL);
   2534   assert(image->signature == MagickCoreSignature);
   2535   assert(image->cache != (Cache) NULL);
   2536   cache_info=(CacheInfo *) image->cache;
   2537   assert(cache_info->signature == MagickCoreSignature);
   2538   assert(id < (int) cache_info->number_threads);
   2539   metacontent=GetVirtualMetacontentFromNexus(cache_info,
   2540     cache_info->nexus_info[id]);
   2541   return(metacontent);
   2542 }
   2543 
   2544 /*
   2546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2547 %                                                                             %
   2548 %                                                                             %
   2549 %                                                                             %
   2550 +   G e t V i r t u a l M e t a c o n t e n t F r o m N e x u s               %
   2551 %                                                                             %
   2552 %                                                                             %
   2553 %                                                                             %
   2554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2555 %
   2556 %  GetVirtualMetacontentFromNexus() returns the meta-content for the specified
   2557 %  cache nexus.
   2558 %
   2559 %  The format of the GetVirtualMetacontentFromNexus() method is:
   2560 %
   2561 %      const void *GetVirtualMetacontentFromNexus(const Cache cache,
   2562 %        NexusInfo *nexus_info)
   2563 %
   2564 %  A description of each parameter follows:
   2565 %
   2566 %    o cache: the pixel cache.
   2567 %
   2568 %    o nexus_info: the cache nexus to return the meta-content.
   2569 %
   2570 */
   2571 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
   2572   NexusInfo *magick_restrict nexus_info)
   2573 {
   2574   CacheInfo
   2575     *magick_restrict cache_info;
   2576 
   2577   assert(cache != (Cache) NULL);
   2578   cache_info=(CacheInfo *) cache;
   2579   assert(cache_info->signature == MagickCoreSignature);
   2580   if (cache_info->storage_class == UndefinedClass)
   2581     return((void *) NULL);
   2582   return(nexus_info->metacontent);
   2583 }
   2584 
   2585 /*
   2587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2588 %                                                                             %
   2589 %                                                                             %
   2590 %                                                                             %
   2591 %   G e t V i r t u a l M e t a c o n t e n t                                 %
   2592 %                                                                             %
   2593 %                                                                             %
   2594 %                                                                             %
   2595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2596 %
   2597 %  GetVirtualMetacontent() returns the virtual metacontent corresponding with
   2598 %  the last call to QueueAuthenticPixels() or GetVirtualPixels().  NULL is
   2599 %  returned if the meta-content are not available.
   2600 %
   2601 %  The format of the GetVirtualMetacontent() method is:
   2602 %
   2603 %      const void *GetVirtualMetacontent(const Image *image)
   2604 %
   2605 %  A description of each parameter follows:
   2606 %
   2607 %    o image: the image.
   2608 %
   2609 */
   2610 MagickExport const void *GetVirtualMetacontent(const Image *image)
   2611 {
   2612   CacheInfo
   2613     *magick_restrict cache_info;
   2614 
   2615   const int
   2616     id = GetOpenMPThreadId();
   2617 
   2618   const void
   2619     *magick_restrict metacontent;
   2620 
   2621   assert(image != (const Image *) NULL);
   2622   assert(image->signature == MagickCoreSignature);
   2623   assert(image->cache != (Cache) NULL);
   2624   cache_info=(CacheInfo *) image->cache;
   2625   assert(cache_info->signature == MagickCoreSignature);
   2626   metacontent=cache_info->methods.get_virtual_metacontent_from_handler(image);
   2627   if (metacontent != (void *) NULL)
   2628     return(metacontent);
   2629   assert(id < (int) cache_info->number_threads);
   2630   metacontent=GetVirtualMetacontentFromNexus(cache_info,
   2631     cache_info->nexus_info[id]);
   2632   return(metacontent);
   2633 }
   2634 
   2635 /*
   2637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2638 %                                                                             %
   2639 %                                                                             %
   2640 %                                                                             %
   2641 +   G e t V i r t u a l P i x e l C a c h e N e x u s                         %
   2642 %                                                                             %
   2643 %                                                                             %
   2644 %                                                                             %
   2645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2646 %
   2647 %  GetVirtualPixelCacheNexus() gets virtual pixels from the in-memory or disk
   2648 %  pixel cache as defined by the geometry parameters.   A pointer to the pixels
   2649 %  is returned if the pixels are transferred, otherwise a NULL is returned.
   2650 %
   2651 %  The format of the GetVirtualPixelCacheNexus() method is:
   2652 %
   2653 %      Quantum *GetVirtualPixelCacheNexus(const Image *image,
   2654 %        const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
   2655 %        const size_t columns,const size_t rows,NexusInfo *nexus_info,
   2656 %        ExceptionInfo *exception)
   2657 %
   2658 %  A description of each parameter follows:
   2659 %
   2660 %    o image: the image.
   2661 %
   2662 %    o virtual_pixel_method: the virtual pixel method.
   2663 %
   2664 %    o x,y,columns,rows:  These values define the perimeter of a region of
   2665 %      pixels.
   2666 %
   2667 %    o nexus_info: the cache nexus to acquire.
   2668 %
   2669 %    o exception: return any errors or warnings in this structure.
   2670 %
   2671 */
   2672 
   2673 static ssize_t
   2674   DitherMatrix[64] =
   2675   {
   2676      0,  48,  12,  60,   3,  51,  15,  63,
   2677     32,  16,  44,  28,  35,  19,  47,  31,
   2678      8,  56,   4,  52,  11,  59,   7,  55,
   2679     40,  24,  36,  20,  43,  27,  39,  23,
   2680      2,  50,  14,  62,   1,  49,  13,  61,
   2681     34,  18,  46,  30,  33,  17,  45,  29,
   2682     10,  58,   6,  54,   9,  57,   5,  53,
   2683     42,  26,  38,  22,  41,  25,  37,  21
   2684   };
   2685 
   2686 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
   2687 {
   2688   ssize_t
   2689     index;
   2690 
   2691   index=x+DitherMatrix[x & 0x07]-32L;
   2692   if (index < 0L)
   2693     return(0L);
   2694   if (index >= (ssize_t) columns)
   2695     return((ssize_t) columns-1L);
   2696   return(index);
   2697 }
   2698 
   2699 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
   2700 {
   2701   ssize_t
   2702     index;
   2703 
   2704   index=y+DitherMatrix[y & 0x07]-32L;
   2705   if (index < 0L)
   2706     return(0L);
   2707   if (index >= (ssize_t) rows)
   2708     return((ssize_t) rows-1L);
   2709   return(index);
   2710 }
   2711 
   2712 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
   2713 {
   2714   if (x < 0L)
   2715     return(0L);
   2716   if (x >= (ssize_t) columns)
   2717     return((ssize_t) (columns-1));
   2718   return(x);
   2719 }
   2720 
   2721 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
   2722 {
   2723   if (y < 0L)
   2724     return(0L);
   2725   if (y >= (ssize_t) rows)
   2726     return((ssize_t) (rows-1));
   2727   return(y);
   2728 }
   2729 
   2730 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
   2731 {
   2732   return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
   2733 }
   2734 
   2735 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
   2736 {
   2737   return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
   2738 }
   2739 
   2740 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
   2741   const size_t extent)
   2742 {
   2743   MagickModulo
   2744     modulo;
   2745 
   2746   /*
   2747     Compute the remainder of dividing offset by extent.  It returns not only
   2748     the quotient (tile the offset falls in) but also the positive remainer
   2749     within that tile such that 0 <= remainder < extent.  This method is
   2750     essentially a ldiv() using a floored modulo division rather than the
   2751     normal default truncated modulo division.
   2752   */
   2753   modulo.quotient=offset/(ssize_t) extent;
   2754   if ((offset < 0L) && (modulo.quotient > (ssize_t) (-SSIZE_MAX)))
   2755     modulo.quotient--;
   2756   modulo.remainder=(ssize_t) (offset-(double) modulo.quotient*extent);
   2757   return(modulo);
   2758 }
   2759 
   2760 MagickPrivate const Quantum *GetVirtualPixelCacheNexus(const Image *image,
   2761   const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
   2762   const size_t columns,const size_t rows,NexusInfo *nexus_info,
   2763   ExceptionInfo *exception)
   2764 {
   2765   CacheInfo
   2766     *magick_restrict cache_info;
   2767 
   2768   MagickOffsetType
   2769     offset;
   2770 
   2771   MagickSizeType
   2772     length,
   2773     number_pixels;
   2774 
   2775   NexusInfo
   2776     **magick_restrict virtual_nexus;
   2777 
   2778   Quantum
   2779     *magick_restrict pixels,
   2780     virtual_pixel[MaxPixelChannels];
   2781 
   2782   RectangleInfo
   2783     region;
   2784 
   2785   register const Quantum
   2786     *magick_restrict p;
   2787 
   2788   register const void
   2789     *magick_restrict r;
   2790 
   2791   register Quantum
   2792     *magick_restrict q;
   2793 
   2794   register ssize_t
   2795     i,
   2796     u;
   2797 
   2798   register unsigned char
   2799     *magick_restrict s;
   2800 
   2801   ssize_t
   2802     v;
   2803 
   2804   void
   2805     *magick_restrict virtual_metacontent;
   2806 
   2807   /*
   2808     Acquire pixels.
   2809   */
   2810   assert(image != (const Image *) NULL);
   2811   assert(image->signature == MagickCoreSignature);
   2812   assert(image->cache != (Cache) NULL);
   2813   cache_info=(CacheInfo *) image->cache;
   2814   assert(cache_info->signature == MagickCoreSignature);
   2815   if (cache_info->type == UndefinedCache)
   2816     return((const Quantum *) NULL);
   2817 #if defined(MAGICKCORE_OPENCL_SUPPORT)
   2818   CopyOpenCLBuffer(cache_info);
   2819 #endif
   2820   region.x=x;
   2821   region.y=y;
   2822   region.width=columns;
   2823   region.height=rows;
   2824   pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,
   2825     ((image->channels & WriteMaskChannel) != 0) ||
   2826     ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
   2827     nexus_info,exception);
   2828   if (pixels == (Quantum *) NULL)
   2829     return((const Quantum *) NULL);
   2830   q=pixels;
   2831   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
   2832     nexus_info->region.x;
   2833   length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
   2834     nexus_info->region.width-1L;
   2835   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
   2836   if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
   2837     if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
   2838         (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
   2839       {
   2840         MagickBooleanType
   2841           status;
   2842 
   2843         /*
   2844           Pixel request is inside cache extents.
   2845         */
   2846         if (nexus_info->authentic_pixel_cache != MagickFalse)
   2847           return(q);
   2848         status=ReadPixelCachePixels(cache_info,nexus_info,exception);
   2849         if (status == MagickFalse)
   2850           return((const Quantum *) NULL);
   2851         if (cache_info->metacontent_extent != 0)
   2852           {
   2853             status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
   2854             if (status == MagickFalse)
   2855               return((const Quantum *) NULL);
   2856           }
   2857         return(q);
   2858       }
   2859   /*
   2860     Pixel request is outside cache extents.
   2861   */
   2862   s=(unsigned char *) nexus_info->metacontent;
   2863   virtual_nexus=AcquirePixelCacheNexus(1);
   2864   (void) memset(virtual_pixel,0,cache_info->number_channels*
   2865     sizeof(*virtual_pixel));
   2866   virtual_metacontent=(void *) NULL;
   2867   switch (virtual_pixel_method)
   2868   {
   2869     case BackgroundVirtualPixelMethod:
   2870     case BlackVirtualPixelMethod:
   2871     case GrayVirtualPixelMethod:
   2872     case TransparentVirtualPixelMethod:
   2873     case MaskVirtualPixelMethod:
   2874     case WhiteVirtualPixelMethod:
   2875     case EdgeVirtualPixelMethod:
   2876     case CheckerTileVirtualPixelMethod:
   2877     case HorizontalTileVirtualPixelMethod:
   2878     case VerticalTileVirtualPixelMethod:
   2879     {
   2880       if (cache_info->metacontent_extent != 0)
   2881         {
   2882           /*
   2883             Acquire a metacontent buffer.
   2884           */
   2885           virtual_metacontent=(void *) AcquireQuantumMemory(1,
   2886             cache_info->metacontent_extent);
   2887           if (virtual_metacontent == (void *) NULL)
   2888             {
   2889               virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
   2890               (void) ThrowMagickException(exception,GetMagickModule(),
   2891                 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
   2892               return((const Quantum *) NULL);
   2893             }
   2894           (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
   2895         }
   2896       switch (virtual_pixel_method)
   2897       {
   2898         case BlackVirtualPixelMethod:
   2899         {
   2900           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
   2901             SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
   2902           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
   2903           break;
   2904         }
   2905         case GrayVirtualPixelMethod:
   2906         {
   2907           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
   2908             SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
   2909               virtual_pixel);
   2910           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
   2911           break;
   2912         }
   2913         case TransparentVirtualPixelMethod:
   2914         {
   2915           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
   2916             SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
   2917           SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
   2918           break;
   2919         }
   2920         case MaskVirtualPixelMethod:
   2921         case WhiteVirtualPixelMethod:
   2922         {
   2923           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
   2924             SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
   2925           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
   2926           break;
   2927         }
   2928         default:
   2929         {
   2930           SetPixelRed(image,ClampToQuantum(image->background_color.red),
   2931             virtual_pixel);
   2932           SetPixelGreen(image,ClampToQuantum(image->background_color.green),
   2933             virtual_pixel);
   2934           SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
   2935             virtual_pixel);
   2936           SetPixelBlack(image,ClampToQuantum(image->background_color.black),
   2937             virtual_pixel);
   2938           SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
   2939             virtual_pixel);
   2940           break;
   2941         }
   2942       }
   2943       break;
   2944     }
   2945     default:
   2946       break;
   2947   }
   2948   for (v=0; v < (ssize_t) rows; v++)
   2949   {
   2950     ssize_t
   2951       y_offset;
   2952 
   2953     y_offset=y+v;
   2954     if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
   2955         (virtual_pixel_method == UndefinedVirtualPixelMethod))
   2956       y_offset=EdgeY(y_offset,cache_info->rows);
   2957     for (u=0; u < (ssize_t) columns; u+=length)
   2958     {
   2959       ssize_t
   2960         x_offset;
   2961 
   2962       x_offset=x+u;
   2963       length=(MagickSizeType) MagickMin(cache_info->columns-x_offset,columns-u);
   2964       if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
   2965           ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
   2966           (length == 0))
   2967         {
   2968           MagickModulo
   2969             x_modulo,
   2970             y_modulo;
   2971 
   2972           /*
   2973             Transfer a single pixel.
   2974           */
   2975           length=(MagickSizeType) 1;
   2976           switch (virtual_pixel_method)
   2977           {
   2978             case EdgeVirtualPixelMethod:
   2979             default:
   2980             {
   2981               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   2982                 EdgeX(x_offset,cache_info->columns),
   2983                 EdgeY(y_offset,cache_info->rows),1UL,1UL,*virtual_nexus,
   2984                 exception);
   2985               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   2986               break;
   2987             }
   2988             case RandomVirtualPixelMethod:
   2989             {
   2990               if (cache_info->random_info == (RandomInfo *) NULL)
   2991                 cache_info->random_info=AcquireRandomInfo();
   2992               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   2993                 RandomX(cache_info->random_info,cache_info->columns),
   2994                 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
   2995                 *virtual_nexus,exception);
   2996               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   2997               break;
   2998             }
   2999             case DitherVirtualPixelMethod:
   3000             {
   3001               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   3002                 DitherX(x_offset,cache_info->columns),
   3003                 DitherY(y_offset,cache_info->rows),1UL,1UL,*virtual_nexus,
   3004                 exception);
   3005               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3006               break;
   3007             }
   3008             case TileVirtualPixelMethod:
   3009             {
   3010               x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
   3011               y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
   3012               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   3013                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
   3014                 exception);
   3015               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3016               break;
   3017             }
   3018             case MirrorVirtualPixelMethod:
   3019             {
   3020               x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
   3021               if ((x_modulo.quotient & 0x01) == 1L)
   3022                 x_modulo.remainder=(ssize_t) cache_info->columns-
   3023                   x_modulo.remainder-1L;
   3024               y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
   3025               if ((y_modulo.quotient & 0x01) == 1L)
   3026                 y_modulo.remainder=(ssize_t) cache_info->rows-
   3027                   y_modulo.remainder-1L;
   3028               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   3029                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
   3030                 exception);
   3031               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3032               break;
   3033             }
   3034             case HorizontalTileEdgeVirtualPixelMethod:
   3035             {
   3036               x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
   3037               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   3038                 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
   3039                 *virtual_nexus,exception);
   3040               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3041               break;
   3042             }
   3043             case VerticalTileEdgeVirtualPixelMethod:
   3044             {
   3045               y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
   3046               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   3047                 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
   3048                 *virtual_nexus,exception);
   3049               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3050               break;
   3051             }
   3052             case BackgroundVirtualPixelMethod:
   3053             case BlackVirtualPixelMethod:
   3054             case GrayVirtualPixelMethod:
   3055             case TransparentVirtualPixelMethod:
   3056             case MaskVirtualPixelMethod:
   3057             case WhiteVirtualPixelMethod:
   3058             {
   3059               p=virtual_pixel;
   3060               r=virtual_metacontent;
   3061               break;
   3062             }
   3063             case CheckerTileVirtualPixelMethod:
   3064             {
   3065               x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
   3066               y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
   3067               if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
   3068                 {
   3069                   p=virtual_pixel;
   3070                   r=virtual_metacontent;
   3071                   break;
   3072                 }
   3073               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   3074                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
   3075                 exception);
   3076               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3077               break;
   3078             }
   3079             case HorizontalTileVirtualPixelMethod:
   3080             {
   3081               if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
   3082                 {
   3083                   p=virtual_pixel;
   3084                   r=virtual_metacontent;
   3085                   break;
   3086                 }
   3087               x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
   3088               y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
   3089               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   3090                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
   3091                 exception);
   3092               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3093               break;
   3094             }
   3095             case VerticalTileVirtualPixelMethod:
   3096             {
   3097               if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
   3098                 {
   3099                   p=virtual_pixel;
   3100                   r=virtual_metacontent;
   3101                   break;
   3102                 }
   3103               x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
   3104               y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
   3105               p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
   3106                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
   3107                 exception);
   3108               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3109               break;
   3110             }
   3111           }
   3112           if (p == (const Quantum *) NULL)
   3113             break;
   3114           (void) memcpy(q,p,(size_t) (cache_info->number_channels*length*
   3115             sizeof(*p)));
   3116           q+=cache_info->number_channels;
   3117           if ((s != (void *) NULL) && (r != (const void *) NULL))
   3118             {
   3119               (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
   3120               s+=cache_info->metacontent_extent;
   3121             }
   3122           continue;
   3123         }
   3124       /*
   3125         Transfer a run of pixels.
   3126       */
   3127       p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
   3128         (size_t) length,1UL,*virtual_nexus,exception);
   3129       if (p == (const Quantum *) NULL)
   3130         break;
   3131       r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
   3132       (void) memcpy(q,p,(size_t) (cache_info->number_channels*length*
   3133         sizeof(*p)));
   3134       q+=cache_info->number_channels*length;
   3135       if ((r != (void *) NULL) && (s != (const void *) NULL))
   3136         {
   3137           (void) memcpy(s,r,(size_t) length);
   3138           s+=length*cache_info->metacontent_extent;
   3139         }
   3140     }
   3141     if (u < (ssize_t) columns)
   3142       break;
   3143   }
   3144   /*
   3145     Free resources.
   3146   */
   3147   if (virtual_metacontent != (void *) NULL)
   3148     virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
   3149   virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
   3150   if (v < (ssize_t) rows)
   3151     return((const Quantum *) NULL);
   3152   return(pixels);
   3153 }
   3154 
   3155 /*
   3157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3158 %                                                                             %
   3159 %                                                                             %
   3160 %                                                                             %
   3161 +   G e t V i r t u a l P i x e l C a c h e                                   %
   3162 %                                                                             %
   3163 %                                                                             %
   3164 %                                                                             %
   3165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3166 %
   3167 %  GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
   3168 %  cache as defined by the geometry parameters.   A pointer to the pixels
   3169 %  is returned if the pixels are transferred, otherwise a NULL is returned.
   3170 %
   3171 %  The format of the GetVirtualPixelCache() method is:
   3172 %
   3173 %      const Quantum *GetVirtualPixelCache(const Image *image,
   3174 %        const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
   3175 %        const ssize_t y,const size_t columns,const size_t rows,
   3176 %        ExceptionInfo *exception)
   3177 %
   3178 %  A description of each parameter follows:
   3179 %
   3180 %    o image: the image.
   3181 %
   3182 %    o virtual_pixel_method: the virtual pixel method.
   3183 %
   3184 %    o x,y,columns,rows:  These values define the perimeter of a region of
   3185 %      pixels.
   3186 %
   3187 %    o exception: return any errors or warnings in this structure.
   3188 %
   3189 */
   3190 static const Quantum *GetVirtualPixelCache(const Image *image,
   3191   const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
   3192   const size_t columns,const size_t rows,ExceptionInfo *exception)
   3193 {
   3194   CacheInfo
   3195     *magick_restrict cache_info;
   3196 
   3197   const int
   3198     id = GetOpenMPThreadId();
   3199 
   3200   const Quantum
   3201     *magick_restrict p;
   3202 
   3203   assert(image != (const Image *) NULL);
   3204   assert(image->signature == MagickCoreSignature);
   3205   assert(image->cache != (Cache) NULL);
   3206   cache_info=(CacheInfo *) image->cache;
   3207   assert(cache_info->signature == MagickCoreSignature);
   3208   assert(id < (int) cache_info->number_threads);
   3209   p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
   3210     cache_info->nexus_info[id],exception);
   3211   return(p);
   3212 }
   3213 
   3214 /*
   3216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3217 %                                                                             %
   3218 %                                                                             %
   3219 %                                                                             %
   3220 %   G e t V i r t u a l P i x e l Q u e u e                                   %
   3221 %                                                                             %
   3222 %                                                                             %
   3223 %                                                                             %
   3224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3225 %
   3226 %  GetVirtualPixelQueue() returns the virtual pixels associated corresponding
   3227 %  with the last call to QueueAuthenticPixels() or GetVirtualPixels().
   3228 %
   3229 %  The format of the GetVirtualPixelQueue() method is:
   3230 %
   3231 %      const Quantum *GetVirtualPixelQueue(const Image image)
   3232 %
   3233 %  A description of each parameter follows:
   3234 %
   3235 %    o image: the image.
   3236 %
   3237 */
   3238 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
   3239 {
   3240   CacheInfo
   3241     *magick_restrict cache_info;
   3242 
   3243   const int
   3244     id = GetOpenMPThreadId();
   3245 
   3246   assert(image != (const Image *) NULL);
   3247   assert(image->signature == MagickCoreSignature);
   3248   assert(image->cache != (Cache) NULL);
   3249   cache_info=(CacheInfo *) image->cache;
   3250   assert(cache_info->signature == MagickCoreSignature);
   3251   if (cache_info->methods.get_virtual_pixels_handler !=
   3252        (GetVirtualPixelsHandler) NULL)
   3253     return(cache_info->methods.get_virtual_pixels_handler(image));
   3254   assert(id < (int) cache_info->number_threads);
   3255   return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
   3256 }
   3257 
   3258 /*
   3260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3261 %                                                                             %
   3262 %                                                                             %
   3263 %                                                                             %
   3264 %   G e t V i r t u a l P i x e l s                                           %
   3265 %                                                                             %
   3266 %                                                                             %
   3267 %                                                                             %
   3268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3269 %
   3270 %  GetVirtualPixels() returns an immutable pixel region. If the
   3271 %  region is successfully accessed, a pointer to it is returned, otherwise
   3272 %  NULL is returned.  The returned pointer may point to a temporary working
   3273 %  copy of the pixels or it may point to the original pixels in memory.
   3274 %  Performance is maximized if the selected region is part of one row, or one
   3275 %  or more full rows, since there is opportunity to access the pixels in-place
   3276 %  (without a copy) if the image is in memory, or in a memory-mapped file.  The
   3277 %  returned pointer must *never* be deallocated by the user.
   3278 %
   3279 %  Pixels accessed via the returned pointer represent a simple array of type
   3280 %  Quantum.  If the image type is CMYK or the storage class is PseudoClass,
   3281 %  call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
   3282 %  access the meta-content (of type void) corresponding to the the
   3283 %  region.
   3284 %
   3285 %  If you plan to modify the pixels, use GetAuthenticPixels() instead.
   3286 %
   3287 %  Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
   3288 %  safe.  In a threaded environment, use GetCacheViewVirtualPixels() or
   3289 %  GetCacheViewAuthenticPixels() instead.
   3290 %
   3291 %  The format of the GetVirtualPixels() method is:
   3292 %
   3293 %      const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
   3294 %        const ssize_t y,const size_t columns,const size_t rows,
   3295 %        ExceptionInfo *exception)
   3296 %
   3297 %  A description of each parameter follows:
   3298 %
   3299 %    o image: the image.
   3300 %
   3301 %    o x,y,columns,rows:  These values define the perimeter of a region of
   3302 %      pixels.
   3303 %
   3304 %    o exception: return any errors or warnings in this structure.
   3305 %
   3306 */
   3307 MagickExport const Quantum *GetVirtualPixels(const Image *image,
   3308   const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
   3309   ExceptionInfo *exception)
   3310 {
   3311   CacheInfo
   3312     *magick_restrict cache_info;
   3313 
   3314   const int
   3315     id = GetOpenMPThreadId();
   3316 
   3317   const Quantum
   3318     *magick_restrict p;
   3319 
   3320   assert(image != (const Image *) NULL);
   3321   assert(image->signature == MagickCoreSignature);
   3322   assert(image->cache != (Cache) NULL);
   3323   cache_info=(CacheInfo *) image->cache;
   3324   assert(cache_info->signature == MagickCoreSignature);
   3325   if (cache_info->methods.get_virtual_pixel_handler !=
   3326        (GetVirtualPixelHandler) NULL)
   3327     return(cache_info->methods.get_virtual_pixel_handler(image,
   3328       GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
   3329   assert(id < (int) cache_info->number_threads);
   3330   p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
   3331     columns,rows,cache_info->nexus_info[id],exception);
   3332   return(p);
   3333 }
   3334 
   3335 /*
   3337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3338 %                                                                             %
   3339 %                                                                             %
   3340 %                                                                             %
   3341 +   G e t V i r t u a l P i x e l s F r o m C a c h e                         %
   3342 %                                                                             %
   3343 %                                                                             %
   3344 %                                                                             %
   3345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3346 %
   3347 %  GetVirtualPixelsCache() returns the pixels associated corresponding with the
   3348 %  last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
   3349 %
   3350 %  The format of the GetVirtualPixelsCache() method is:
   3351 %
   3352 %      Quantum *GetVirtualPixelsCache(const Image *image)
   3353 %
   3354 %  A description of each parameter follows:
   3355 %
   3356 %    o image: the image.
   3357 %
   3358 */
   3359 static const Quantum *GetVirtualPixelsCache(const Image *image)
   3360 {
   3361   CacheInfo
   3362     *magick_restrict cache_info;
   3363 
   3364   const int
   3365     id = GetOpenMPThreadId();
   3366 
   3367   assert(image != (const Image *) NULL);
   3368   assert(image->signature == MagickCoreSignature);
   3369   assert(image->cache != (Cache) NULL);
   3370   cache_info=(CacheInfo *) image->cache;
   3371   assert(cache_info->signature == MagickCoreSignature);
   3372   assert(id < (int) cache_info->number_threads);
   3373   return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
   3374 }
   3375 
   3376 /*
   3378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3379 %                                                                             %
   3380 %                                                                             %
   3381 %                                                                             %
   3382 +   G e t V i r t u a l P i x e l s N e x u s                                 %
   3383 %                                                                             %
   3384 %                                                                             %
   3385 %                                                                             %
   3386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3387 %
   3388 %  GetVirtualPixelsNexus() returns the pixels associated with the specified
   3389 %  cache nexus.
   3390 %
   3391 %  The format of the GetVirtualPixelsNexus() method is:
   3392 %
   3393 %      const Quantum *GetVirtualPixelsNexus(const Cache cache,
   3394 %        NexusInfo *nexus_info)
   3395 %
   3396 %  A description of each parameter follows:
   3397 %
   3398 %    o cache: the pixel cache.
   3399 %
   3400 %    o nexus_info: the cache nexus to return the colormap pixels.
   3401 %
   3402 */
   3403 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
   3404   NexusInfo *magick_restrict nexus_info)
   3405 {
   3406   CacheInfo
   3407     *magick_restrict cache_info;
   3408 
   3409   assert(cache != (Cache) NULL);
   3410   cache_info=(CacheInfo *) cache;
   3411   assert(cache_info->signature == MagickCoreSignature);
   3412   if (cache_info->storage_class == UndefinedClass)
   3413     return((Quantum *) NULL);
   3414   return((const Quantum *) nexus_info->pixels);
   3415 }
   3416 
   3417 /*
   3419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3420 %                                                                             %
   3421 %                                                                             %
   3422 %                                                                             %
   3423 +   M a s k P i x e l C a c h e N e x u s                                     %
   3424 %                                                                             %
   3425 %                                                                             %
   3426 %                                                                             %
   3427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3428 %
   3429 %  MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
   3430 %  The method returns MagickTrue if the pixel region is masked, otherwise
   3431 %  MagickFalse.
   3432 %
   3433 %  The format of the MaskPixelCacheNexus() method is:
   3434 %
   3435 %      MagickBooleanType MaskPixelCacheNexus(Image *image,
   3436 %        NexusInfo *nexus_info,ExceptionInfo *exception)
   3437 %
   3438 %  A description of each parameter follows:
   3439 %
   3440 %    o image: the image.
   3441 %
   3442 %    o nexus_info: the cache nexus to clip.
   3443 %
   3444 %    o exception: return any errors or warnings in this structure.
   3445 %
   3446 */
   3447 
   3448 static inline Quantum ApplyPixelCompositeMask(const Quantum p,
   3449   const MagickRealType alpha,const Quantum q,const MagickRealType beta)
   3450 {
   3451   double
   3452     mask_alpha;
   3453 
   3454   if (fabs(alpha-OpaqueAlpha) < MagickEpsilon)
   3455     return(p);
   3456   mask_alpha=1.0-QuantumScale*QuantumScale*alpha*beta;
   3457   mask_alpha=PerceptibleReciprocal(mask_alpha);
   3458   return(ClampToQuantum(mask_alpha*MagickOver_((double) p,alpha,(double) q,beta)));
   3459 }
   3460 
   3461 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
   3462   ExceptionInfo *exception)
   3463 {
   3464   CacheInfo
   3465     *magick_restrict cache_info;
   3466 
   3467   MagickSizeType
   3468     number_pixels;
   3469 
   3470   NexusInfo
   3471     **magick_restrict image_nexus;
   3472 
   3473   register Quantum
   3474     *magick_restrict p,
   3475     *magick_restrict q;
   3476 
   3477   register ssize_t
   3478     n;
   3479 
   3480   /*
   3481     Apply clip mask.
   3482   */
   3483   if (image->debug != MagickFalse)
   3484     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   3485   if ((image->channels & CompositeMaskChannel) == 0)
   3486     return(MagickTrue);
   3487   cache_info=(CacheInfo *) image->cache;
   3488   if (cache_info == (Cache) NULL)
   3489     return(MagickFalse);
   3490   image_nexus=AcquirePixelCacheNexus(1);
   3491   p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
   3492     nexus_info->region.width,nexus_info->region.height,image_nexus[0],
   3493     exception);
   3494   q=nexus_info->pixels;
   3495   number_pixels=(MagickSizeType) nexus_info->region.width*
   3496     nexus_info->region.height;
   3497   for (n=0; n < (ssize_t) number_pixels; n++)
   3498   {
   3499     double
   3500       mask_alpha;
   3501 
   3502     register ssize_t
   3503       i;
   3504 
   3505     if (p == (Quantum *) NULL)
   3506       break;
   3507     mask_alpha=(double) GetPixelCompositeMask(image,p);
   3508     for (i=0; i < (ssize_t) image->number_channels; i++)
   3509     {
   3510       PixelChannel channel = GetPixelChannelChannel(image,i);
   3511       PixelTrait traits = GetPixelChannelTraits(image,channel);
   3512       if ((traits & UpdatePixelTrait) == 0)
   3513         continue;
   3514       q[i]=ApplyPixelCompositeMask(p[i],mask_alpha,q[i],
   3515         (MagickRealType) GetPixelAlpha(image,q));
   3516     }
   3517     p+=GetPixelChannels(image);
   3518     q+=GetPixelChannels(image);
   3519   }
   3520   image_nexus=DestroyPixelCacheNexus(image_nexus,1);
   3521   if (n < (ssize_t) number_pixels)
   3522     return(MagickFalse);
   3523   return(MagickTrue);
   3524 }
   3525 
   3526 /*
   3528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3529 %                                                                             %
   3530 %                                                                             %
   3531 %                                                                             %
   3532 +   O p e n P i x e l C a c h e                                               %
   3533 %                                                                             %
   3534 %                                                                             %
   3535 %                                                                             %
   3536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3537 %
   3538 %  OpenPixelCache() allocates the pixel cache.  This includes defining the cache
   3539 %  dimensions, allocating space for the image pixels and optionally the
   3540 %  metacontent, and memory mapping the cache if it is disk based.  The cache
   3541 %  nexus array is initialized as well.
   3542 %
   3543 %  The format of the OpenPixelCache() method is:
   3544 %
   3545 %      MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
   3546 %        ExceptionInfo *exception)
   3547 %
   3548 %  A description of each parameter follows:
   3549 %
   3550 %    o image: the image.
   3551 %
   3552 %    o mode: ReadMode, WriteMode, or IOMode.
   3553 %
   3554 %    o exception: return any errors or warnings in this structure.
   3555 %
   3556 */
   3557 
   3558 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
   3559   const MapMode mode)
   3560 {
   3561   int
   3562     file;
   3563 
   3564   /*
   3565     Open pixel cache on disk.
   3566   */
   3567   if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
   3568     return(MagickTrue);  /* cache already open and in the proper mode */
   3569   if (*cache_info->cache_filename == '\0')
   3570     file=AcquireUniqueFileResource(cache_info->cache_filename);
   3571   else
   3572     switch (mode)
   3573     {
   3574       case ReadMode:
   3575       {
   3576         file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
   3577         break;
   3578       }
   3579       case WriteMode:
   3580       {
   3581         file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
   3582           O_BINARY | O_EXCL,S_MODE);
   3583         if (file == -1)
   3584           file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
   3585         break;
   3586       }
   3587       case IOMode:
   3588       default:
   3589       {
   3590         file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
   3591           O_EXCL,S_MODE);
   3592         if (file == -1)
   3593           file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
   3594         break;
   3595       }
   3596     }
   3597   if (file == -1)
   3598     return(MagickFalse);
   3599   (void) AcquireMagickResource(FileResource,1);
   3600   if (cache_info->file != -1)
   3601     (void) ClosePixelCacheOnDisk(cache_info);
   3602   cache_info->file=file;
   3603   cache_info->disk_mode=mode;
   3604   return(MagickTrue);
   3605 }
   3606 
   3607 static inline MagickOffsetType WritePixelCacheRegion(
   3608   const CacheInfo *magick_restrict cache_info,const MagickOffsetType offset,
   3609   const MagickSizeType length,const unsigned char *magick_restrict buffer)
   3610 {
   3611   register MagickOffsetType
   3612     i;
   3613 
   3614   ssize_t
   3615     count;
   3616 
   3617 #if !defined(MAGICKCORE_HAVE_PWRITE)
   3618   if (lseek(cache_info->file,offset,SEEK_SET) < 0)
   3619     return((MagickOffsetType) -1);
   3620 #endif
   3621   count=0;
   3622   for (i=0; i < (MagickOffsetType) length; i+=count)
   3623   {
   3624 #if !defined(MAGICKCORE_HAVE_PWRITE)
   3625     count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
   3626       SSIZE_MAX));
   3627 #else
   3628     count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
   3629       SSIZE_MAX),offset+i);
   3630 #endif
   3631     if (count <= 0)
   3632       {
   3633         count=0;
   3634         if (errno != EINTR)
   3635           break;
   3636       }
   3637   }
   3638   return(i);
   3639 }
   3640 
   3641 static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
   3642 {
   3643   CacheInfo
   3644     *magick_restrict cache_info;
   3645 
   3646   MagickOffsetType
   3647     count,
   3648     extent,
   3649     offset;
   3650 
   3651   cache_info=(CacheInfo *) image->cache;
   3652   if (image->debug != MagickFalse)
   3653     {
   3654       char
   3655         format[MagickPathExtent],
   3656         message[MagickPathExtent];
   3657 
   3658       (void) FormatMagickSize(length,MagickFalse,"B",MagickPathExtent,format);
   3659       (void) FormatLocaleString(message,MagickPathExtent,
   3660         "extend %s (%s[%d], disk, %s)",cache_info->filename,
   3661         cache_info->cache_filename,cache_info->file,format);
   3662       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
   3663     }
   3664   if (length != (MagickSizeType) ((MagickOffsetType) length))
   3665     return(MagickFalse);
   3666   offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
   3667   if (offset < 0)
   3668     return(MagickFalse);
   3669   if ((MagickSizeType) offset >= length)
   3670     count=(MagickOffsetType) 1;
   3671   else
   3672     {
   3673       extent=(MagickOffsetType) length-1;
   3674       count=WritePixelCacheRegion(cache_info,extent,1,(const unsigned char *)
   3675         "");
   3676       if (count != 1)
   3677         return(MagickFalse);
   3678 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
   3679       if (cache_info->synchronize != MagickFalse)
   3680         if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
   3681           return(MagickFalse);
   3682 #endif
   3683     }
   3684   offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
   3685   if (offset < 0)
   3686     return(MagickFalse);
   3687   return(MagickTrue);
   3688 }
   3689 
   3690 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
   3691   ExceptionInfo *exception)
   3692 {
   3693   CacheInfo
   3694     *magick_restrict cache_info,
   3695     source_info;
   3696 
   3697   char
   3698     format[MagickPathExtent],
   3699     message[MagickPathExtent];
   3700 
   3701   const char
   3702     *hosts,
   3703     *type;
   3704 
   3705   MagickBooleanType
   3706     status;
   3707 
   3708   MagickSizeType
   3709     length,
   3710     number_pixels;
   3711 
   3712   size_t
   3713     columns,
   3714     packet_size;
   3715 
   3716   assert(image != (const Image *) NULL);
   3717   assert(image->signature == MagickCoreSignature);
   3718   assert(image->cache != (Cache) NULL);
   3719   if (image->debug != MagickFalse)
   3720     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   3721   if (cache_anonymous_memory < 0)
   3722     {
   3723       char
   3724         *value;
   3725 
   3726       /*
   3727         Does the security policy require anonymous mapping for pixel cache?
   3728       */
   3729       cache_anonymous_memory=0;
   3730       value=GetPolicyValue("pixel-cache-memory");
   3731       if (value == (char *) NULL)
   3732         value=GetPolicyValue("cache:memory-map");
   3733       if (LocaleCompare(value,"anonymous") == 0)
   3734         {
   3735 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
   3736           cache_anonymous_memory=1;
   3737 #else
   3738           (void) ThrowMagickException(exception,GetMagickModule(),
   3739             MissingDelegateError,"DelegateLibrarySupportNotBuiltIn",
   3740             "'%s' (policy requires anonymous memory mapping)",image->filename);
   3741 #endif
   3742         }
   3743       value=DestroyString(value);
   3744     }
   3745   if ((image->columns == 0) || (image->rows == 0))
   3746     ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
   3747   cache_info=(CacheInfo *) image->cache;
   3748   assert(cache_info->signature == MagickCoreSignature);
   3749   if ((AcquireMagickResource(WidthResource,image->columns) == MagickFalse) ||
   3750       (AcquireMagickResource(HeightResource,image->rows) == MagickFalse))
   3751     ThrowBinaryException(ImageError,"WidthOrHeightExceedsLimit",
   3752       image->filename);
   3753   length=GetImageListLength(image);
   3754   if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
   3755     ThrowBinaryException(ResourceLimitError,"ListLengthExceedsLimit",
   3756       image->filename);
   3757   source_info=(*cache_info);
   3758   source_info.file=(-1);
   3759   (void) FormatLocaleString(cache_info->filename,MagickPathExtent,"%s[%.20g]",
   3760     image->filename,(double) image->scene);
   3761   cache_info->storage_class=image->storage_class;
   3762   cache_info->colorspace=image->colorspace;
   3763   cache_info->alpha_trait=image->alpha_trait;
   3764   cache_info->channels=image->channels;
   3765   cache_info->rows=image->rows;
   3766   cache_info->columns=image->columns;
   3767   InitializePixelChannelMap(image);
   3768   cache_info->number_channels=GetPixelChannels(image);
   3769   (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
   3770     sizeof(*image->channel_map));
   3771   cache_info->metacontent_extent=image->metacontent_extent;
   3772   cache_info->mode=mode;
   3773   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
   3774   packet_size=cache_info->number_channels*sizeof(Quantum);
   3775   if (image->metacontent_extent != 0)
   3776     packet_size+=cache_info->metacontent_extent;
   3777   length=number_pixels*packet_size;
   3778   columns=(size_t) (length/cache_info->rows/packet_size);
   3779   if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
   3780       ((ssize_t) cache_info->rows < 0))
   3781     ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
   3782       image->filename);
   3783   cache_info->length=length;
   3784   if (image->ping != MagickFalse)
   3785     {
   3786       cache_info->storage_class=image->storage_class;
   3787       cache_info->colorspace=image->colorspace;
   3788       cache_info->type=PingCache;
   3789       return(MagickTrue);
   3790     }
   3791   status=AcquireMagickResource(AreaResource,(MagickSizeType)
   3792     cache_info->columns*cache_info->rows);
   3793   if (cache_info->mode == PersistMode)
   3794     status=MagickFalse;
   3795   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
   3796     cache_info->metacontent_extent);
   3797   if ((status != MagickFalse) &&
   3798       (length == (MagickSizeType) ((size_t) length)) &&
   3799       ((cache_info->type == UndefinedCache) || (cache_info->type == MemoryCache)))
   3800     {
   3801       status=AcquireMagickResource(MemoryResource,cache_info->length);
   3802       if (status != MagickFalse)
   3803         {
   3804           status=MagickTrue;
   3805           if (cache_anonymous_memory <= 0)
   3806             {
   3807               cache_info->mapped=MagickFalse;
   3808               cache_info->pixels=(Quantum *) MagickAssumeAligned(
   3809                 AcquireAlignedMemory(1,(size_t) cache_info->length));
   3810             }
   3811           else
   3812             {
   3813               cache_info->mapped=MagickTrue;
   3814               cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
   3815                 cache_info->length);
   3816             }
   3817           if (cache_info->pixels == (Quantum *) NULL)
   3818             {
   3819               cache_info->mapped=source_info.mapped;
   3820               cache_info->pixels=source_info.pixels;
   3821             }
   3822           else
   3823             {
   3824               /*
   3825                 Create memory pixel cache.
   3826               */
   3827               cache_info->type=MemoryCache;
   3828               cache_info->metacontent=(void *) NULL;
   3829               if (cache_info->metacontent_extent != 0)
   3830                 cache_info->metacontent=(void *) (cache_info->pixels+
   3831                   cache_info->number_channels*number_pixels);
   3832               if ((source_info.storage_class != UndefinedClass) &&
   3833                   (mode != ReadMode))
   3834                 {
   3835                   status=ClonePixelCacheRepository(cache_info,&source_info,
   3836                     exception);
   3837                   RelinquishPixelCachePixels(&source_info);
   3838                 }
   3839               if (image->debug != MagickFalse)
   3840                 {
   3841                   (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
   3842                     MagickPathExtent,format);
   3843                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
   3844                     cache_info->type);
   3845                   (void) FormatLocaleString(message,MagickPathExtent,
   3846                     "open %s (%s %s, %.20gx%.20gx%.20g %s)",
   3847                     cache_info->filename,cache_info->mapped != MagickFalse ?
   3848                     "Anonymous" : "Heap",type,(double) cache_info->columns,
   3849                     (double) cache_info->rows,(double)
   3850                     cache_info->number_channels,format);
   3851                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
   3852                     message);
   3853                 }
   3854               return(status == 0 ? MagickFalse : MagickTrue);
   3855             }
   3856         }
   3857     }
   3858   status=AcquireMagickResource(DiskResource,cache_info->length);
   3859   hosts=(const char *) GetImageRegistry(StringRegistryType,"cache:hosts",
   3860     exception);
   3861   if ((status == MagickFalse) && (hosts != (const char *) NULL))
   3862     {
   3863       DistributeCacheInfo
   3864         *server_info;
   3865 
   3866       /*
   3867         Distribute the pixel cache to a remote server.
   3868       */
   3869       server_info=AcquireDistributeCacheInfo(exception);
   3870       if (server_info != (DistributeCacheInfo *) NULL)
   3871         {
   3872           status=OpenDistributePixelCache(server_info,image);
   3873           if (status == MagickFalse)
   3874             {
   3875               ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
   3876                 GetDistributeCacheHostname(server_info));
   3877               server_info=DestroyDistributeCacheInfo(server_info);
   3878             }
   3879           else
   3880             {
   3881               /*
   3882                 Create a distributed pixel cache.
   3883               */
   3884               status=MagickTrue;
   3885               cache_info->type=DistributedCache;
   3886               cache_info->server_info=server_info;
   3887               (void) FormatLocaleString(cache_info->cache_filename,
   3888                 MagickPathExtent,"%s:%d",GetDistributeCacheHostname(
   3889                 (DistributeCacheInfo *) cache_info->server_info),
   3890                 GetDistributeCachePort((DistributeCacheInfo *)
   3891                 cache_info->server_info));
   3892               if ((source_info.storage_class != UndefinedClass) &&
   3893                   (mode != ReadMode))
   3894                 {
   3895                   status=ClonePixelCacheRepository(cache_info,&source_info,
   3896                     exception);
   3897                   RelinquishPixelCachePixels(&source_info);
   3898                 }
   3899               if (image->debug != MagickFalse)
   3900                 {
   3901                   (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
   3902                     MagickPathExtent,format);
   3903                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
   3904                     cache_info->type);
   3905                   (void) FormatLocaleString(message,MagickPathExtent,
   3906                     "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
   3907                     cache_info->filename,cache_info->cache_filename,
   3908                     GetDistributeCacheFile((DistributeCacheInfo *)
   3909                     cache_info->server_info),type,(double) cache_info->columns,
   3910                     (double) cache_info->rows,(double)
   3911                     cache_info->number_channels,format);
   3912                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
   3913                     message);
   3914                 }
   3915               return(status == 0 ? MagickFalse : MagickTrue);
   3916             }
   3917         }
   3918       cache_info->type=UndefinedCache;
   3919       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
   3920         "CacheResourcesExhausted","`%s'",image->filename);
   3921       return(MagickFalse);
   3922     }
   3923   /*
   3924     Create pixel cache on disk.
   3925   */
   3926   if (status == MagickFalse)
   3927     {
   3928       cache_info->type=UndefinedCache;
   3929       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
   3930         "CacheResourcesExhausted","`%s'",image->filename);
   3931       return(MagickFalse);
   3932     }
   3933   if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
   3934       (cache_info->mode != PersistMode))
   3935     {
   3936       (void) ClosePixelCacheOnDisk(cache_info);
   3937       *cache_info->cache_filename='\0';
   3938     }
   3939   if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
   3940     {
   3941       ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
   3942         image->filename);
   3943       return(MagickFalse);
   3944     }
   3945   status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
   3946     cache_info->length);
   3947   if (status == MagickFalse)
   3948     {
   3949       ThrowFileException(exception,CacheError,"UnableToExtendCache",
   3950         image->filename);
   3951       return(MagickFalse);
   3952     }
   3953   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
   3954     cache_info->metacontent_extent);
   3955   if (length != (MagickSizeType) ((size_t) length))
   3956     cache_info->type=DiskCache;
   3957   else
   3958     {
   3959       status=AcquireMagickResource(MapResource,cache_info->length);
   3960       if (status == MagickFalse)
   3961         cache_info->type=DiskCache;
   3962       else
   3963         if ((cache_info->type != MapCache) && (cache_info->type != MemoryCache))
   3964           {
   3965             cache_info->type=DiskCache;
   3966             RelinquishMagickResource(MapResource,cache_info->length);
   3967           }
   3968         else
   3969           {
   3970             cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
   3971               cache_info->offset,(size_t) cache_info->length);
   3972             if (cache_info->pixels == (Quantum *) NULL)
   3973               {
   3974                 cache_info->type=DiskCache;
   3975                 cache_info->mapped=source_info.mapped;
   3976                 cache_info->pixels=source_info.pixels;
   3977                 RelinquishMagickResource(MapResource,cache_info->length);
   3978               }
   3979             else
   3980               {
   3981                 /*
   3982                   Create file-backed memory-mapped pixel cache.
   3983                 */
   3984                 (void) ClosePixelCacheOnDisk(cache_info);
   3985                 cache_info->type=MapCache;
   3986                 cache_info->mapped=MagickTrue;
   3987                 cache_info->metacontent=(void *) NULL;
   3988                 if (cache_info->metacontent_extent != 0)
   3989                   cache_info->metacontent=(void *) (cache_info->pixels+
   3990                     cache_info->number_channels*number_pixels);
   3991                 if ((source_info.storage_class != UndefinedClass) &&
   3992                     (mode != ReadMode))
   3993                   {
   3994                     status=ClonePixelCacheRepository(cache_info,&source_info,
   3995                       exception);
   3996                     RelinquishPixelCachePixels(&source_info);
   3997                   }
   3998                 if (image->debug != MagickFalse)
   3999                   {
   4000                     (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
   4001                       MagickPathExtent,format);
   4002                     type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
   4003                       cache_info->type);
   4004                     (void) FormatLocaleString(message,MagickPathExtent,
   4005                       "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
   4006                       cache_info->filename,cache_info->cache_filename,
   4007                       cache_info->file,type,(double) cache_info->columns,
   4008                       (double) cache_info->rows,(double)
   4009                       cache_info->number_channels,format);
   4010                     (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
   4011                       message);
   4012                   }
   4013                 return(status == 0 ? MagickFalse : MagickTrue);
   4014               }
   4015         }
   4016     }
   4017   status=MagickTrue;
   4018   if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
   4019     {
   4020       status=ClonePixelCacheRepository(cache_info,&source_info,exception);
   4021       RelinquishPixelCachePixels(&source_info);
   4022     }
   4023   if (image->debug != MagickFalse)
   4024     {
   4025       (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
   4026         MagickPathExtent,format);
   4027       type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
   4028         cache_info->type);
   4029       (void) FormatLocaleString(message,MagickPathExtent,
   4030         "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
   4031         cache_info->cache_filename,cache_info->file,type,(double)
   4032         cache_info->columns,(double) cache_info->rows,(double)
   4033         cache_info->number_channels,format);
   4034       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
   4035     }
   4036   return(status == 0 ? MagickFalse : MagickTrue);
   4037 }
   4038 
   4039 /*
   4041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4042 %                                                                             %
   4043 %                                                                             %
   4044 %                                                                             %
   4045 +   P e r s i s t P i x e l C a c h e                                         %
   4046 %                                                                             %
   4047 %                                                                             %
   4048 %                                                                             %
   4049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4050 %
   4051 %  PersistPixelCache() attaches to or initializes a persistent pixel cache.  A
   4052 %  persistent pixel cache is one that resides on disk and is not destroyed
   4053 %  when the program exits.
   4054 %
   4055 %  The format of the PersistPixelCache() method is:
   4056 %
   4057 %      MagickBooleanType PersistPixelCache(Image *image,const char *filename,
   4058 %        const MagickBooleanType attach,MagickOffsetType *offset,
   4059 %        ExceptionInfo *exception)
   4060 %
   4061 %  A description of each parameter follows:
   4062 %
   4063 %    o image: the image.
   4064 %
   4065 %    o filename: the persistent pixel cache filename.
   4066 %
   4067 %    o attach: A value other than zero initializes the persistent pixel cache.
   4068 %
   4069 %    o initialize: A value other than zero initializes the persistent pixel
   4070 %      cache.
   4071 %
   4072 %    o offset: the offset in the persistent cache to store pixels.
   4073 %
   4074 %    o exception: return any errors or warnings in this structure.
   4075 %
   4076 */
   4077 MagickExport MagickBooleanType PersistPixelCache(Image *image,
   4078   const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
   4079   ExceptionInfo *exception)
   4080 {
   4081   CacheInfo
   4082     *magick_restrict cache_info,
   4083     *magick_restrict clone_info;
   4084 
   4085   MagickBooleanType
   4086     status;
   4087 
   4088   ssize_t
   4089     page_size;
   4090 
   4091   assert(image != (Image *) NULL);
   4092   assert(image->signature == MagickCoreSignature);
   4093   if (image->debug != MagickFalse)
   4094     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   4095   assert(image->cache != (void *) NULL);
   4096   assert(filename != (const char *) NULL);
   4097   assert(offset != (MagickOffsetType *) NULL);
   4098   page_size=GetMagickPageSize();
   4099   cache_info=(CacheInfo *) image->cache;
   4100   assert(cache_info->signature == MagickCoreSignature);
   4101 #if defined(MAGICKCORE_OPENCL_SUPPORT)
   4102   CopyOpenCLBuffer(cache_info);
   4103 #endif
   4104   if (attach != MagickFalse)
   4105     {
   4106       /*
   4107         Attach existing persistent pixel cache.
   4108       */
   4109       if (image->debug != MagickFalse)
   4110         (void) LogMagickEvent(CacheEvent,GetMagickModule(),
   4111           "attach persistent cache");
   4112       (void) CopyMagickString(cache_info->cache_filename,filename,
   4113         MagickPathExtent);
   4114       cache_info->type=DiskCache;
   4115       cache_info->offset=(*offset);
   4116       if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
   4117         return(MagickFalse);
   4118       *offset+=cache_info->length+page_size-(cache_info->length % page_size);
   4119       return(SyncImagePixelCache(image,exception));
   4120     }
   4121   /*
   4122     Clone persistent pixel cache.
   4123   */
   4124   status=AcquireMagickResource(DiskResource,cache_info->length);
   4125   if (status == MagickFalse)
   4126     {
   4127       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
   4128         "CacheResourcesExhausted","`%s'",image->filename);
   4129       return(MagickFalse);
   4130     }
   4131   clone_info=(CacheInfo *) ClonePixelCache(cache_info);
   4132   clone_info->type=DiskCache;
   4133   (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
   4134   clone_info->file=(-1);
   4135   clone_info->storage_class=cache_info->storage_class;
   4136   clone_info->colorspace=cache_info->colorspace;
   4137   clone_info->alpha_trait=cache_info->alpha_trait;
   4138   clone_info->channels=cache_info->channels;
   4139   clone_info->columns=cache_info->columns;
   4140   clone_info->rows=cache_info->rows;
   4141   clone_info->number_channels=cache_info->number_channels;
   4142   clone_info->metacontent_extent=cache_info->metacontent_extent;
   4143   clone_info->mode=PersistMode;
   4144   clone_info->length=cache_info->length;
   4145   (void) memcpy(clone_info->channel_map,cache_info->channel_map,
   4146     MaxPixelChannels*sizeof(*cache_info->channel_map));
   4147   clone_info->offset=(*offset);
   4148   status=ClonePixelCacheRepository(clone_info,cache_info,exception);
   4149   *offset+=cache_info->length+page_size-(cache_info->length % page_size);
   4150   clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
   4151   return(status);
   4152 }
   4153 
   4154 /*
   4156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4157 %                                                                             %
   4158 %                                                                             %
   4159 %                                                                             %
   4160 +   Q u e u e A u t h e n t i c P i x e l C a c h e N e x u s                 %
   4161 %                                                                             %
   4162 %                                                                             %
   4163 %                                                                             %
   4164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4165 %
   4166 %  QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
   4167 %  defined by the region rectangle and returns a pointer to the region.  This
   4168 %  region is subsequently transferred from the pixel cache with
   4169 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
   4170 %  pixels are transferred, otherwise a NULL is returned.
   4171 %
   4172 %  The format of the QueueAuthenticPixelCacheNexus() method is:
   4173 %
   4174 %      Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
   4175 %        const ssize_t y,const size_t columns,const size_t rows,
   4176 %        const MagickBooleanType clone,NexusInfo *nexus_info,
   4177 %        ExceptionInfo *exception)
   4178 %
   4179 %  A description of each parameter follows:
   4180 %
   4181 %    o image: the image.
   4182 %
   4183 %    o x,y,columns,rows:  These values define the perimeter of a region of
   4184 %      pixels.
   4185 %
   4186 %    o nexus_info: the cache nexus to set.
   4187 %
   4188 %    o clone: clone the pixel cache.
   4189 %
   4190 %    o exception: return any errors or warnings in this structure.
   4191 %
   4192 */
   4193 MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
   4194   const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
   4195   const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
   4196 {
   4197   CacheInfo
   4198     *magick_restrict cache_info;
   4199 
   4200   MagickOffsetType
   4201     offset;
   4202 
   4203   MagickSizeType
   4204     number_pixels;
   4205 
   4206   Quantum
   4207     *magick_restrict pixels;
   4208 
   4209   RectangleInfo
   4210     region;
   4211 
   4212   /*
   4213     Validate pixel cache geometry.
   4214   */
   4215   assert(image != (const Image *) NULL);
   4216   assert(image->signature == MagickCoreSignature);
   4217   assert(image->cache != (Cache) NULL);
   4218   cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
   4219   if (cache_info == (Cache) NULL)
   4220     return((Quantum *) NULL);
   4221   assert(cache_info->signature == MagickCoreSignature);
   4222   if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
   4223       (y < 0) || (x >= (ssize_t) cache_info->columns) ||
   4224       (y >= (ssize_t) cache_info->rows))
   4225     {
   4226       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
   4227         "PixelsAreNotAuthentic","`%s'",image->filename);
   4228       return((Quantum *) NULL);
   4229     }
   4230   offset=(MagickOffsetType) y*cache_info->columns+x;
   4231   if (offset < 0)
   4232     return((Quantum *) NULL);
   4233   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
   4234   offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
   4235   if ((MagickSizeType) offset >= number_pixels)
   4236     return((Quantum *) NULL);
   4237   /*
   4238     Return pixel cache.
   4239   */
   4240   region.x=x;
   4241   region.y=y;
   4242   region.width=columns;
   4243   region.height=rows;
   4244   pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,&region,
   4245     ((image->channels & WriteMaskChannel) != 0) ||
   4246     ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
   4247     nexus_info,exception);
   4248   return(pixels);
   4249 }
   4250 
   4251 /*
   4253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4254 %                                                                             %
   4255 %                                                                             %
   4256 %                                                                             %
   4257 +   Q u e u e A u t h e n t i c P i x e l s C a c h e                         %
   4258 %                                                                             %
   4259 %                                                                             %
   4260 %                                                                             %
   4261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4262 %
   4263 %  QueueAuthenticPixelsCache() allocates an region to store image pixels as
   4264 %  defined by the region rectangle and returns a pointer to the region.  This
   4265 %  region is subsequently transferred from the pixel cache with
   4266 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
   4267 %  pixels are transferred, otherwise a NULL is returned.
   4268 %
   4269 %  The format of the QueueAuthenticPixelsCache() method is:
   4270 %
   4271 %      Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
   4272 %        const ssize_t y,const size_t columns,const size_t rows,
   4273 %        ExceptionInfo *exception)
   4274 %
   4275 %  A description of each parameter follows:
   4276 %
   4277 %    o image: the image.
   4278 %
   4279 %    o x,y,columns,rows:  These values define the perimeter of a region of
   4280 %      pixels.
   4281 %
   4282 %    o exception: return any errors or warnings in this structure.
   4283 %
   4284 */
   4285 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
   4286   const ssize_t y,const size_t columns,const size_t rows,
   4287   ExceptionInfo *exception)
   4288 {
   4289   CacheInfo
   4290     *magick_restrict cache_info;
   4291 
   4292   const int
   4293     id = GetOpenMPThreadId();
   4294 
   4295   Quantum
   4296     *magick_restrict pixels;
   4297 
   4298   assert(image != (const Image *) NULL);
   4299   assert(image->signature == MagickCoreSignature);
   4300   assert(image->cache != (Cache) NULL);
   4301   cache_info=(CacheInfo *) image->cache;
   4302   assert(cache_info->signature == MagickCoreSignature);
   4303   assert(id < (int) cache_info->number_threads);
   4304   pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
   4305     cache_info->nexus_info[id],exception);
   4306   return(pixels);
   4307 }
   4308 
   4309 /*
   4311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4312 %                                                                             %
   4313 %                                                                             %
   4314 %                                                                             %
   4315 %   Q u e u e A u t h e n t i c P i x e l s                                   %
   4316 %                                                                             %
   4317 %                                                                             %
   4318 %                                                                             %
   4319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4320 %
   4321 %  QueueAuthenticPixels() queues a mutable pixel region.  If the region is
   4322 %  successfully initialized a pointer to a Quantum array representing the
   4323 %  region is returned, otherwise NULL is returned.  The returned pointer may
   4324 %  point to a temporary working buffer for the pixels or it may point to the
   4325 %  final location of the pixels in memory.
   4326 %
   4327 %  Write-only access means that any existing pixel values corresponding to
   4328 %  the region are ignored.  This is useful if the initial image is being
   4329 %  created from scratch, or if the existing pixel values are to be
   4330 %  completely replaced without need to refer to their pre-existing values.
   4331 %  The application is free to read and write the pixel buffer returned by
   4332 %  QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
   4333 %  initialize the pixel array values. Initializing pixel array values is the
   4334 %  application's responsibility.
   4335 %
   4336 %  Performance is maximized if the selected region is part of one row, or
   4337 %  one or more full rows, since then there is opportunity to access the
   4338 %  pixels in-place (without a copy) if the image is in memory, or in a
   4339 %  memory-mapped file. The returned pointer must *never* be deallocated
   4340 %  by the user.
   4341 %
   4342 %  Pixels accessed via the returned pointer represent a simple array of type
   4343 %  Quantum. If the image type is CMYK or the storage class is PseudoClass,
   4344 %  call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
   4345 %  obtain the meta-content (of type void) corresponding to the region.
   4346 %  Once the Quantum (and/or Quantum) array has been updated, the
   4347 %  changes must be saved back to the underlying image using
   4348 %  SyncAuthenticPixels() or they may be lost.
   4349 %
   4350 %  The format of the QueueAuthenticPixels() method is:
   4351 %
   4352 %      Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
   4353 %        const ssize_t y,const size_t columns,const size_t rows,
   4354 %        ExceptionInfo *exception)
   4355 %
   4356 %  A description of each parameter follows:
   4357 %
   4358 %    o image: the image.
   4359 %
   4360 %    o x,y,columns,rows:  These values define the perimeter of a region of
   4361 %      pixels.
   4362 %
   4363 %    o exception: return any errors or warnings in this structure.
   4364 %
   4365 */
   4366 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
   4367   const ssize_t y,const size_t columns,const size_t rows,
   4368   ExceptionInfo *exception)
   4369 {
   4370   CacheInfo
   4371     *magick_restrict cache_info;
   4372 
   4373   const int
   4374     id = GetOpenMPThreadId();
   4375 
   4376   Quantum
   4377     *magick_restrict pixels;
   4378 
   4379   assert(image != (Image *) NULL);
   4380   assert(image->signature == MagickCoreSignature);
   4381   assert(image->cache != (Cache) NULL);
   4382   cache_info=(CacheInfo *) image->cache;
   4383   assert(cache_info->signature == MagickCoreSignature);
   4384   if (cache_info->methods.queue_authentic_pixels_handler !=
   4385       (QueueAuthenticPixelsHandler) NULL)
   4386     {
   4387       pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
   4388         columns,rows,exception);
   4389       return(pixels);
   4390     }
   4391   assert(id < (int) cache_info->number_threads);
   4392   pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
   4393     cache_info->nexus_info[id],exception);
   4394   return(pixels);
   4395 }
   4396 
   4397 /*
   4399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4400 %                                                                             %
   4401 %                                                                             %
   4402 %                                                                             %
   4403 +   R e a d P i x e l C a c h e M e t a c o n t e n t                         %
   4404 %                                                                             %
   4405 %                                                                             %
   4406 %                                                                             %
   4407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4408 %
   4409 %  ReadPixelCacheMetacontent() reads metacontent from the specified region of
   4410 %  the pixel cache.
   4411 %
   4412 %  The format of the ReadPixelCacheMetacontent() method is:
   4413 %
   4414 %      MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
   4415 %        NexusInfo *nexus_info,ExceptionInfo *exception)
   4416 %
   4417 %  A description of each parameter follows:
   4418 %
   4419 %    o cache_info: the pixel cache.
   4420 %
   4421 %    o nexus_info: the cache nexus to read the metacontent.
   4422 %
   4423 %    o exception: return any errors or warnings in this structure.
   4424 %
   4425 */
   4426 
   4427 static inline MagickOffsetType ReadPixelCacheRegion(
   4428   const CacheInfo *magick_restrict cache_info,const MagickOffsetType offset,
   4429   const MagickSizeType length,unsigned char *magick_restrict buffer)
   4430 {
   4431   register MagickOffsetType
   4432     i;
   4433 
   4434   ssize_t
   4435     count;
   4436 
   4437 #if !defined(MAGICKCORE_HAVE_PREAD)
   4438   if (lseek(cache_info->file,offset,SEEK_SET) < 0)
   4439     return((MagickOffsetType) -1);
   4440 #endif
   4441   count=0;
   4442   for (i=0; i < (MagickOffsetType) length; i+=count)
   4443   {
   4444 #if !defined(MAGICKCORE_HAVE_PREAD)
   4445     count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
   4446       SSIZE_MAX));
   4447 #else
   4448     count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
   4449       SSIZE_MAX),offset+i);
   4450 #endif
   4451     if (count <= 0)
   4452       {
   4453         count=0;
   4454         if (errno != EINTR)
   4455           break;
   4456       }
   4457   }
   4458   return(i);
   4459 }
   4460 
   4461 static MagickBooleanType ReadPixelCacheMetacontent(
   4462   CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
   4463   ExceptionInfo *exception)
   4464 {
   4465   MagickOffsetType
   4466     count,
   4467     offset;
   4468 
   4469   MagickSizeType
   4470     extent,
   4471     length;
   4472 
   4473   register ssize_t
   4474     y;
   4475 
   4476   register unsigned char
   4477     *magick_restrict q;
   4478 
   4479   size_t
   4480     rows;
   4481 
   4482   if (cache_info->metacontent_extent == 0)
   4483     return(MagickFalse);
   4484   if (nexus_info->authentic_pixel_cache != MagickFalse)
   4485     return(MagickTrue);
   4486   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
   4487     nexus_info->region.x;
   4488   length=(MagickSizeType) nexus_info->region.width*
   4489     cache_info->metacontent_extent;
   4490   extent=length*nexus_info->region.height;
   4491   rows=nexus_info->region.height;
   4492   y=0;
   4493   q=(unsigned char *) nexus_info->metacontent;
   4494   switch (cache_info->type)
   4495   {
   4496     case MemoryCache:
   4497     case MapCache:
   4498     {
   4499       register unsigned char
   4500         *magick_restrict p;
   4501 
   4502       /*
   4503         Read meta-content from memory.
   4504       */
   4505       if ((cache_info->columns == nexus_info->region.width) &&
   4506           (extent == (MagickSizeType) ((size_t) extent)))
   4507         {
   4508           length=extent;
   4509           rows=1UL;
   4510         }
   4511       p=(unsigned char *) cache_info->metacontent+offset*
   4512         cache_info->metacontent_extent;
   4513       for (y=0; y < (ssize_t) rows; y++)
   4514       {
   4515         (void) memcpy(q,p,(size_t) length);
   4516         p+=cache_info->metacontent_extent*cache_info->columns;
   4517         q+=cache_info->metacontent_extent*nexus_info->region.width;
   4518       }
   4519       break;
   4520     }
   4521     case DiskCache:
   4522     {
   4523       /*
   4524         Read meta content from disk.
   4525       */
   4526       LockSemaphoreInfo(cache_info->file_semaphore);
   4527       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
   4528         {
   4529           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
   4530             cache_info->cache_filename);
   4531           UnlockSemaphoreInfo(cache_info->file_semaphore);
   4532           return(MagickFalse);
   4533         }
   4534       if ((cache_info->columns == nexus_info->region.width) &&
   4535           (extent <= MagickMaxBufferExtent))
   4536         {
   4537           length=extent;
   4538           rows=1UL;
   4539         }
   4540       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
   4541       for (y=0; y < (ssize_t) rows; y++)
   4542       {
   4543         count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
   4544           cache_info->number_channels*sizeof(Quantum)+offset*
   4545           cache_info->metacontent_extent,length,(unsigned char *) q);
   4546         if (count != (MagickOffsetType) length)
   4547           break;
   4548         offset+=cache_info->columns;
   4549         q+=cache_info->metacontent_extent*nexus_info->region.width;
   4550       }
   4551       if (IsFileDescriptorLimitExceeded() != MagickFalse)
   4552         (void) ClosePixelCacheOnDisk(cache_info);
   4553       UnlockSemaphoreInfo(cache_info->file_semaphore);
   4554       break;
   4555     }
   4556     case DistributedCache:
   4557     {
   4558       RectangleInfo
   4559         region;
   4560 
   4561       /*
   4562         Read metacontent from distributed cache.
   4563       */
   4564       LockSemaphoreInfo(cache_info->file_semaphore);
   4565       region=nexus_info->region;
   4566       if ((cache_info->columns != nexus_info->region.width) ||
   4567           (extent > MagickMaxBufferExtent))
   4568         region.height=1UL;
   4569       else
   4570         {
   4571           length=extent;
   4572           rows=1UL;
   4573         }
   4574       for (y=0; y < (ssize_t) rows; y++)
   4575       {
   4576         count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
   4577           cache_info->server_info,&region,length,(unsigned char *) q);
   4578         if (count != (MagickOffsetType) length)
   4579           break;
   4580         q+=cache_info->metacontent_extent*nexus_info->region.width;
   4581         region.y++;
   4582       }
   4583       UnlockSemaphoreInfo(cache_info->file_semaphore);
   4584       break;
   4585     }
   4586     default:
   4587       break;
   4588   }
   4589   if (y < (ssize_t) rows)
   4590     {
   4591       ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
   4592         cache_info->cache_filename);
   4593       return(MagickFalse);
   4594     }
   4595   if ((cache_info->debug != MagickFalse) &&
   4596       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
   4597     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
   4598       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
   4599       nexus_info->region.width,(double) nexus_info->region.height,(double)
   4600       nexus_info->region.x,(double) nexus_info->region.y);
   4601   return(MagickTrue);
   4602 }
   4603 
   4604 /*
   4606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4607 %                                                                             %
   4608 %                                                                             %
   4609 %                                                                             %
   4610 +   R e a d P i x e l C a c h e P i x e l s                                   %
   4611 %                                                                             %
   4612 %                                                                             %
   4613 %                                                                             %
   4614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4615 %
   4616 %  ReadPixelCachePixels() reads pixels from the specified region of the pixel
   4617 %  cache.
   4618 %
   4619 %  The format of the ReadPixelCachePixels() method is:
   4620 %
   4621 %      MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
   4622 %        NexusInfo *nexus_info,ExceptionInfo *exception)
   4623 %
   4624 %  A description of each parameter follows:
   4625 %
   4626 %    o cache_info: the pixel cache.
   4627 %
   4628 %    o nexus_info: the cache nexus to read the pixels.
   4629 %
   4630 %    o exception: return any errors or warnings in this structure.
   4631 %
   4632 */
   4633 static MagickBooleanType ReadPixelCachePixels(
   4634   CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
   4635   ExceptionInfo *exception)
   4636 {
   4637   MagickOffsetType
   4638     count,
   4639     offset;
   4640 
   4641   MagickSizeType
   4642     extent,
   4643     length;
   4644 
   4645   register Quantum
   4646     *magick_restrict q;
   4647 
   4648   register ssize_t
   4649     y;
   4650 
   4651   size_t
   4652     number_channels,
   4653     rows;
   4654 
   4655   if (nexus_info->authentic_pixel_cache != MagickFalse)
   4656     return(MagickTrue);
   4657   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns;
   4658   if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
   4659     return(MagickFalse);
   4660   offset+=nexus_info->region.x;
   4661   number_channels=cache_info->number_channels;
   4662   length=(MagickSizeType) number_channels*nexus_info->region.width*
   4663     sizeof(Quantum);
   4664   if ((length/number_channels/sizeof(Quantum)) != nexus_info->region.width)
   4665     return(MagickFalse);
   4666   rows=nexus_info->region.height;
   4667   extent=length*rows;
   4668   if ((extent == 0) || ((extent/length) != rows))
   4669     return(MagickFalse);
   4670   y=0;
   4671   q=nexus_info->pixels;
   4672   switch (cache_info->type)
   4673   {
   4674     case MemoryCache:
   4675     case MapCache:
   4676     {
   4677       register Quantum
   4678         *magick_restrict p;
   4679 
   4680       /*
   4681         Read pixels from memory.
   4682       */
   4683       if ((cache_info->columns == nexus_info->region.width) &&
   4684           (extent == (MagickSizeType) ((size_t) extent)))
   4685         {
   4686           length=extent;
   4687           rows=1UL;
   4688         }
   4689       p=cache_info->pixels+cache_info->number_channels*offset;
   4690       for (y=0; y < (ssize_t) rows; y++)
   4691       {
   4692         (void) memcpy(q,p,(size_t) length);
   4693         p+=cache_info->number_channels*cache_info->columns;
   4694         q+=cache_info->number_channels*nexus_info->region.width;
   4695       }
   4696       break;
   4697     }
   4698     case DiskCache:
   4699     {
   4700       /*
   4701         Read pixels from disk.
   4702       */
   4703       LockSemaphoreInfo(cache_info->file_semaphore);
   4704       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
   4705         {
   4706           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
   4707             cache_info->cache_filename);
   4708           UnlockSemaphoreInfo(cache_info->file_semaphore);
   4709           return(MagickFalse);
   4710         }
   4711       if ((cache_info->columns == nexus_info->region.width) &&
   4712           (extent <= MagickMaxBufferExtent))
   4713         {
   4714           length=extent;
   4715           rows=1UL;
   4716         }
   4717       for (y=0; y < (ssize_t) rows; y++)
   4718       {
   4719         count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
   4720           cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
   4721         if (count != (MagickOffsetType) length)
   4722           break;
   4723         offset+=cache_info->columns;
   4724         q+=cache_info->number_channels*nexus_info->region.width;
   4725       }
   4726       if (IsFileDescriptorLimitExceeded() != MagickFalse)
   4727         (void) ClosePixelCacheOnDisk(cache_info);
   4728       UnlockSemaphoreInfo(cache_info->file_semaphore);
   4729       break;
   4730     }
   4731     case DistributedCache:
   4732     {
   4733       RectangleInfo
   4734         region;
   4735 
   4736       /*
   4737         Read pixels from distributed cache.
   4738       */
   4739       LockSemaphoreInfo(cache_info->file_semaphore);
   4740       region=nexus_info->region;
   4741       if ((cache_info->columns != nexus_info->region.width) ||
   4742           (extent > MagickMaxBufferExtent))
   4743         region.height=1UL;
   4744       else
   4745         {
   4746           length=extent;
   4747           rows=1UL;
   4748         }
   4749       for (y=0; y < (ssize_t) rows; y++)
   4750       {
   4751         count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
   4752           cache_info->server_info,&region,length,(unsigned char *) q);
   4753         if (count != (MagickOffsetType) length)
   4754           break;
   4755         q+=cache_info->number_channels*nexus_info->region.width;
   4756         region.y++;
   4757       }
   4758       UnlockSemaphoreInfo(cache_info->file_semaphore);
   4759       break;
   4760     }
   4761     default:
   4762       break;
   4763   }
   4764   if (y < (ssize_t) rows)
   4765     {
   4766       ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
   4767         cache_info->cache_filename);
   4768       return(MagickFalse);
   4769     }
   4770   if ((cache_info->debug != MagickFalse) &&
   4771       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
   4772     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
   4773       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
   4774       nexus_info->region.width,(double) nexus_info->region.height,(double)
   4775       nexus_info->region.x,(double) nexus_info->region.y);
   4776   return(MagickTrue);
   4777 }
   4778 
   4779 /*
   4781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4782 %                                                                             %
   4783 %                                                                             %
   4784 %                                                                             %
   4785 +   R e f e r e n c e P i x e l C a c h e                                     %
   4786 %                                                                             %
   4787 %                                                                             %
   4788 %                                                                             %
   4789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4790 %
   4791 %  ReferencePixelCache() increments the reference count associated with the
   4792 %  pixel cache returning a pointer to the cache.
   4793 %
   4794 %  The format of the ReferencePixelCache method is:
   4795 %
   4796 %      Cache ReferencePixelCache(Cache cache_info)
   4797 %
   4798 %  A description of each parameter follows:
   4799 %
   4800 %    o cache_info: the pixel cache.
   4801 %
   4802 */
   4803 MagickPrivate Cache ReferencePixelCache(Cache cache)
   4804 {
   4805   CacheInfo
   4806     *magick_restrict cache_info;
   4807 
   4808   assert(cache != (Cache *) NULL);
   4809   cache_info=(CacheInfo *) cache;
   4810   assert(cache_info->signature == MagickCoreSignature);
   4811   LockSemaphoreInfo(cache_info->semaphore);
   4812   cache_info->reference_count++;
   4813   UnlockSemaphoreInfo(cache_info->semaphore);
   4814   return(cache_info);
   4815 }
   4816 
   4817 /*
   4819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4820 %                                                                             %
   4821 %                                                                             %
   4822 %                                                                             %
   4823 +   R e s e t P i x e l C a c h e C h a n n e l s                             %
   4824 %                                                                             %
   4825 %                                                                             %
   4826 %                                                                             %
   4827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4828 %
   4829 %  ResetPixelCacheChannels() resets the pixel cache channels.
   4830 %
   4831 %  The format of the ResetPixelCacheChannels method is:
   4832 %
   4833 %      void ResetPixelCacheChannels(Image *)
   4834 %
   4835 %  A description of each parameter follows:
   4836 %
   4837 %    o image: the image.
   4838 %
   4839 */
   4840 MagickPrivate void ResetPixelCacheChannels(Image *image)
   4841 {
   4842   CacheInfo
   4843     *magick_restrict cache_info;
   4844 
   4845   assert(image != (const Image *) NULL);
   4846   assert(image->signature == MagickCoreSignature);
   4847   assert(image->cache != (Cache) NULL);
   4848   cache_info=(CacheInfo *) image->cache;
   4849   assert(cache_info->signature == MagickCoreSignature);
   4850   cache_info->number_channels=GetPixelChannels(image);
   4851 }
   4852 
   4853 /*
   4855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4856 %                                                                             %
   4857 %                                                                             %
   4858 %                                                                             %
   4859 +   R e s e t C a c h e A n o n y m o u s M e m o r y                         %
   4860 %                                                                             %
   4861 %                                                                             %
   4862 %                                                                             %
   4863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4864 %
   4865 %  ResetCacheAnonymousMemory() resets the anonymous_memory value.
   4866 %
   4867 %  The format of the ResetCacheAnonymousMemory method is:
   4868 %
   4869 %      void ResetCacheAnonymousMemory(void)
   4870 %
   4871 */
   4872 MagickPrivate void ResetCacheAnonymousMemory(void)
   4873 {
   4874   cache_anonymous_memory=0;
   4875 }
   4876 
   4877 /*
   4879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4880 %                                                                             %
   4881 %                                                                             %
   4882 %                                                                             %
   4883 +   R e s e t P i x e l C a c h e E p o c h                                   %
   4884 %                                                                             %
   4885 %                                                                             %
   4886 %                                                                             %
   4887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4888 %
   4889 %  ResetPixelCacheEpoch() resets the pixel cache epoch.
   4890 %
   4891 %  The format of the ResetPixelCacheEpoch method is:
   4892 %
   4893 %      void ResetPixelCacheEpoch(void)
   4894 %
   4895 */
   4896 MagickPrivate void ResetPixelCacheEpoch(void)
   4897 {
   4898   cache_epoch=0;
   4899 }
   4900 
   4901 /*
   4903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4904 %                                                                             %
   4905 %                                                                             %
   4906 %                                                                             %
   4907 +   S e t P i x e l C a c h e M e t h o d s                                   %
   4908 %                                                                             %
   4909 %                                                                             %
   4910 %                                                                             %
   4911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4912 %
   4913 %  SetPixelCacheMethods() sets the image pixel methods to the specified ones.
   4914 %
   4915 %  The format of the SetPixelCacheMethods() method is:
   4916 %
   4917 %      SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
   4918 %
   4919 %  A description of each parameter follows:
   4920 %
   4921 %    o cache: the pixel cache.
   4922 %
   4923 %    o cache_methods: Specifies a pointer to a CacheMethods structure.
   4924 %
   4925 */
   4926 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
   4927 {
   4928   CacheInfo
   4929     *magick_restrict cache_info;
   4930 
   4931   GetOneAuthenticPixelFromHandler
   4932     get_one_authentic_pixel_from_handler;
   4933 
   4934   GetOneVirtualPixelFromHandler
   4935     get_one_virtual_pixel_from_handler;
   4936 
   4937   /*
   4938     Set cache pixel methods.
   4939   */
   4940   assert(cache != (Cache) NULL);
   4941   assert(cache_methods != (CacheMethods *) NULL);
   4942   cache_info=(CacheInfo *) cache;
   4943   assert(cache_info->signature == MagickCoreSignature);
   4944   if (cache_info->debug != MagickFalse)
   4945     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   4946       cache_info->filename);
   4947   if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
   4948     cache_info->methods.get_virtual_pixel_handler=
   4949       cache_methods->get_virtual_pixel_handler;
   4950   if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
   4951     cache_info->methods.destroy_pixel_handler=
   4952       cache_methods->destroy_pixel_handler;
   4953   if (cache_methods->get_virtual_metacontent_from_handler !=
   4954       (GetVirtualMetacontentFromHandler) NULL)
   4955     cache_info->methods.get_virtual_metacontent_from_handler=
   4956       cache_methods->get_virtual_metacontent_from_handler;
   4957   if (cache_methods->get_authentic_pixels_handler !=
   4958       (GetAuthenticPixelsHandler) NULL)
   4959     cache_info->methods.get_authentic_pixels_handler=
   4960       cache_methods->get_authentic_pixels_handler;
   4961   if (cache_methods->queue_authentic_pixels_handler !=
   4962       (QueueAuthenticPixelsHandler) NULL)
   4963     cache_info->methods.queue_authentic_pixels_handler=
   4964       cache_methods->queue_authentic_pixels_handler;
   4965   if (cache_methods->sync_authentic_pixels_handler !=
   4966       (SyncAuthenticPixelsHandler) NULL)
   4967     cache_info->methods.sync_authentic_pixels_handler=
   4968       cache_methods->sync_authentic_pixels_handler;
   4969   if (cache_methods->get_authentic_pixels_from_handler !=
   4970       (GetAuthenticPixelsFromHandler) NULL)
   4971     cache_info->methods.get_authentic_pixels_from_handler=
   4972       cache_methods->get_authentic_pixels_from_handler;
   4973   if (cache_methods->get_authentic_metacontent_from_handler !=
   4974       (GetAuthenticMetacontentFromHandler) NULL)
   4975     cache_info->methods.get_authentic_metacontent_from_handler=
   4976       cache_methods->get_authentic_metacontent_from_handler;
   4977   get_one_virtual_pixel_from_handler=
   4978     cache_info->methods.get_one_virtual_pixel_from_handler;
   4979   if (get_one_virtual_pixel_from_handler !=
   4980       (GetOneVirtualPixelFromHandler) NULL)
   4981     cache_info->methods.get_one_virtual_pixel_from_handler=
   4982       cache_methods->get_one_virtual_pixel_from_handler;
   4983   get_one_authentic_pixel_from_handler=
   4984     cache_methods->get_one_authentic_pixel_from_handler;
   4985   if (get_one_authentic_pixel_from_handler !=
   4986       (GetOneAuthenticPixelFromHandler) NULL)
   4987     cache_info->methods.get_one_authentic_pixel_from_handler=
   4988       cache_methods->get_one_authentic_pixel_from_handler;
   4989 }
   4990 
   4991 /*
   4993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4994 %                                                                             %
   4995 %                                                                             %
   4996 %                                                                             %
   4997 +   S e t P i x e l C a c h e N e x u s P i x e l s                           %
   4998 %                                                                             %
   4999 %                                                                             %
   5000 %                                                                             %
   5001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5002 %
   5003 %  SetPixelCacheNexusPixels() defines the region of the cache for the
   5004 %  specified cache nexus.
   5005 %
   5006 %  The format of the SetPixelCacheNexusPixels() method is:
   5007 %
   5008 %      Quantum SetPixelCacheNexusPixels(const CacheInfo *cache_info,
   5009 %        const MapMode mode,const RectangleInfo *region,
   5010 %        const MagickBooleanType buffered,NexusInfo *nexus_info,
   5011 %        ExceptionInfo *exception)
   5012 %
   5013 %  A description of each parameter follows:
   5014 %
   5015 %    o cache_info: the pixel cache.
   5016 %
   5017 %    o mode: ReadMode, WriteMode, or IOMode.
   5018 %
   5019 %    o region: A pointer to the RectangleInfo structure that defines the
   5020 %      region of this particular cache nexus.
   5021 %
   5022 %    o buffered: if true, nexus pixels are buffered.
   5023 %
   5024 %    o nexus_info: the cache nexus to set.
   5025 %
   5026 %    o exception: return any errors or warnings in this structure.
   5027 %
   5028 */
   5029 
   5030 static inline MagickBooleanType AcquireCacheNexusPixels(
   5031   const CacheInfo *magick_restrict cache_info,const MagickSizeType length,
   5032   NexusInfo *nexus_info,ExceptionInfo *exception)
   5033 {
   5034   if (length != (MagickSizeType) ((size_t) length))
   5035     {
   5036       (void) ThrowMagickException(exception,GetMagickModule(),
   5037         ResourceLimitError,"PixelCacheAllocationFailed","`%s'",
   5038         cache_info->filename);
   5039       return(MagickFalse);
   5040     }
   5041   nexus_info->length=0;
   5042   nexus_info->mapped=MagickFalse;
   5043   if (cache_anonymous_memory <= 0)
   5044     {
   5045       nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
   5046         (size_t) length));
   5047       if (nexus_info->cache != (Quantum *) NULL)
   5048         (void) memset(nexus_info->cache,0,(size_t) length);
   5049     }
   5050   else
   5051     {
   5052       nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t) length);
   5053       if (nexus_info->cache != (Quantum *) NULL)
   5054         nexus_info->mapped=MagickTrue;
   5055     }
   5056   if (nexus_info->cache == (Quantum *) NULL)
   5057     {
   5058       (void) ThrowMagickException(exception,GetMagickModule(),
   5059         ResourceLimitError,"PixelCacheAllocationFailed","`%s'",
   5060         cache_info->filename);
   5061       return(MagickFalse);
   5062     }
   5063   nexus_info->length=length;
   5064   return(MagickTrue);
   5065 }
   5066 
   5067 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
   5068   const MapMode mode)
   5069 {
   5070   if (nexus_info->length < CACHE_LINE_SIZE)
   5071     return;
   5072   if (mode == ReadMode)
   5073     {
   5074       MagickCachePrefetch((unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
   5075         0,1);
   5076       return;
   5077     }
   5078   MagickCachePrefetch((unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
   5079 }
   5080 
   5081 static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
   5082   const MapMode mode,const RectangleInfo *region,
   5083   const MagickBooleanType buffered,NexusInfo *nexus_info,
   5084   ExceptionInfo *exception)
   5085 {
   5086   MagickBooleanType
   5087     status;
   5088 
   5089   MagickSizeType
   5090     length,
   5091     number_pixels;
   5092 
   5093   assert(cache_info != (const CacheInfo *) NULL);
   5094   assert(cache_info->signature == MagickCoreSignature);
   5095   if (cache_info->type == UndefinedCache)
   5096     return((Quantum *) NULL);
   5097   (void) memset(&nexus_info->region,0,sizeof(nexus_info->region));
   5098   if ((region->width == 0) || (region->height == 0))
   5099     {
   5100       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
   5101         "NoPixelsDefinedInCache","`%s'",cache_info->filename);
   5102       return((Quantum *) NULL);
   5103     }
   5104   assert(nexus_info->signature == MagickCoreSignature);
   5105   if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
   5106       (buffered == MagickFalse))
   5107     {
   5108       ssize_t
   5109         x,
   5110         y;
   5111 
   5112       x=(ssize_t) region->width+region->x-1;
   5113       y=(ssize_t) region->height+region->y-1;
   5114       if (((region->x >= 0) &&
   5115            (region->y >= 0) && (y < (ssize_t) cache_info->rows)) &&
   5116           (((region->x == 0) && (region->width == cache_info->columns)) ||
   5117            ((region->height == 1) && (x < (ssize_t) cache_info->columns))))
   5118         {
   5119           MagickOffsetType
   5120             offset;
   5121 
   5122           /*
   5123             Pixels are accessed directly from memory.
   5124           */
   5125           offset=(MagickOffsetType) region->y*cache_info->columns+region->x;
   5126           nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
   5127             offset;
   5128           nexus_info->metacontent=(void *) NULL;
   5129           if (cache_info->metacontent_extent != 0)
   5130             nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
   5131               offset*cache_info->metacontent_extent;
   5132           nexus_info->region=(*region);
   5133           nexus_info->authentic_pixel_cache=MagickTrue;
   5134           PrefetchPixelCacheNexusPixels(nexus_info,mode);
   5135           return(nexus_info->pixels);
   5136         }
   5137     }
   5138   /*
   5139     Pixels are stored in a staging region until they are synced to the cache.
   5140   */
   5141   if (((region->x != (ssize_t) nexus_info->region.width) ||
   5142        (region->y != (ssize_t) nexus_info->region.height)) &&
   5143       ((AcquireMagickResource(WidthResource,region->width) == MagickFalse) ||
   5144        (AcquireMagickResource(HeightResource,region->height) == MagickFalse)))
   5145     {
   5146       (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
   5147         "WidthOrHeightExceedsLimit","`%s'",cache_info->filename);
   5148       return((Quantum *) NULL);
   5149     }
   5150   number_pixels=(MagickSizeType) region->width*region->height;
   5151   length=MagickMax(number_pixels,cache_info->columns)*
   5152     cache_info->number_channels*sizeof(*nexus_info->pixels);
   5153   if (cache_info->metacontent_extent != 0)
   5154     length+=number_pixels*cache_info->metacontent_extent;
   5155   status=MagickTrue;
   5156   if (nexus_info->cache == (Quantum *) NULL)
   5157     status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
   5158   else
   5159     if (nexus_info->length < length)
   5160       {
   5161         RelinquishCacheNexusPixels(nexus_info);
   5162         status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
   5163       }
   5164   if (status == MagickFalse)
   5165     return((Quantum *) NULL);
   5166   nexus_info->pixels=nexus_info->cache;
   5167   nexus_info->metacontent=(void *) NULL;
   5168   if (cache_info->metacontent_extent != 0)
   5169     nexus_info->metacontent=(void *) (nexus_info->pixels+
   5170       cache_info->number_channels*number_pixels);
   5171   nexus_info->region=(*region);
   5172   nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
   5173     MagickTrue : MagickFalse;
   5174   PrefetchPixelCacheNexusPixels(nexus_info,mode);
   5175   return(nexus_info->pixels);
   5176 }
   5177 
   5178 /*
   5180 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5181 %                                                                             %
   5182 %                                                                             %
   5183 %                                                                             %
   5184 %   S e t P i x e l C a c h e V i r t u a l M e t h o d                       %
   5185 %                                                                             %
   5186 %                                                                             %
   5187 %                                                                             %
   5188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5189 %
   5190 %  SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
   5191 %  pixel cache and returns the previous setting.  A virtual pixel is any pixel
   5192 %  access that is outside the boundaries of the image cache.
   5193 %
   5194 %  The format of the SetPixelCacheVirtualMethod() method is:
   5195 %
   5196 %      VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
   5197 %        const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
   5198 %
   5199 %  A description of each parameter follows:
   5200 %
   5201 %    o image: the image.
   5202 %
   5203 %    o virtual_pixel_method: choose the type of virtual pixel.
   5204 %
   5205 %    o exception: return any errors or warnings in this structure.
   5206 %
   5207 */
   5208 
   5209 static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
   5210   ExceptionInfo *exception)
   5211 {
   5212   CacheInfo
   5213     *magick_restrict cache_info;
   5214 
   5215   CacheView
   5216     *magick_restrict image_view;
   5217 
   5218   MagickBooleanType
   5219     status;
   5220 
   5221   ssize_t
   5222     y;
   5223 
   5224   assert(image != (Image *) NULL);
   5225   assert(image->signature == MagickCoreSignature);
   5226   if (image->debug != MagickFalse)
   5227     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   5228   assert(image->cache != (Cache) NULL);
   5229   cache_info=(CacheInfo *) image->cache;
   5230   assert(cache_info->signature == MagickCoreSignature);
   5231   image->alpha_trait=BlendPixelTrait;
   5232   status=MagickTrue;
   5233   image_view=AcquireVirtualCacheView(image,exception);  /* must be virtual */
   5234 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   5235   #pragma omp parallel for schedule(static) shared(status) \
   5236     magick_number_threads(image,image,image->rows,1)
   5237 #endif
   5238   for (y=0; y < (ssize_t) image->rows; y++)
   5239   {
   5240     register Quantum
   5241       *magick_restrict q;
   5242 
   5243     register ssize_t
   5244       x;
   5245 
   5246     if (status == MagickFalse)
   5247       continue;
   5248     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
   5249     if (q == (Quantum *) NULL)
   5250       {
   5251         status=MagickFalse;
   5252         continue;
   5253       }
   5254     for (x=0; x < (ssize_t) image->columns; x++)
   5255     {
   5256       SetPixelAlpha(image,alpha,q);
   5257       q+=GetPixelChannels(image);
   5258     }
   5259     status=SyncCacheViewAuthenticPixels(image_view,exception);
   5260   }
   5261   image_view=DestroyCacheView(image_view);
   5262   return(status);
   5263 }
   5264 
   5265 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
   5266   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
   5267 {
   5268   CacheInfo
   5269     *magick_restrict cache_info;
   5270 
   5271   VirtualPixelMethod
   5272     method;
   5273 
   5274   assert(image != (Image *) NULL);
   5275   assert(image->signature == MagickCoreSignature);
   5276   if (image->debug != MagickFalse)
   5277     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   5278   assert(image->cache != (Cache) NULL);
   5279   cache_info=(CacheInfo *) image->cache;
   5280   assert(cache_info->signature == MagickCoreSignature);
   5281   method=cache_info->virtual_pixel_method;
   5282   cache_info->virtual_pixel_method=virtual_pixel_method;
   5283   if ((image->columns != 0) && (image->rows != 0))
   5284     switch (virtual_pixel_method)
   5285     {
   5286       case BackgroundVirtualPixelMethod:
   5287       {
   5288         if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
   5289             (image->alpha_trait == UndefinedPixelTrait))
   5290           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
   5291         if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
   5292             (IsGrayColorspace(image->colorspace) != MagickFalse))
   5293           (void) SetImageColorspace(image,sRGBColorspace,exception);
   5294         break;
   5295       }
   5296       case TransparentVirtualPixelMethod:
   5297       {
   5298         if (image->alpha_trait == UndefinedPixelTrait)
   5299           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
   5300         break;
   5301       }
   5302       default:
   5303         break;
   5304     }
   5305   return(method);
   5306 }
   5307 
   5308 #if defined(MAGICKCORE_OPENCL_SUPPORT)
   5309 /*
   5310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5311 %                                                                             %
   5312 %                                                                             %
   5313 %                                                                             %
   5314 +   S y n c A u t h e n t i c O p e n C L B u f f e r                         %
   5315 %                                                                             %
   5316 %                                                                             %
   5317 %                                                                             %
   5318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5319 %
   5320 %  SyncAuthenticOpenCLBuffer() makes sure that all the OpenCL operations have
   5321 %  been completed and updates the host memory.
   5322 %
   5323 %  The format of the SyncAuthenticOpenCLBuffer() method is:
   5324 %
   5325 %      void SyncAuthenticOpenCLBuffer(const Image *image)
   5326 %
   5327 %  A description of each parameter follows:
   5328 %
   5329 %    o image: the image.
   5330 %
   5331 */
   5332 
   5333 static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
   5334 {
   5335   assert(cache_info != (CacheInfo *) NULL);
   5336   assert(cache_info->signature == MagickCoreSignature);
   5337   if ((cache_info->type != MemoryCache) ||
   5338       (cache_info->opencl == (MagickCLCacheInfo) NULL))
   5339     return;
   5340   /*
   5341     Ensure single threaded access to OpenCL environment.
   5342   */
   5343   LockSemaphoreInfo(cache_info->semaphore);
   5344   cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
   5345   UnlockSemaphoreInfo(cache_info->semaphore);
   5346 }
   5347 
   5348 MagickPrivate void SyncAuthenticOpenCLBuffer(const Image *image)
   5349 {
   5350   CacheInfo
   5351     *magick_restrict cache_info;
   5352 
   5353   assert(image != (const Image *) NULL);
   5354   cache_info=(CacheInfo *) image->cache;
   5355   CopyOpenCLBuffer(cache_info);
   5356 }
   5357 #endif
   5358 
   5359 /*
   5361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5362 %                                                                             %
   5363 %                                                                             %
   5364 %                                                                             %
   5365 +   S y n c A u t h e n t i c P i x e l C a c h e N e x u s                   %
   5366 %                                                                             %
   5367 %                                                                             %
   5368 %                                                                             %
   5369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5370 %
   5371 %  SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
   5372 %  in-memory or disk cache.  The method returns MagickTrue if the pixel region
   5373 %  is synced, otherwise MagickFalse.
   5374 %
   5375 %  The format of the SyncAuthenticPixelCacheNexus() method is:
   5376 %
   5377 %      MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
   5378 %        NexusInfo *nexus_info,ExceptionInfo *exception)
   5379 %
   5380 %  A description of each parameter follows:
   5381 %
   5382 %    o image: the image.
   5383 %
   5384 %    o nexus_info: the cache nexus to sync.
   5385 %
   5386 %    o exception: return any errors or warnings in this structure.
   5387 %
   5388 */
   5389 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
   5390   NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
   5391 {
   5392   CacheInfo
   5393     *magick_restrict cache_info;
   5394 
   5395   MagickBooleanType
   5396     status;
   5397 
   5398   /*
   5399     Transfer pixels to the cache.
   5400   */
   5401   assert(image != (Image *) NULL);
   5402   assert(image->signature == MagickCoreSignature);
   5403   if (image->cache == (Cache) NULL)
   5404     ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
   5405   cache_info=(CacheInfo *) image->cache;
   5406   assert(cache_info->signature == MagickCoreSignature);
   5407   if (cache_info->type == UndefinedCache)
   5408     return(MagickFalse);
   5409   if (image->mask_trait != UpdatePixelTrait)
   5410     {
   5411       if (((image->channels & WriteMaskChannel) != 0) &&
   5412           (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
   5413         return(MagickFalse);
   5414       if (((image->channels & CompositeMaskChannel) != 0) &&
   5415           (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
   5416         return(MagickFalse);
   5417     }
   5418   if (nexus_info->authentic_pixel_cache != MagickFalse)
   5419     {
   5420       image->taint=MagickTrue;
   5421       return(MagickTrue);
   5422     }
   5423   assert(cache_info->signature == MagickCoreSignature);
   5424   status=WritePixelCachePixels(cache_info,nexus_info,exception);
   5425   if ((cache_info->metacontent_extent != 0) &&
   5426       (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
   5427     return(MagickFalse);
   5428   if (status != MagickFalse)
   5429     image->taint=MagickTrue;
   5430   return(status);
   5431 }
   5432 
   5433 /*
   5435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5436 %                                                                             %
   5437 %                                                                             %
   5438 %                                                                             %
   5439 +   S y n c A u t h e n t i c P i x e l C a c h e                             %
   5440 %                                                                             %
   5441 %                                                                             %
   5442 %                                                                             %
   5443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5444 %
   5445 %  SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
   5446 %  or disk cache.  The method returns MagickTrue if the pixel region is synced,
   5447 %  otherwise MagickFalse.
   5448 %
   5449 %  The format of the SyncAuthenticPixelsCache() method is:
   5450 %
   5451 %      MagickBooleanType SyncAuthenticPixelsCache(Image *image,
   5452 %        ExceptionInfo *exception)
   5453 %
   5454 %  A description of each parameter follows:
   5455 %
   5456 %    o image: the image.
   5457 %
   5458 %    o exception: return any errors or warnings in this structure.
   5459 %
   5460 */
   5461 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
   5462   ExceptionInfo *exception)
   5463 {
   5464   CacheInfo
   5465     *magick_restrict cache_info;
   5466 
   5467   const int
   5468     id = GetOpenMPThreadId();
   5469 
   5470   MagickBooleanType
   5471     status;
   5472 
   5473   assert(image != (Image *) NULL);
   5474   assert(image->signature == MagickCoreSignature);
   5475   assert(image->cache != (Cache) NULL);
   5476   cache_info=(CacheInfo *) image->cache;
   5477   assert(cache_info->signature == MagickCoreSignature);
   5478   assert(id < (int) cache_info->number_threads);
   5479   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
   5480     exception);
   5481   return(status);
   5482 }
   5483 
   5484 /*
   5486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5487 %                                                                             %
   5488 %                                                                             %
   5489 %                                                                             %
   5490 %   S y n c A u t h e n t i c P i x e l s                                     %
   5491 %                                                                             %
   5492 %                                                                             %
   5493 %                                                                             %
   5494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5495 %
   5496 %  SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
   5497 %  The method returns MagickTrue if the pixel region is flushed, otherwise
   5498 %  MagickFalse.
   5499 %
   5500 %  The format of the SyncAuthenticPixels() method is:
   5501 %
   5502 %      MagickBooleanType SyncAuthenticPixels(Image *image,
   5503 %        ExceptionInfo *exception)
   5504 %
   5505 %  A description of each parameter follows:
   5506 %
   5507 %    o image: the image.
   5508 %
   5509 %    o exception: return any errors or warnings in this structure.
   5510 %
   5511 */
   5512 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
   5513   ExceptionInfo *exception)
   5514 {
   5515   CacheInfo
   5516     *magick_restrict cache_info;
   5517 
   5518   const int
   5519     id = GetOpenMPThreadId();
   5520 
   5521   MagickBooleanType
   5522     status;
   5523 
   5524   assert(image != (Image *) NULL);
   5525   assert(image->signature == MagickCoreSignature);
   5526   assert(image->cache != (Cache) NULL);
   5527   cache_info=(CacheInfo *) image->cache;
   5528   assert(cache_info->signature == MagickCoreSignature);
   5529   if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
   5530     {
   5531       status=cache_info->methods.sync_authentic_pixels_handler(image,
   5532         exception);
   5533       return(status);
   5534     }
   5535   assert(id < (int) cache_info->number_threads);
   5536   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
   5537     exception);
   5538   return(status);
   5539 }
   5540 
   5541 /*
   5543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5544 %                                                                             %
   5545 %                                                                             %
   5546 %                                                                             %
   5547 +   S y n c I m a g e P i x e l C a c h e                                     %
   5548 %                                                                             %
   5549 %                                                                             %
   5550 %                                                                             %
   5551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5552 %
   5553 %  SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
   5554 %  The method returns MagickTrue if the pixel region is flushed, otherwise
   5555 %  MagickFalse.
   5556 %
   5557 %  The format of the SyncImagePixelCache() method is:
   5558 %
   5559 %      MagickBooleanType SyncImagePixelCache(Image *image,
   5560 %        ExceptionInfo *exception)
   5561 %
   5562 %  A description of each parameter follows:
   5563 %
   5564 %    o image: the image.
   5565 %
   5566 %    o exception: return any errors or warnings in this structure.
   5567 %
   5568 */
   5569 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
   5570   ExceptionInfo *exception)
   5571 {
   5572   CacheInfo
   5573     *magick_restrict cache_info;
   5574 
   5575   assert(image != (Image *) NULL);
   5576   assert(exception != (ExceptionInfo *) NULL);
   5577   cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
   5578   return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
   5579 }
   5580 
   5581 /*
   5583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5584 %                                                                             %
   5585 %                                                                             %
   5586 %                                                                             %
   5587 +   W r i t e P i x e l C a c h e M e t a c o n t e n t                       %
   5588 %                                                                             %
   5589 %                                                                             %
   5590 %                                                                             %
   5591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5592 %
   5593 %  WritePixelCacheMetacontent() writes the meta-content to the specified region
   5594 %  of the pixel cache.
   5595 %
   5596 %  The format of the WritePixelCacheMetacontent() method is:
   5597 %
   5598 %      MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
   5599 %        NexusInfo *nexus_info,ExceptionInfo *exception)
   5600 %
   5601 %  A description of each parameter follows:
   5602 %
   5603 %    o cache_info: the pixel cache.
   5604 %
   5605 %    o nexus_info: the cache nexus to write the meta-content.
   5606 %
   5607 %    o exception: return any errors or warnings in this structure.
   5608 %
   5609 */
   5610 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
   5611   NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
   5612 {
   5613   MagickOffsetType
   5614     count,
   5615     offset;
   5616 
   5617   MagickSizeType
   5618     extent,
   5619     length;
   5620 
   5621   register const unsigned char
   5622     *magick_restrict p;
   5623 
   5624   register ssize_t
   5625     y;
   5626 
   5627   size_t
   5628     rows;
   5629 
   5630   if (cache_info->metacontent_extent == 0)
   5631     return(MagickFalse);
   5632   if (nexus_info->authentic_pixel_cache != MagickFalse)
   5633     return(MagickTrue);
   5634   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
   5635     nexus_info->region.x;
   5636   length=(MagickSizeType) nexus_info->region.width*
   5637     cache_info->metacontent_extent;
   5638   extent=(MagickSizeType) length*nexus_info->region.height;
   5639   rows=nexus_info->region.height;
   5640   y=0;
   5641   p=(unsigned char *) nexus_info->metacontent;
   5642   switch (cache_info->type)
   5643   {
   5644     case MemoryCache:
   5645     case MapCache:
   5646     {
   5647       register unsigned char
   5648         *magick_restrict q;
   5649 
   5650       /*
   5651         Write associated pixels to memory.
   5652       */
   5653       if ((cache_info->columns == nexus_info->region.width) &&
   5654           (extent == (MagickSizeType) ((size_t) extent)))
   5655         {
   5656           length=extent;
   5657           rows=1UL;
   5658         }
   5659       q=(unsigned char *) cache_info->metacontent+offset*
   5660         cache_info->metacontent_extent;
   5661       for (y=0; y < (ssize_t) rows; y++)
   5662       {
   5663         (void) memcpy(q,p,(size_t) length);
   5664         p+=nexus_info->region.width*cache_info->metacontent_extent;
   5665         q+=cache_info->columns*cache_info->metacontent_extent;
   5666       }
   5667       break;
   5668     }
   5669     case DiskCache:
   5670     {
   5671       /*
   5672         Write associated pixels to disk.
   5673       */
   5674       LockSemaphoreInfo(cache_info->file_semaphore);
   5675       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
   5676         {
   5677           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
   5678             cache_info->cache_filename);
   5679           UnlockSemaphoreInfo(cache_info->file_semaphore);
   5680           return(MagickFalse);
   5681         }
   5682       if ((cache_info->columns == nexus_info->region.width) &&
   5683           (extent <= MagickMaxBufferExtent))
   5684         {
   5685           length=extent;
   5686           rows=1UL;
   5687         }
   5688       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
   5689       for (y=0; y < (ssize_t) rows; y++)
   5690       {
   5691         count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
   5692           cache_info->number_channels*sizeof(Quantum)+offset*
   5693           cache_info->metacontent_extent,length,(const unsigned char *) p);
   5694         if (count != (MagickOffsetType) length)
   5695           break;
   5696         p+=cache_info->metacontent_extent*nexus_info->region.width;
   5697         offset+=cache_info->columns;
   5698       }
   5699       if (IsFileDescriptorLimitExceeded() != MagickFalse)
   5700         (void) ClosePixelCacheOnDisk(cache_info);
   5701       UnlockSemaphoreInfo(cache_info->file_semaphore);
   5702       break;
   5703     }
   5704     case DistributedCache:
   5705     {
   5706       RectangleInfo
   5707         region;
   5708 
   5709       /*
   5710         Write metacontent to distributed cache.
   5711       */
   5712       LockSemaphoreInfo(cache_info->file_semaphore);
   5713       region=nexus_info->region;
   5714       if ((cache_info->columns != nexus_info->region.width) ||
   5715           (extent > MagickMaxBufferExtent))
   5716         region.height=1UL;
   5717       else
   5718         {
   5719           length=extent;
   5720           rows=1UL;
   5721         }
   5722       for (y=0; y < (ssize_t) rows; y++)
   5723       {
   5724         count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
   5725           cache_info->server_info,&region,length,(const unsigned char *) p);
   5726         if (count != (MagickOffsetType) length)
   5727           break;
   5728         p+=cache_info->metacontent_extent*nexus_info->region.width;
   5729         region.y++;
   5730       }
   5731       UnlockSemaphoreInfo(cache_info->file_semaphore);
   5732       break;
   5733     }
   5734     default:
   5735       break;
   5736   }
   5737   if (y < (ssize_t) rows)
   5738     {
   5739       ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
   5740         cache_info->cache_filename);
   5741       return(MagickFalse);
   5742     }
   5743   if ((cache_info->debug != MagickFalse) &&
   5744       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
   5745     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
   5746       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
   5747       nexus_info->region.width,(double) nexus_info->region.height,(double)
   5748       nexus_info->region.x,(double) nexus_info->region.y);
   5749   return(MagickTrue);
   5750 }
   5751 
   5752 /*
   5754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5755 %                                                                             %
   5756 %                                                                             %
   5757 %                                                                             %
   5758 +   W r i t e C a c h e P i x e l s                                           %
   5759 %                                                                             %
   5760 %                                                                             %
   5761 %                                                                             %
   5762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5763 %
   5764 %  WritePixelCachePixels() writes image pixels to the specified region of the
   5765 %  pixel cache.
   5766 %
   5767 %  The format of the WritePixelCachePixels() method is:
   5768 %
   5769 %      MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
   5770 %        NexusInfo *nexus_info,ExceptionInfo *exception)
   5771 %
   5772 %  A description of each parameter follows:
   5773 %
   5774 %    o cache_info: the pixel cache.
   5775 %
   5776 %    o nexus_info: the cache nexus to write the pixels.
   5777 %
   5778 %    o exception: return any errors or warnings in this structure.
   5779 %
   5780 */
   5781 static MagickBooleanType WritePixelCachePixels(
   5782   CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
   5783   ExceptionInfo *exception)
   5784 {
   5785   MagickOffsetType
   5786     count,
   5787     offset;
   5788 
   5789   MagickSizeType
   5790     extent,
   5791     length;
   5792 
   5793   register const Quantum
   5794     *magick_restrict p;
   5795 
   5796   register ssize_t
   5797     y;
   5798 
   5799   size_t
   5800     rows;
   5801 
   5802   if (nexus_info->authentic_pixel_cache != MagickFalse)
   5803     return(MagickTrue);
   5804   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
   5805     nexus_info->region.x;
   5806   length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
   5807     sizeof(Quantum);
   5808   extent=length*nexus_info->region.height;
   5809   rows=nexus_info->region.height;
   5810   y=0;
   5811   p=nexus_info->pixels;
   5812   switch (cache_info->type)
   5813   {
   5814     case MemoryCache:
   5815     case MapCache:
   5816     {
   5817       register Quantum
   5818         *magick_restrict q;
   5819 
   5820       /*
   5821         Write pixels to memory.
   5822       */
   5823       if ((cache_info->columns == nexus_info->region.width) &&
   5824           (extent == (MagickSizeType) ((size_t) extent)))
   5825         {
   5826           length=extent;
   5827           rows=1UL;
   5828         }
   5829       q=cache_info->pixels+cache_info->number_channels*offset;
   5830       for (y=0; y < (ssize_t) rows; y++)
   5831       {
   5832         (void) memcpy(q,p,(size_t) length);
   5833         p+=cache_info->number_channels*nexus_info->region.width;
   5834         q+=cache_info->number_channels*cache_info->columns;
   5835       }
   5836       break;
   5837     }
   5838     case DiskCache:
   5839     {
   5840       /*
   5841         Write pixels to disk.
   5842       */
   5843       LockSemaphoreInfo(cache_info->file_semaphore);
   5844       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
   5845         {
   5846           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
   5847             cache_info->cache_filename);
   5848           UnlockSemaphoreInfo(cache_info->file_semaphore);
   5849           return(MagickFalse);
   5850         }
   5851       if ((cache_info->columns == nexus_info->region.width) &&
   5852           (extent <= MagickMaxBufferExtent))
   5853         {
   5854           length=extent;
   5855           rows=1UL;
   5856         }
   5857       for (y=0; y < (ssize_t) rows; y++)
   5858       {
   5859         count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
   5860           cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
   5861           p);
   5862         if (count != (MagickOffsetType) length)
   5863           break;
   5864         p+=cache_info->number_channels*nexus_info->region.width;
   5865         offset+=cache_info->columns;
   5866       }
   5867       if (IsFileDescriptorLimitExceeded() != MagickFalse)
   5868         (void) ClosePixelCacheOnDisk(cache_info);
   5869       UnlockSemaphoreInfo(cache_info->file_semaphore);
   5870       break;
   5871     }
   5872     case DistributedCache:
   5873     {
   5874       RectangleInfo
   5875         region;
   5876 
   5877       /*
   5878         Write pixels to distributed cache.
   5879       */
   5880       LockSemaphoreInfo(cache_info->file_semaphore);
   5881       region=nexus_info->region;
   5882       if ((cache_info->columns != nexus_info->region.width) ||
   5883           (extent > MagickMaxBufferExtent))
   5884         region.height=1UL;
   5885       else
   5886         {
   5887           length=extent;
   5888           rows=1UL;
   5889         }
   5890       for (y=0; y < (ssize_t) rows; y++)
   5891       {
   5892         count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
   5893           cache_info->server_info,&region,length,(const unsigned char *) p);
   5894         if (count != (MagickOffsetType) length)
   5895           break;
   5896         p+=cache_info->number_channels*nexus_info->region.width;
   5897         region.y++;
   5898       }
   5899       UnlockSemaphoreInfo(cache_info->file_semaphore);
   5900       break;
   5901     }
   5902     default:
   5903       break;
   5904   }
   5905   if (y < (ssize_t) rows)
   5906     {
   5907       ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
   5908         cache_info->cache_filename);
   5909       return(MagickFalse);
   5910     }
   5911   if ((cache_info->debug != MagickFalse) &&
   5912       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
   5913     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
   5914       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
   5915       nexus_info->region.width,(double) nexus_info->region.height,(double)
   5916       nexus_info->region.x,(double) nexus_info->region.y);
   5917   return(MagickTrue);
   5918 }
   5919