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