]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/cache.c
...
[imagemagick] / MagickCore / cache.c
index 9f61442f282c907c229a463d084e32b09adec4e5..0278817410915f1015dbb9971068b968cc541c72 100644 (file)
 %                                 July 1999                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
 %  obtain a copy of the License at                                            %
 %                                                                             %
-%    http://www.imagemagick.org/script/license.php                            %
+%    https://www.imagemagick.org/script/license.php                           %
 %                                                                             %
 %  Unless required by applicable law or agreed to in writing, software        %
 %  distributed under the License is distributed on an "AS IS" BASIS,          %
@@ -119,11 +119,16 @@ static MagickBooleanType
   GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
     const ssize_t,const ssize_t,Quantum *,ExceptionInfo *),
   OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
-  ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
-  ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
+  OpenPixelCacheOnDisk(CacheInfo *,const MapMode),
+  ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
+    ExceptionInfo *),
+  ReadPixelCacheMetacontent(CacheInfo *magick_restrict,
+    NexusInfo *magick_restrict,ExceptionInfo *),
   SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
-  WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
-  WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *);
+  WritePixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
+    ExceptionInfo *),
+  WritePixelCacheMetacontent(CacheInfo *,NexusInfo *magick_restrict,
+    ExceptionInfo *);
 
 static Quantum
   *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
@@ -133,6 +138,11 @@ static Quantum
   *SetPixelCacheNexusPixels(const CacheInfo *,const MapMode,
     const RectangleInfo *,NexusInfo *,ExceptionInfo *) magick_hot_spot;
 
+#if defined(MAGICKCORE_OPENCL_SUPPORT)
+static void
+  CopyOpenCLBuffer(CacheInfo *magick_restrict);
+#endif
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
@@ -145,6 +155,12 @@ static volatile MagickBooleanType
 
 static SemaphoreInfo
   *cache_semaphore = (SemaphoreInfo *) NULL;
+
+static ssize_t
+  cache_anonymous_memory = (-1);
+
+static time_t
+  cache_epoch = 0;
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -171,10 +187,10 @@ static SemaphoreInfo
 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   char
-    *synchronize;
+    *value;
 
   cache_info=(CacheInfo *) AcquireQuantumMemory(1,sizeof(*cache_info));
   if (cache_info == (CacheInfo *) NULL)
@@ -195,17 +211,23 @@ MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
   cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
   if (cache_info->nexus_info == (NexusInfo **) NULL)
     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
-  synchronize=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
-  if (synchronize != (const char *) NULL)
+  value=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
+  if (value != (const char *) NULL)
+    {
+      cache_info->synchronize=IsStringTrue(value);
+      value=DestroyString(value);
+    }
+  value=GetPolicyValue("cache:synchronize");
+  if (value != (const char *) NULL)
     {
-      cache_info->synchronize=IsStringTrue(synchronize);
-      synchronize=DestroyString(synchronize);
+      cache_info->synchronize=IsStringTrue(value);
+      value=DestroyString(value);
     }
   cache_info->semaphore=AcquireSemaphoreInfo();
   cache_info->reference_count=1;
   cache_info->file_semaphore=AcquireSemaphoreInfo();
   cache_info->debug=IsEventLogging();
-  cache_info->signature=MagickSignature;
+  cache_info->signature=MagickCoreSignature;
   return((Cache ) cache_info);
 }
 \f
@@ -234,7 +256,7 @@ MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
 {
   NexusInfo
-    **restrict nexus_info;
+    **magick_restrict nexus_info;
 
   register ssize_t
     i;
@@ -251,7 +273,7 @@ MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
   for (i=0; i < (ssize_t) number_threads; i++)
   {
     nexus_info[i]=(&nexus_info[0][i]);
-    nexus_info[i]->signature=MagickSignature;
+    nexus_info[i]->signature=MagickCoreSignature;
   }
   return(nexus_info);
 }
@@ -288,15 +310,15 @@ MagickPrivate const void *AcquirePixelCachePixels(const Image *image,
   MagickSizeType *length,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   *length=0;
   if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
     return((const void *) NULL);
@@ -382,14 +404,14 @@ MagickPrivate void CacheComponentTerminus(void)
 MagickPrivate Cache ClonePixelCache(const Cache cache)
 {
   CacheInfo
-    *restrict clone_info;
+    *magick_restrict clone_info;
 
   const CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(cache != NULL);
   cache_info=(const CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       cache_info->filename);
@@ -428,18 +450,18 @@ MagickPrivate Cache ClonePixelCache(const Cache cache)
 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
 {
   CacheInfo
-    *restrict cache_info,
-    *restrict source_info;
+    *magick_restrict cache_info,
+    *magick_restrict source_info;
 
   assert(clone != (Cache) NULL);
   source_info=(CacheInfo *) clone;
-  assert(source_info->signature == MagickSignature);
+  assert(source_info->signature == MagickCoreSignature);
   if (source_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       source_info->filename);
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   source_info->methods=cache_info->methods;
 }
 \f
@@ -452,7 +474,8 @@ MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
 %  ClonePixelCacheRepository() clones the source pixel cache to the destination
 %  cache.
 %
@@ -471,21 +494,62 @@ MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
 %
 */
 
-static inline MagickSizeType MagickMin(const MagickSizeType x,
-  const MagickSizeType y)
+static MagickBooleanType ClonePixelCacheOnDisk(
+  CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
 {
-  if (x < y)
-    return(x);
-  return(y);
+  MagickSizeType
+    extent;
+
+  size_t
+    quantum;
+
+  ssize_t
+    count;
+
+  struct stat
+    file_stats;
+
+  unsigned char
+    *buffer;
+
+  /*
+    Clone pixel cache on disk with identical morphology.
+  */
+  if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
+      (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
+    return(MagickFalse);
+  quantum=(size_t) MagickMaxBufferExtent;
+  if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
+    quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
+  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
+  if (buffer == (unsigned char *) NULL)
+    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+  extent=0;
+  while ((count=read(cache_info->file,buffer,quantum)) > 0)
+  {
+    ssize_t
+      number_bytes;
+
+    number_bytes=write(clone_info->file,buffer,(size_t) count);
+    if (number_bytes != count)
+      break;
+    extent+=number_bytes;
+  }
+  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
+  if (extent != cache_info->length)
+    return(MagickFalse);
+  return(MagickTrue);
 }
 
 static MagickBooleanType ClonePixelCacheRepository(
-  CacheInfo *restrict clone_info,CacheInfo *restrict cache_info,
+  CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
   ExceptionInfo *exception)
 {
 #define MaxCacheThreads  2
-#define cache_threads(source,destination,chunk) \
-  num_threads((chunk) < (16*GetMagickResourceLimit(ThreadResource)) ? 1 : \
+#define cache_threads(source,destination) \
+  num_threads(((source)->type == DiskCache) || \
+    ((destination)->type == DiskCache) || (((source)->rows) < \
+    (16*GetMagickResourceLimit(ThreadResource))) ? 1 : \
     GetMagickResourceLimit(ThreadResource) < MaxCacheThreads ? \
     GetMagickResourceLimit(ThreadResource) : MaxCacheThreads)
 
@@ -494,8 +558,8 @@ static MagickBooleanType ClonePixelCacheRepository(
     status;
 
   NexusInfo
-    **restrict cache_nexus,
-    **restrict clone_nexus;
+    **magick_restrict cache_nexus,
+    **magick_restrict clone_nexus;
 
   size_t
     length;
@@ -509,23 +573,32 @@ static MagickBooleanType ClonePixelCacheRepository(
   if (cache_info->type == PingCache)
     return(MagickTrue);
   length=cache_info->number_channels*sizeof(*cache_info->channel_map);
-  if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
-      ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)) &&
-      (cache_info->columns == clone_info->columns) &&
+  if ((cache_info->columns == clone_info->columns) &&
       (cache_info->rows == clone_info->rows) &&
       (cache_info->number_channels == clone_info->number_channels) &&
       (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
       (cache_info->metacontent_extent == clone_info->metacontent_extent))
     {
-      (void) memcpy(clone_info->pixels,cache_info->pixels,cache_info->columns*
-        cache_info->number_channels*cache_info->rows*
-        sizeof(*cache_info->pixels));
-      if ((cache_info->metacontent_extent != 0) &&
-          (clone_info->metacontent_extent != 0))
-        (void) memcpy(clone_info->metacontent,cache_info->metacontent,
-          cache_info->columns*cache_info->rows*clone_info->metacontent_extent*
-          sizeof(unsigned char));
-      return(MagickTrue);
+      /*
+        Identical pixel cache morphology.
+      */
+      if (((cache_info->type == MemoryCache) ||
+           (cache_info->type == MapCache)) &&
+          ((clone_info->type == MemoryCache) ||
+           (clone_info->type == MapCache)))
+        {
+          (void) memcpy(clone_info->pixels,cache_info->pixels,
+            cache_info->columns*cache_info->number_channels*cache_info->rows*
+            sizeof(*cache_info->pixels));
+          if ((cache_info->metacontent_extent != 0) &&
+              (clone_info->metacontent_extent != 0))
+            (void) memcpy(clone_info->metacontent,cache_info->metacontent,
+              cache_info->columns*cache_info->rows*
+              clone_info->metacontent_extent*sizeof(unsigned char));
+          return(MagickTrue);
+        }
+      if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
+        return(ClonePixelCacheOnDisk(cache_info,clone_info));
     }
   /*
     Mismatched pixel cache morphology.
@@ -544,7 +617,7 @@ static MagickBooleanType ClonePixelCacheRepository(
   status=MagickTrue;
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4) shared(status) \
-    cache_threads(cache_info,clone_info,cache_info->rows)
+    cache_threads(cache_info,clone_info)
 #endif
   for (y=0; y < (ssize_t) cache_info->rows; y++)
   {
@@ -568,8 +641,8 @@ static MagickBooleanType ClonePixelCacheRepository(
     region.height=1;
     region.x=0;
     region.y=y;
-    pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,cache_nexus[id],
-      exception);
+    pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,
+      cache_nexus[id],exception);
     if (pixels == (Quantum *) NULL)
       continue;
     status=ReadPixelCachePixels(cache_info,cache_nexus[id],exception);
@@ -588,10 +661,10 @@ static MagickBooleanType ClonePixelCacheRepository(
     else
       {
         register const Quantum
-          *restrict p;
+          *magick_restrict p;
 
         register Quantum
-          *restrict q;
+          *magick_restrict q;
 
         /*
           Mismatched pixel channel map.
@@ -616,8 +689,7 @@ static MagickBooleanType ClonePixelCacheRepository(
             channel=clone_info->channel_map[i].channel;
             traits=cache_info->channel_map[channel].traits;
             if (traits != UndefinedPixelTrait)
-              (void) memcpy(q,p+cache_info->channel_map[channel].offset,
-                sizeof(Quantum));
+              *q=*(p+cache_info->channel_map[channel].offset);
             q++;
           }
           p+=cache_info->number_channels;
@@ -635,7 +707,7 @@ static MagickBooleanType ClonePixelCacheRepository(
         clone_info->metacontent_extent);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
       #pragma omp parallel for schedule(static,4) shared(status) \
-        cache_threads(cache_info,clone_info,cache_info->rows)
+        cache_threads(cache_info,clone_info)
 #endif
       for (y=0; y < (ssize_t) cache_info->rows; y++)
       {
@@ -680,9 +752,9 @@ static MagickBooleanType ClonePixelCacheRepository(
   if (cache_info->debug != MagickFalse)
     {
       char
-        message[MaxTextExtent];
+        message[MagickPathExtent];
 
-      (void) FormatLocaleString(message,MaxTextExtent,"%s => %s",
+      (void) FormatLocaleString(message,MagickPathExtent,"%s => %s",
         CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
         CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
@@ -715,7 +787,7 @@ static MagickBooleanType ClonePixelCacheRepository(
 static void DestroyImagePixelCache(Image *image)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (image->cache == (void *) NULL)
@@ -748,15 +820,15 @@ static void DestroyImagePixelCache(Image *image)
 MagickExport void DestroyImagePixels(Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
     {
       cache_info->methods.destroy_pixel_handler(image);
@@ -809,14 +881,20 @@ static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
   {
     case MemoryCache:
     {
+#if defined(MAGICKCORE_OPENCL_SUPPORT)
+      if (cache_info->opencl != (MagickCLCacheInfo) NULL)
+        {
+          cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
+            MagickTrue);
+          cache_info->pixels=(Quantum *) NULL;
+          break;
+        }
+#endif
       if (cache_info->mapped == MagickFalse)
         cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
           cache_info->pixels);
       else
-        {
-          (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
-          cache_info->pixels=(Quantum *) NULL;
-        }
+        (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
       RelinquishMagickResource(MemoryResource,cache_info->length);
       break;
     }
@@ -824,7 +902,7 @@ static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
     {
       (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
       cache_info->pixels=(Quantum *) NULL;
-      if (cache_info->mode != ReadMode)
+      if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
         (void) RelinquishUniqueFileResource(cache_info->cache_filename);
       *cache_info->cache_filename='\0';
       RelinquishMagickResource(MapResource,cache_info->length);
@@ -833,7 +911,7 @@ static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
     {
       if (cache_info->file != -1)
         (void) ClosePixelCacheOnDisk(cache_info);
-      if (cache_info->mode != ReadMode)
+      if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
         (void) RelinquishUniqueFileResource(cache_info->cache_filename);
       *cache_info->cache_filename='\0';
       RelinquishMagickResource(DiskResource,cache_info->length);
@@ -857,11 +935,11 @@ static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
 MagickPrivate Cache DestroyPixelCache(Cache cache)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       cache_info->filename);
@@ -876,9 +954,9 @@ MagickPrivate Cache DestroyPixelCache(Cache cache)
   if (cache_info->debug != MagickFalse)
     {
       char
-        message[MaxTextExtent];
+        message[MagickPathExtent];
 
-      (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
+      (void) FormatLocaleString(message,MagickPathExtent,"destroy %s",
         cache_info->filename);
       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
     }
@@ -895,7 +973,7 @@ MagickPrivate Cache DestroyPixelCache(Cache cache)
     RelinquishSemaphoreInfo(&cache_info->file_semaphore);
   if (cache_info->semaphore != (SemaphoreInfo *) NULL)
     RelinquishSemaphoreInfo(&cache_info->semaphore);
-  cache_info->signature=(~MagickSignature);
+  cache_info->signature=(~MagickCoreSignature);
   cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
   cache=(Cache) NULL;
   return(cache);
@@ -951,7 +1029,7 @@ MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
   {
     if (nexus_info[i]->cache != (Quantum *) NULL)
       RelinquishCacheNexusPixels(nexus_info[i]);
-    nexus_info[i]->signature=(~MagickSignature);
+    nexus_info[i]->signature=(~MagickCoreSignature);
   }
   nexus_info[0]=(NexusInfo *) RelinquishMagickMemory(nexus_info[0]);
   nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
@@ -985,16 +1063,16 @@ MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
 MagickExport void *GetAuthenticMetacontent(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->methods.get_authentic_metacontent_from_handler !=
       (GetAuthenticMetacontentFromHandler) NULL)
     {
@@ -1036,19 +1114,80 @@ MagickExport void *GetAuthenticMetacontent(const Image *image)
 static void *GetAuthenticMetacontentFromCache(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   return(cache_info->nexus_info[id]->metacontent);
 }
+
+#if defined(MAGICKCORE_OPENCL_SUPPORT)
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   G e t A u t h e n t i c O p e n C L B u f f e r                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetAuthenticOpenCLBuffer() returns an OpenCL buffer used to execute OpenCL
+%  operations.
+%
+%  The format of the GetAuthenticOpenCLBuffer() method is:
+%
+%      cl_mem GetAuthenticOpenCLBuffer(const Image *image,
+%        MagickCLDevice device,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o device: the device to use.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickPrivate cl_mem GetAuthenticOpenCLBuffer(const Image *image,
+  MagickCLDevice device,ExceptionInfo *exception)
+{
+  CacheInfo
+    *magick_restrict cache_info;
+
+  cl_int
+    status;
+
+  assert(image != (const Image *) NULL);
+  assert(device != (const MagickCLDevice) NULL);
+  cache_info=(CacheInfo *) image->cache;
+  if (cache_info->type == UndefinedCache)
+    SyncImagePixelCache((Image *) image,exception);
+  if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
+    return((cl_mem) NULL);
+  if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
+      (cache_info->opencl->device->context != device->context))
+    cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
+  if (cache_info->opencl == (MagickCLCacheInfo) NULL)
+    {
+      assert(cache_info->pixels != (Quantum *) NULL);
+      cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
+        cache_info->length);
+      if (cache_info->opencl == (MagickCLCacheInfo) NULL)
+        return((cl_mem) NULL);
+    }
+  assert(cache_info->opencl->pixels == cache_info->pixels);
+  return(cache_info->opencl->buffer);
+}
+#endif
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1090,22 +1229,22 @@ MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   Quantum
-    *restrict pixels;
+    *magick_restrict pixels;
 
   /*
     Transfer pixels from the cache.
   */
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
     nexus_info,exception);
   if (pixels == (Quantum *) NULL)
     return((Quantum *) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (nexus_info->authentic_pixel_cache != MagickFalse)
     return(pixels);
   if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
@@ -1142,16 +1281,16 @@ MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   return(cache_info->nexus_info[id]->pixels);
 }
@@ -1183,16 +1322,16 @@ static Quantum *GetAuthenticPixelsFromCache(const Image *image)
 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->methods.get_authentic_pixels_from_handler !=
        (GetAuthenticPixelsFromHandler) NULL)
     return(cache_info->methods.get_authentic_pixels_from_handler(image));
@@ -1208,7 +1347,8 @@ MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
 %   G e t A u t h e n t i c P i x e l s                                       %
 %                                                                             %
 %                                                                             %
-%                                                                             % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  GetAuthenticPixels() obtains a pixel region for read/write access. If the
 %  region is successfully accessed, a pointer to a Quantum array
@@ -1249,7 +1389,7 @@ MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1258,10 +1398,10 @@ MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
     *pixels;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->methods.get_authentic_pixels_handler !=
       (GetAuthenticPixelsHandler) NULL)
     {
@@ -1311,21 +1451,21 @@ static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   Quantum
-    *restrict pixels;
+    *magick_restrict pixels;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
   if (cache_info == (Cache) NULL)
     return((Quantum *) NULL);
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
     cache_info->nexus_info[id],exception);
@@ -1358,18 +1498,18 @@ static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
 MagickExport MagickSizeType GetImageExtent(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
 }
@@ -1405,14 +1545,14 @@ MagickExport MagickSizeType GetImageExtent(const Image *image)
 */
 
 static inline MagickBooleanType ValidatePixelCacheMorphology(
-  const Image *restrict image)
+  const Image *magick_restrict image)
 {
   const CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const PixelChannelMap
-    *restrict p,
-    *restrict q;
+    *magick_restrict p,
+    *magick_restrict q;
 
   /*
     Does the image match the pixel cache morphology?
@@ -1439,44 +1579,44 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   MagickBooleanType
     destroy,
     status;
 
   static MagickSizeType
-    cpu_throttle = 0,
-    cycles = 0,
-    time_limit = 0;
-
-  static time_t
-    cache_timestamp = 0;
+    cache_timelimit = MagickResourceInfinity,
+    cpu_throttle = MagickResourceInfinity,
+    cycles = 0;
 
   status=MagickTrue;
-  LockSemaphoreInfo(image->semaphore);
-  if (cpu_throttle == 0)
+  if (cpu_throttle == MagickResourceInfinity)
     cpu_throttle=GetMagickResourceLimit(ThrottleResource);
   if ((cpu_throttle != 0) && ((cycles++ % 32) == 0))
     MagickDelay(cpu_throttle);
-  if (time_limit == 0)
+  if (cache_epoch == 0)
     {
       /*
         Set the expire time in seconds.
       */
-      time_limit=GetMagickResourceLimit(TimeResource);
-      cache_timestamp=time((time_t *) NULL);
+      cache_timelimit=GetMagickResourceLimit(TimeResource);
+      cache_epoch=time((time_t *) NULL);
     }
-  if ((time_limit != MagickResourceInfinity) &&
-      ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
-     {
+  if ((cache_timelimit != MagickResourceInfinity) &&
+      ((MagickSizeType) (time((time_t *) NULL)-cache_epoch) >= cache_timelimit))
+    {
 #if defined(ECANCELED)
-       errno=ECANCELED;
+      errno=ECANCELED;
 #endif
-       ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
-     }
+      ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
+    }
+  LockSemaphoreInfo(image->semaphore);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
+#if defined(MAGICKCORE_OPENCL_SUPPORT)
+  CopyOpenCLBuffer(cache_info);
+#endif
   destroy=MagickFalse;
   if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
     {
@@ -1563,13 +1703,13 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
 MagickExport CacheType GetImagePixelCacheType(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   return(cache_info->type);
 }
 \f
@@ -1603,44 +1743,55 @@ MagickExport CacheType GetImagePixelCacheType(const Image *image)
 %    o exception: return any errors or warnings in this structure.
 %
 */
+
+static inline MagickBooleanType CopyPixel(const Image *image,
+  const Quantum *source,Quantum *destination)
+{
+  register ssize_t
+    i;
+
+  if (source == (const Quantum *) NULL)
+    {
+      destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
+      destination[GreenPixelChannel]=ClampToQuantum(
+        image->background_color.green);
+      destination[BluePixelChannel]=ClampToQuantum(
+        image->background_color.blue);
+      destination[BlackPixelChannel]=ClampToQuantum(
+        image->background_color.black);
+      destination[AlphaPixelChannel]=ClampToQuantum(
+        image->background_color.alpha);
+      return(MagickFalse);
+    }
+  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+  {
+    PixelChannel channel = GetPixelChannelChannel(image,i);
+    destination[channel]=source[i];
+  }
+  return(MagickTrue);
+}
+
 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   register Quantum
-    *restrict q;
-
-  register ssize_t
-    i;
+    *magick_restrict q;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
   if (cache_info->methods.get_one_authentic_pixel_from_handler !=
        (GetOneAuthenticPixelFromHandler) NULL)
     return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
       pixel,exception));
   q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
-  if (q == (Quantum *) NULL)
-    {
-      pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
-      pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
-      pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
-      pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
-      pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
-      return(MagickFalse);
-    }
-  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-  {
-    PixelChannel channel=GetPixelChannelChannel(image,i);
-    pixel[channel]=q[i];
-  }
-  return(MagickTrue);
+  return(CopyPixel(image,q,pixel));
 }
 \f
 /*
@@ -1678,41 +1829,24 @@ static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   register Quantum
-    *restrict q;
-
-  register ssize_t
-    i;
+    *magick_restrict q;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
   q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
     exception);
-  if (q == (Quantum *) NULL)
-    {
-      pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
-      pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
-      pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
-      pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
-      pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
-      return(MagickFalse);
-    }
-  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-  {
-    PixelChannel channel=GetPixelChannelChannel(image,i);
-    pixel[channel]=q[i];
-  }
-  return(MagickTrue);
+  return(CopyPixel(image,q,pixel));
 }
 \f
 /*
@@ -1750,7 +1884,7 @@ MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1758,14 +1892,11 @@ MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
   const Quantum
     *p;
 
-  register ssize_t
-    i;
-
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
   if (cache_info->methods.get_one_virtual_pixel_from_handler !=
        (GetOneVirtualPixelFromHandler) NULL)
@@ -1774,21 +1905,7 @@ MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
   assert(id < (int) cache_info->number_threads);
   p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
     1UL,1UL,cache_info->nexus_info[id],exception);
-  if (p == (const Quantum *) NULL)
-    {
-      pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
-      pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
-      pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
-      pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
-      pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
-      return(MagickFalse);
-    }
-  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-  {
-    PixelChannel channel=GetPixelChannelChannel(image,i);
-    pixel[channel]=p[i];
-  }
-  return(MagickTrue);
+  return(CopyPixel(image,p,pixel));
 }
 \f
 /*
@@ -1830,7 +1947,7 @@ static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
   Quantum *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1838,33 +1955,16 @@ static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
   const Quantum
     *p;
 
-  register ssize_t
-    i;
-
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
   p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
     cache_info->nexus_info[id],exception);
-  if (p == (const Quantum *) NULL)
-    {
-      pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
-      pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
-      pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
-      pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
-      pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
-      return(MagickFalse);
-    }
-  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-  {
-    PixelChannel channel=GetPixelChannelChannel(image,i);
-    pixel[channel]=p[i];
-  }
-  return(MagickTrue);
+  return(CopyPixel(image,p,pixel));
 }
 \f
 /*
@@ -1906,19 +2006,19 @@ MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
   PixelInfo *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   register const Quantum
-    *restrict p;
+    *magick_restrict p;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   GetPixelInfo(image,pixel);
   p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
@@ -1954,11 +2054,11 @@ MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       cache_info->filename);
@@ -1970,6 +2070,42 @@ MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   G e t P i x e l C a c h e F i l e n a m e                                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetPixelCacheFilename() returns the filename associated with the pixel
+%  cache.
+%
+%  The format of the GetPixelCacheFilename() method is:
+%
+%      const char *GetPixelCacheFilename(const Image *image)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+*/
+MagickExport const char *GetPixelCacheFilename(const Image *image)
+{
+  CacheInfo
+    *magick_restrict cache_info;
+
+  assert(image != (const Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  assert(image->cache != (Cache) NULL);
+  cache_info=(CacheInfo *) image->cache;
+  assert(cache_info->signature == MagickCoreSignature);
+  return(cache_info->cache_filename);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +   G e t P i x e l C a c h e M e t h o d s                                   %
 %                                                                             %
 %                                                                             %
@@ -2033,17 +2169,17 @@ MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
 %
 */
 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
-  NexusInfo *restrict nexus_info)
+  NexusInfo *magick_restrict nexus_info)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   MagickSizeType
     extent;
 
   assert(cache != NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
   if (extent == 0)
     return((MagickSizeType) cache_info->columns*cache_info->rows);
@@ -2077,24 +2213,23 @@ MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
 %    o exception: return any errors or warnings in this structure.
 %
 */
-MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
+MagickExport void *GetPixelCachePixels(Image *image,MagickSizeType *length,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   assert(length != (MagickSizeType *) NULL);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
-  *length=0;
+  assert(cache_info->signature == MagickCoreSignature);
+  *length=cache_info->length;
   if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
     return((void *) NULL);
-  *length=cache_info->length;
   return((void *) cache_info->pixels);
 }
 \f
@@ -2125,11 +2260,11 @@ MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       cache_info->filename);
@@ -2158,23 +2293,23 @@ MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
 %
 %    o image: the image.
 %
-%    o width: the optimize cache tile width in pixels.
+%    o width: the optimized cache tile width in pixels.
 %
-%    o height: the optimize cache tile height in pixels.
+%    o height: the optimized cache tile height in pixels.
 %
 */
 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
   size_t *height)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
   if (GetImagePixelCacheType(image) == DiskCache)
     *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
@@ -2208,13 +2343,13 @@ MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   return(cache_info->virtual_pixel_method);
 }
 \f
@@ -2244,19 +2379,19 @@ MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
 static const void *GetVirtualMetacontentFromCache(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   const void
-    *restrict metacontent;
+    *magick_restrict metacontent;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   metacontent=GetVirtualMetacontentFromNexus(cache_info,
     cache_info->nexus_info[id]);
@@ -2290,14 +2425,14 @@ static const void *GetVirtualMetacontentFromCache(const Image *image)
 %
 */
 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
-  NexusInfo *restrict nexus_info)
+  NexusInfo *magick_restrict nexus_info)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->storage_class == UndefinedClass)
     return((void *) NULL);
   return(nexus_info->metacontent);
@@ -2330,19 +2465,19 @@ MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
 MagickExport const void *GetVirtualMetacontent(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   const void
-    *restrict metacontent;
+    *magick_restrict metacontent;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   metacontent=cache_info->methods.get_virtual_metacontent_from_handler(image);
   if (metacontent != (void *) NULL)
     return(metacontent);
@@ -2482,7 +2617,7 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   MagickOffsetType
     offset;
@@ -2492,47 +2627,50 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
     number_pixels;
 
   NexusInfo
-    **restrict virtual_nexus;
+    **magick_restrict virtual_nexus;
 
   Quantum
-    *restrict pixels,
+    *magick_restrict pixels,
     virtual_pixel[MaxPixelChannels];
 
   RectangleInfo
     region;
 
   register const Quantum
-    *restrict p;
+    *magick_restrict p;
 
   register const void
-    *restrict r;
+    *magick_restrict r;
 
   register Quantum
-    *restrict q;
+    *magick_restrict q;
 
   register ssize_t
     i,
     u;
 
   register unsigned char
-    *restrict s;
+    *magick_restrict s;
 
   ssize_t
     v;
 
   void
-    *restrict virtual_metacontent;
+    *magick_restrict virtual_metacontent;
 
   /*
     Acquire pixels.
   */
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->type == UndefinedCache)
     return((const Quantum *) NULL);
+#if defined(MAGICKCORE_OPENCL_SUPPORT)
+  CopyOpenCLBuffer(cache_info);
+#endif
   region.x=x;
   region.y=y;
   region.width=columns;
@@ -2577,8 +2715,6 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
   virtual_nexus=AcquirePixelCacheNexus(1);
   if (virtual_nexus == (NexusInfo **) NULL)
     {
-      if (virtual_nexus != (NexusInfo **) NULL)
-        virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
         "UnableToGetCacheNexus","`%s'",image->filename);
       return((const Quantum *) NULL);
@@ -2621,7 +2757,7 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
         case BlackVirtualPixelMethod:
         {
           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
-            SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
+            SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
           break;
         }
@@ -2636,7 +2772,7 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
         case TransparentVirtualPixelMethod:
         {
           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
-            SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
+            SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
           SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
           break;
         }
@@ -2860,6 +2996,8 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
           s+=length*cache_info->metacontent_extent;
         }
     }
+    if (u < (ssize_t) columns)
+      break;
   }
   /*
     Free resources.
@@ -2867,6 +3005,8 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
   if (virtual_metacontent != (void *) NULL)
     virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
   virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
+  if (v < (ssize_t) rows)
+    return((const Quantum *) NULL);
   return(pixels);
 }
 \f
@@ -2909,19 +3049,19 @@ static const Quantum *GetVirtualPixelCache(const Image *image,
   const size_t columns,const size_t rows,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   const Quantum
-    *restrict p;
+    *magick_restrict p;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
     cache_info->nexus_info[id],exception);
@@ -2954,16 +3094,16 @@ static const Quantum *GetVirtualPixelCache(const Image *image,
 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->methods.get_virtual_pixels_handler !=
        (GetVirtualPixelsHandler) NULL)
     return(cache_info->methods.get_virtual_pixels_handler(image));
@@ -3024,19 +3164,19 @@ MagickExport const Quantum *GetVirtualPixels(const Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   const Quantum
-    *restrict p;
+    *magick_restrict p;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->methods.get_virtual_pixel_handler !=
        (GetVirtualPixelHandler) NULL)
     return(cache_info->methods.get_virtual_pixel_handler(image,
@@ -3073,16 +3213,16 @@ MagickExport const Quantum *GetVirtualPixels(const Image *image,
 static const Quantum *GetVirtualPixelsCache(const Image *image)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
 }
@@ -3114,14 +3254,14 @@ static const Quantum *GetVirtualPixelsCache(const Image *image)
 %
 */
 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
-  NexusInfo *restrict nexus_info)
+  NexusInfo *magick_restrict nexus_info)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->storage_class == UndefinedClass)
     return((Quantum *) NULL);
   return((const Quantum *) nexus_info->pixels);
@@ -3158,19 +3298,6 @@ MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
 %
 */
 
-static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
-{
-  cache_info->mapped=MagickFalse;
-  cache_info->pixels=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
-    (size_t) cache_info->length));
-  if (cache_info->pixels == (Quantum *) NULL)
-    {
-      cache_info->mapped=MagickTrue;
-      cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
-        cache_info->length);
-    }
-}
-
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
@@ -3195,8 +3322,8 @@ static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
   /*
     Open pixel cache on disk.
   */
-  if (cache_info->file != -1)
-    return(MagickTrue);  /* cache already open */
+  if ((cache_info->file != -1) && (cache_info->mode == mode))
+    return(MagickTrue);  /* cache already open and in the proper mode */
   if (*cache_info->cache_filename == '\0')
     file=AcquireUniqueFileResource(cache_info->cache_filename);
   else
@@ -3228,14 +3355,15 @@ static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
   if (file == -1)
     return(MagickFalse);
   (void) AcquireMagickResource(FileResource,1);
+  if (cache_info->file != -1)
+    (void) ClosePixelCacheOnDisk(cache_info);
   cache_info->file=file;
-  cache_info->mode=mode;
   return(MagickTrue);
 }
 
 static inline MagickOffsetType WritePixelCacheRegion(
-  const CacheInfo *restrict cache_info,const MagickOffsetType offset,
-  const MagickSizeType length,const unsigned char *restrict buffer)
+  const CacheInfo *magick_restrict cache_info,const MagickOffsetType offset,
+  const MagickSizeType length,const unsigned char *magick_restrict buffer)
 {
   register MagickOffsetType
     i;
@@ -3251,11 +3379,11 @@ static inline MagickOffsetType WritePixelCacheRegion(
   for (i=0; i < (MagickOffsetType) length; i+=count)
   {
 #if !defined(MAGICKCORE_HAVE_PWRITE)
-    count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
-      (MagickSizeType) SSIZE_MAX));
+    count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
+      SSIZE_MAX));
 #else
-    count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
-      (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
+    count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
+      SSIZE_MAX),(off_t) (offset+i));
 #endif
     if (count <= 0)
       {
@@ -3270,7 +3398,7 @@ static inline MagickOffsetType WritePixelCacheRegion(
 static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   MagickOffsetType
     count,
@@ -3281,11 +3409,11 @@ static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
   if (image->debug != MagickFalse)
     {
       char
-        format[MaxTextExtent],
-        message[MaxTextExtent];
+        format[MagickPathExtent],
+        message[MagickPathExtent];
 
-      (void) FormatMagickSize(length,MagickFalse,format);
-      (void) FormatLocaleString(message,MaxTextExtent,
+      (void) FormatMagickSize(length,MagickFalse,"B",MagickPathExtent,format);
+      (void) FormatLocaleString(message,MagickPathExtent,
         "extend %s (%s[%d], disk, %s)",cache_info->filename,
         cache_info->cache_filename,cache_info->file,format);
       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
@@ -3296,29 +3424,38 @@ static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
   if (offset < 0)
     return(MagickFalse);
   if ((MagickSizeType) offset >= length)
-    return(MagickTrue);
-  extent=(MagickOffsetType) length-1;
-  count=WritePixelCacheRegion(cache_info,extent,1,(const unsigned char *) "");
+    count=(MagickOffsetType) 1;
+  else
+    {
+      extent=(MagickOffsetType) length-1;
+      count=WritePixelCacheRegion(cache_info,extent,1,(const unsigned char *)
+        "");
+      if (count != 1)
+        return(MagickFalse);
 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
-  if (cache_info->synchronize != MagickFalse)
-    (void) posix_fallocate(cache_info->file,offset+1,extent-offset);
+      if (cache_info->synchronize != MagickFalse)
+        (void) posix_fallocate(cache_info->file,offset+1,extent-offset);
 #endif
 #if defined(SIGBUS)
-  (void) signal(SIGBUS,CacheSignalHandler);
+      (void) signal(SIGBUS,CacheSignalHandler);
 #endif
-  return(count != (MagickOffsetType) 1 ? MagickFalse : MagickTrue);
+    }
+  offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
+  if (offset < 0)
+    return(MagickFalse);
+  return(MagickTrue);
 }
 
 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info,
+    *magick_restrict cache_info,
     source_info;
 
   char
-    format[MaxTextExtent],
-    message[MaxTextExtent];
+    format[MagickPathExtent],
+    message[MagickPathExtent];
 
   const char
     *type;
@@ -3335,17 +3472,45 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
     packet_size;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  if (cache_anonymous_memory < 0)
+    {
+      char
+        *value;
+
+      /*
+        Does the security policy require anonymous mapping for pixel cache?
+      */
+      cache_anonymous_memory=0;
+      value=GetPolicyValue("pixel-cache-memory");
+      if (value == (char *) NULL)
+        value=GetPolicyValue("cache:memory-map");
+      if (LocaleCompare(value,"anonymous") == 0)
+        {
+#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
+          cache_anonymous_memory=1;
+#else
+          (void) ThrowMagickException(exception,GetMagickModule(),
+            MissingDelegateError,"DelegateLibrarySupportNotBuiltIn",
+            "'%s' (policy requires anonymous memory mapping)",image->filename);
+#endif
+        }
+      value=DestroyString(value);
+    }
   if ((image->columns == 0) || (image->rows == 0))
     ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
+  if ((AcquireMagickResource(WidthResource,image->columns) == MagickFalse) ||
+      (AcquireMagickResource(HeightResource,image->rows) == MagickFalse))
+    ThrowBinaryException(ImageError,"WidthOrHeightExceedsLimit",
+      image->filename);
   source_info=(*cache_info);
   source_info.file=(-1);
-  (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
+  (void) FormatLocaleString(cache_info->filename,MagickPathExtent,"%s[%.20g]",
     image->filename,(double) GetImageIndexInList(image));
   cache_info->storage_class=image->storage_class;
   cache_info->colorspace=image->colorspace;
@@ -3360,14 +3525,6 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
     sizeof(*image->channel_map));
   cache_info->metacontent_extent=image->metacontent_extent;
   cache_info->mode=mode;
-  if (image->ping != MagickFalse)
-    {
-      cache_info->type=PingCache;
-      cache_info->pixels=(Quantum *) NULL;
-      cache_info->metacontent=(void *) NULL;
-      cache_info->length=0;
-      return(MagickTrue);
-    }
   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
   packet_size=cache_info->number_channels*sizeof(Quantum);
   if (image->metacontent_extent != 0)
@@ -3379,7 +3536,16 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
     ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
       image->filename);
   cache_info->length=length;
+  if (image->ping != MagickFalse)
+    {
+      cache_info->storage_class=image->storage_class;
+      cache_info->colorspace=image->colorspace;
+      cache_info->type=PingCache;
+      return(MagickTrue);
+    }
   status=AcquireMagickResource(AreaResource,cache_info->length);
+  if (cache_info->mode == PersistMode)
+    status=MagickFalse;
   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
     cache_info->metacontent_extent);
   if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
@@ -3388,7 +3554,19 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
       if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
           (cache_info->type == MemoryCache))
         {
-          AllocatePixelCachePixels(cache_info);
+          status=MagickTrue;
+          if (cache_anonymous_memory <= 0)
+            {
+              cache_info->mapped=MagickFalse;
+              cache_info->pixels=(Quantum *) MagickAssumeAligned(
+                AcquireAlignedMemory(1,(size_t) cache_info->length));
+            }
+          else
+            {
+              cache_info->mapped=MagickTrue;
+              cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
+                cache_info->length);
+            }
           if (cache_info->pixels == (Quantum *) NULL)
             cache_info->pixels=source_info.pixels;
           else
@@ -3396,7 +3574,6 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
               /*
                 Create memory pixel cache.
               */
-              status=MagickTrue;
               cache_info->type=MemoryCache;
               cache_info->metacontent=(void *) NULL;
               if (cache_info->metacontent_extent != 0)
@@ -3411,10 +3588,11 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
                 }
               if (image->debug != MagickFalse)
                 {
-                  (void) FormatMagickSize(cache_info->length,MagickTrue,format);
+                  (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
+                    MagickPathExtent,format);
                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
                     cache_info->type);
-                  (void) FormatLocaleString(message,MaxTextExtent,
+                  (void) FormatLocaleString(message,MagickPathExtent,
                     "open %s (%s %s, %.20gx%.20gx%.20g %s)",
                     cache_info->filename,cache_info->mapped != MagickFalse ?
                     "Anonymous" : "Heap",type,(double) cache_info->columns,
@@ -3423,7 +3601,7 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
                     message);
                 }
-              return(status);
+              return(status == 0 ? MagickFalse : MagickTrue);
             }
         }
       RelinquishMagickResource(MemoryResource,cache_info->length);
@@ -3454,10 +3632,11 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
               /*
                 Create a distributed pixel cache.
               */
+              status=MagickTrue;
               cache_info->type=DistributedCache;
               cache_info->server_info=server_info;
               (void) FormatLocaleString(cache_info->cache_filename,
-                MaxTextExtent,"%s:%d",GetDistributeCacheHostname(
+                MagickPathExtent,"%s:%d",GetDistributeCacheHostname(
                 (DistributeCacheInfo *) cache_info->server_info),
                 GetDistributeCachePort((DistributeCacheInfo *)
                 cache_info->server_info));
@@ -3470,11 +3649,11 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
                 }
               if (image->debug != MagickFalse)
                 {
-                  (void) FormatMagickSize(cache_info->length,MagickFalse,
-                    format);
+                  (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
+                    MagickPathExtent,format);
                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
                     cache_info->type);
-                  (void) FormatLocaleString(message,MaxTextExtent,
+                  (void) FormatLocaleString(message,MagickPathExtent,
                     "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
                     cache_info->filename,cache_info->cache_filename,
                     GetDistributeCacheFile((DistributeCacheInfo *)
@@ -3484,7 +3663,7 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
                     message);
                 }
-              return(MagickTrue);
+              return(status == 0 ? MagickFalse : MagickTrue);
             }
         }
       RelinquishMagickResource(DiskResource,cache_info->length);
@@ -3492,7 +3671,8 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
         "CacheResourcesExhausted","`%s'",image->filename);
       return(MagickFalse);
     }
-  if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
+  if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
+      (cache_info->mode != PersistMode))
     {
       (void) ClosePixelCacheOnDisk(cache_info);
       *cache_info->cache_filename='\0';
@@ -3521,9 +3701,13 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
       status=AcquireMagickResource(MapResource,cache_info->length);
       if ((status == MagickFalse) && (cache_info->type != MapCache) &&
           (cache_info->type != MemoryCache))
-        cache_info->type=DiskCache;
+        {
+          status=MagickTrue;
+          cache_info->type=DiskCache;
+        }
       else
         {
+          status=MagickTrue;
           cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
             cache_info->offset,(size_t) cache_info->length);
           if (cache_info->pixels == (Quantum *) NULL)
@@ -3536,7 +3720,6 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
               /*
                 Create file-backed memory-mapped pixel cache.
               */
-              status=MagickTrue;
               (void) ClosePixelCacheOnDisk(cache_info);
               cache_info->type=MapCache;
               cache_info->mapped=MagickTrue;
@@ -3553,10 +3736,11 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
                 }
               if (image->debug != MagickFalse)
                 {
-                  (void) FormatMagickSize(cache_info->length,MagickTrue,format);
+                  (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
+                    MagickPathExtent,format);
                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
                     cache_info->type);
-                  (void) FormatLocaleString(message,MaxTextExtent,
+                  (void) FormatLocaleString(message,MagickPathExtent,
                     "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
                     cache_info->filename,cache_info->cache_filename,
                     cache_info->file,type,(double) cache_info->columns,(double)
@@ -3565,7 +3749,7 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
                     message);
                 }
-              return(status);
+              return(status == 0 ? MagickFalse : MagickTrue);
             }
         }
       RelinquishMagickResource(MapResource,cache_info->length);
@@ -3578,17 +3762,18 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
     }
   if (image->debug != MagickFalse)
     {
-      (void) FormatMagickSize(cache_info->length,MagickFalse,format);
+      (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
+        MagickPathExtent,format);
       type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
         cache_info->type);
-      (void) FormatLocaleString(message,MaxTextExtent,
+      (void) FormatLocaleString(message,MagickPathExtent,
         "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
         cache_info->cache_filename,cache_info->file,type,(double)
         cache_info->columns,(double) cache_info->rows,(double)
         cache_info->number_channels,format);
       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
     }
-  return(status);
+  return(status == 0 ? MagickFalse : MagickTrue);
 }
 \f
 /*
@@ -3633,11 +3818,8 @@ MagickExport MagickBooleanType PersistPixelCache(Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info,
-    *restrict clone_info;
-
-  Image
-    clone_image;
+    *magick_restrict cache_info,
+    *magick_restrict clone_info;
 
   MagickBooleanType
     status;
@@ -3646,7 +3828,7 @@ MagickExport MagickBooleanType PersistPixelCache(Image *image,
     page_size;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->cache != (void *) NULL);
@@ -3654,7 +3836,10 @@ MagickExport MagickBooleanType PersistPixelCache(Image *image,
   assert(offset != (MagickOffsetType *) NULL);
   page_size=GetMagickPageSize();
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
+#if defined(MAGICKCORE_OPENCL_SUPPORT)
+  CopyOpenCLBuffer(cache_info);
+#endif
   if (attach != MagickFalse)
     {
       /*
@@ -3664,7 +3849,7 @@ MagickExport MagickBooleanType PersistPixelCache(Image *image,
         (void) LogMagickEvent(CacheEvent,GetMagickModule(),
           "attach persistent cache");
       (void) CopyMagickString(cache_info->cache_filename,filename,
-        MaxTextExtent);
+        MagickPathExtent);
       cache_info->type=DiskCache;
       cache_info->offset=(*offset);
       if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
@@ -3672,52 +3857,28 @@ MagickExport MagickBooleanType PersistPixelCache(Image *image,
       *offset+=cache_info->length+page_size-(cache_info->length % page_size);
       return(MagickTrue);
     }
-  if ((cache_info->mode != ReadMode) &&
-      ((cache_info->type == DiskCache) || (cache_info->type == MapCache)) &&
-      (cache_info->reference_count == 1))
-    {
-      LockSemaphoreInfo(cache_info->semaphore);
-      if ((cache_info->mode != ReadMode) &&
-          ((cache_info->type == DiskCache) || (cache_info->type == MapCache)) &&
-          (cache_info->reference_count == 1))
-        {
-          int
-            status;
-
-          /*
-            Usurp existing persistent pixel cache.
-          */
-          status=rename_utf8(cache_info->cache_filename,filename);
-          if (status == 0)
-            {
-              (void) CopyMagickString(cache_info->cache_filename,filename,
-                MaxTextExtent);
-              *offset+=cache_info->length+page_size-(cache_info->length %
-                page_size);
-              UnlockSemaphoreInfo(cache_info->semaphore);
-              cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
-              if (image->debug != MagickFalse)
-                (void) LogMagickEvent(CacheEvent,GetMagickModule(),
-                  "Usurp resident persistent cache");
-              return(MagickTrue);
-            }
-        }
-      UnlockSemaphoreInfo(cache_info->semaphore);
-    }
   /*
     Clone persistent pixel cache.
   */
-  clone_image=(*image);
-  clone_info=(CacheInfo *) clone_image.cache;
-  image->cache=ClonePixelCache(cache_info);
-  cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
-  (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
-  cache_info->type=DiskCache;
-  cache_info->offset=(*offset);
-  cache_info=(CacheInfo *) image->cache;
-  status=OpenPixelCache(image,IOMode,exception);
-  if (status != MagickFalse)
-    status=ClonePixelCacheRepository(cache_info,clone_info,exception);
+  clone_info=(CacheInfo *) ClonePixelCache(cache_info);
+  clone_info->type=DiskCache;
+  (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
+  clone_info->file=(-1);
+  clone_info->storage_class=cache_info->storage_class;
+  clone_info->colorspace=cache_info->colorspace;
+  clone_info->alpha_trait=cache_info->alpha_trait;
+  clone_info->read_mask=cache_info->read_mask;
+  clone_info->write_mask=cache_info->write_mask;
+  clone_info->rows=cache_info->rows;
+  clone_info->columns=cache_info->columns;
+  clone_info->number_channels=cache_info->number_channels;
+  clone_info->metacontent_extent=cache_info->metacontent_extent;
+  clone_info->mode=PersistMode;
+  clone_info->length=cache_info->length;
+  (void) memcpy(clone_info->channel_map,cache_info->channel_map,
+    MaxPixelChannels*sizeof(*cache_info->channel_map));
+  clone_info->offset=(*offset);
+  status=ClonePixelCacheRepository(clone_info,cache_info,exception);
   *offset+=cache_info->length+page_size-(cache_info->length % page_size);
   clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
   return(status);
@@ -3766,7 +3927,7 @@ MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
   const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   MagickOffsetType
     offset;
@@ -3775,7 +3936,7 @@ MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
     number_pixels;
 
   Quantum
-    *restrict pixels;
+    *magick_restrict pixels;
 
   RectangleInfo
     region;
@@ -3784,12 +3945,12 @@ MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
     Validate pixel cache geometry.
   */
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
   if (cache_info == (Cache) NULL)
     return((Quantum *) NULL);
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
       (y < 0) || (x >= (ssize_t) cache_info->columns) ||
       (y >= (ssize_t) cache_info->rows))
@@ -3855,19 +4016,19 @@ static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   Quantum
-    *restrict pixels;
+    *magick_restrict pixels;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
     cache_info->nexus_info[id],exception);
@@ -3935,19 +4096,19 @@ MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   Quantum
-    *restrict pixels;
+    *magick_restrict pixels;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->methods.queue_authentic_pixels_handler !=
       (QueueAuthenticPixelsHandler) NULL)
     {
@@ -3991,8 +4152,8 @@ MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
 */
 
 static inline MagickOffsetType ReadPixelCacheRegion(
-  const CacheInfo *restrict cache_info,const MagickOffsetType offset,
-  const MagickSizeType length,unsigned char *restrict buffer)
+  const CacheInfo *magick_restrict cache_info,const MagickOffsetType offset,
+  const MagickSizeType length,unsigned char *magick_restrict buffer)
 {
   register MagickOffsetType
     i;
@@ -4008,11 +4169,11 @@ static inline MagickOffsetType ReadPixelCacheRegion(
   for (i=0; i < (MagickOffsetType) length; i+=count)
   {
 #if !defined(MAGICKCORE_HAVE_PREAD)
-    count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
-      (MagickSizeType) SSIZE_MAX));
+    count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
+      SSIZE_MAX));
 #else
-    count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
-      (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
+    count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
+      SSIZE_MAX),(off_t) (offset+i));
 #endif
     if (count <= 0)
       {
@@ -4025,7 +4186,7 @@ static inline MagickOffsetType ReadPixelCacheRegion(
 }
 
 static MagickBooleanType ReadPixelCacheMetacontent(
-  CacheInfo *restrict cache_info,NexusInfo *restrict nexus_info,
+  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
   ExceptionInfo *exception)
 {
   MagickOffsetType
@@ -4040,7 +4201,7 @@ static MagickBooleanType ReadPixelCacheMetacontent(
     y;
 
   register unsigned char
-    *restrict q;
+    *magick_restrict q;
 
   size_t
     rows;
@@ -4063,7 +4224,7 @@ static MagickBooleanType ReadPixelCacheMetacontent(
     case MapCache:
     {
       register unsigned char
-        *restrict p;
+        *magick_restrict p;
 
       /*
         Read meta-content from memory.
@@ -4195,8 +4356,9 @@ static MagickBooleanType ReadPixelCacheMetacontent(
 %    o exception: return any errors or warnings in this structure.
 %
 */
-static MagickBooleanType ReadPixelCachePixels(CacheInfo *restrict cache_info,
-  NexusInfo *restrict nexus_info,ExceptionInfo *exception)
+static MagickBooleanType ReadPixelCachePixels(
+  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
+  ExceptionInfo *exception)
 {
   MagickOffsetType
     count,
@@ -4207,22 +4369,30 @@ static MagickBooleanType ReadPixelCachePixels(CacheInfo *restrict cache_info,
     length;
 
   register Quantum
-    *restrict q;
+    *magick_restrict q;
 
   register ssize_t
     y;
 
   size_t
+    number_channels,
     rows;
 
   if (nexus_info->authentic_pixel_cache != MagickFalse)
     return(MagickTrue);
-  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
-    nexus_info->region.x;
-  length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
+  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns;
+  if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
+    return(MagickFalse);
+  offset+=nexus_info->region.x;
+  number_channels=cache_info->number_channels;
+  length=(MagickSizeType) number_channels*nexus_info->region.width*
     sizeof(Quantum);
-  extent=length*nexus_info->region.height;
+  if ((length/number_channels/sizeof(Quantum)) != nexus_info->region.width)
+    return(MagickFalse);
   rows=nexus_info->region.height;
+  extent=length*rows;
+  if ((extent == 0) || ((extent/length) != rows))
+    return(MagickFalse);
   y=0;
   q=nexus_info->pixels;
   switch (cache_info->type)
@@ -4231,7 +4401,7 @@ static MagickBooleanType ReadPixelCachePixels(CacheInfo *restrict cache_info,
     case MapCache:
     {
       register Quantum
-        *restrict p;
+        *magick_restrict p;
 
       /*
         Read pixels from memory.
@@ -4358,11 +4528,11 @@ static MagickBooleanType ReadPixelCachePixels(CacheInfo *restrict cache_info,
 MagickPrivate Cache ReferencePixelCache(Cache cache)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(cache != (Cache *) NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   LockSemaphoreInfo(cache_info->semaphore);
   cache_info->reference_count++;
   UnlockSemaphoreInfo(cache_info->semaphore);
@@ -4374,6 +4544,64 @@ MagickPrivate Cache ReferencePixelCache(Cache cache)
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   R e s e t P i x e l C a c h e C h a n n e l s                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ResetPixelCacheChannels() resets the pixel cache channels.
+%
+%  The format of the ResetPixelCacheChannels method is:
+%
+%      void ResetPixelCacheChannels(Image *)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+*/
+MagickPrivate void ResetPixelCacheChannels(Image *image)
+{
+  CacheInfo
+    *magick_restrict cache_info;
+
+  assert(image != (const Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  assert(image->cache != (Cache) NULL);
+  cache_info=(CacheInfo *) image->cache;
+  assert(cache_info->signature == MagickCoreSignature);
+  cache_info->number_channels=GetPixelChannels(image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   R e s e t P i x e l C a c h e E p o c h                                   %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ResetPixelCacheEpoch() resets the pixel cache epoch.
+%
+%  The format of the ResetPixelCacheEpoch method is:
+%
+%      void ResetPixelCacheEpoch(void)
+%
+*/
+MagickPrivate void ResetPixelCacheEpoch(void)
+{
+  cache_epoch=0;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +   S e t P i x e l C a c h e M e t h o d s                                   %
 %                                                                             %
 %                                                                             %
@@ -4396,7 +4624,7 @@ MagickPrivate Cache ReferencePixelCache(Cache cache)
 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   GetOneAuthenticPixelFromHandler
     get_one_authentic_pixel_from_handler;
@@ -4410,7 +4638,7 @@ MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
   assert(cache != (Cache) NULL);
   assert(cache_methods != (CacheMethods *) NULL);
   cache_info=(CacheInfo *) cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       cache_info->filename);
@@ -4494,15 +4722,21 @@ MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
 */
 
 static inline MagickBooleanType AcquireCacheNexusPixels(
-  const CacheInfo *restrict cache_info,NexusInfo *nexus_info,
+  const CacheInfo *magick_restrict cache_info,NexusInfo *nexus_info,
   ExceptionInfo *exception)
 {
   if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
     return(MagickFalse);
-  nexus_info->mapped=MagickFalse;
-  nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
-    (size_t) nexus_info->length));
-  if (nexus_info->cache == (Quantum *) NULL)
+  if (cache_anonymous_memory <= 0)
+    {
+      nexus_info->mapped=MagickFalse;
+      nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
+        (size_t) nexus_info->length));
+      if (nexus_info->cache != (Quantum *) NULL)
+        (void) ResetMagickMemory(nexus_info->cache,0,(size_t)
+          nexus_info->length);
+    }
+  else
     {
       nexus_info->mapped=MagickTrue;
       nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
@@ -4519,7 +4753,8 @@ static inline MagickBooleanType AcquireCacheNexusPixels(
 }
 
 static inline MagickBooleanType IsPixelCacheAuthentic(
-  const CacheInfo *restrict cache_info,const NexusInfo *restrict nexus_info)
+  const CacheInfo *magick_restrict cache_info,
+  const NexusInfo *magick_restrict nexus_info)
 {
   MagickBooleanType
     status;
@@ -4562,7 +4797,7 @@ static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
     number_pixels;
 
   assert(cache_info != (const CacheInfo *) NULL);
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->type == UndefinedCache)
     return((Quantum *) NULL);
   nexus_info->region=(*region);
@@ -4675,10 +4910,10 @@ static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   CacheView
-    *restrict image_view;
+    *magick_restrict image_view;
 
   MagickBooleanType
     status;
@@ -4687,12 +4922,12 @@ static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
     y;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   image->alpha_trait=BlendPixelTrait;
   status=MagickTrue;
   image_view=AcquireVirtualCacheView(image,exception);  /* must be virtual */
@@ -4703,7 +4938,7 @@ static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
   for (y=0; y < (ssize_t) image->rows; y++)
   {
     register Quantum
-      *restrict q;
+      *magick_restrict q;
 
     register ssize_t
       x;
@@ -4731,18 +4966,18 @@ MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   VirtualPixelMethod
     method;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   method=cache_info->virtual_pixel_method;
   cache_info->virtual_pixel_method=virtual_pixel_method;
   if ((image->columns != 0) && (image->rows != 0))
@@ -4750,8 +4985,8 @@ MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
     {
       case BackgroundVirtualPixelMethod:
       {
-        if ((image->background_color.alpha_trait == BlendPixelTrait) &&
-            (image->alpha_trait != BlendPixelTrait))
+        if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
+            (image->alpha_trait == UndefinedPixelTrait))
           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
         if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
             (IsGrayColorspace(image->colorspace) != MagickFalse))
@@ -4760,7 +4995,7 @@ MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
       }
       case TransparentVirtualPixelMethod:
       {
-        if (image->alpha_trait != BlendPixelTrait)
+        if (image->alpha_trait == UndefinedPixelTrait)
           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
         break;
       }
@@ -4769,6 +5004,58 @@ MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
     }
   return(method);
 }
+
+#if defined(MAGICKCORE_OPENCL_SUPPORT)
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   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                         %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  SyncAuthenticOpenCLBuffer() makes sure that all the OpenCL operations have
+%  been completed and updates the host memory.
+%
+%  The format of the SyncAuthenticOpenCLBuffer() method is:
+%
+%      void SyncAuthenticOpenCLBuffer(const Image *image)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+*/
+
+static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
+{
+  assert(cache_info != (CacheInfo *) NULL);
+  assert(cache_info->signature == MagickCoreSignature);
+  if ((cache_info->type != MemoryCache) ||
+      (cache_info->opencl == (MagickCLCacheInfo) NULL))
+    return;
+  /*
+    Ensure single threaded access to OpenCL environment.
+  */
+  LockSemaphoreInfo(cache_info->semaphore);
+  cache_info->opencl=(MagickCLCacheInfo) CopyMagickCLCacheInfo(
+    cache_info->opencl);
+  UnlockSemaphoreInfo(cache_info->semaphore);
+}
+
+MagickPrivate void SyncAuthenticOpenCLBuffer(const Image *image)
+{
+  CacheInfo
+    *magick_restrict cache_info;
+
+  assert(image != (const Image *) NULL);
+  cache_info=(CacheInfo *) image->cache;
+  CopyOpenCLBuffer(cache_info);
+}
+#endif
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -4800,10 +5087,10 @@ MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
 %
 */
 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
-  NexusInfo *restrict nexus_info,ExceptionInfo *exception)
+  NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   MagickBooleanType
     status;
@@ -4812,11 +5099,11 @@ MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
     Transfer pixels to the cache.
   */
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->cache == (Cache) NULL)
     ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->type == UndefinedCache)
     return(MagickFalse);
   if (nexus_info->authentic_pixel_cache != MagickFalse)
@@ -4824,7 +5111,7 @@ MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
       image->taint=MagickTrue;
       return(MagickTrue);
     }
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   status=WritePixelCachePixels(cache_info,nexus_info,exception);
   if ((cache_info->metacontent_extent != 0) &&
       (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
@@ -4865,7 +5152,7 @@ static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -4874,10 +5161,10 @@ static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
     status;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   assert(id < (int) cache_info->number_threads);
   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
     exception);
@@ -4915,7 +5202,7 @@ MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -4924,10 +5211,10 @@ MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
     status;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
-  assert(cache_info->signature == MagickSignature);
+  assert(cache_info->signature == MagickCoreSignature);
   if (cache_info->methods.sync_authentic_pixels_handler !=
        (SyncAuthenticPixelsHandler) NULL)
     {
@@ -4972,7 +5259,7 @@ MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *restrict cache_info;
+    *magick_restrict cache_info;
 
   assert(image != (Image *) NULL);
   assert(exception != (ExceptionInfo *) NULL);
@@ -5009,7 +5296,7 @@ MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
 %
 */
 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
-  NexusInfo *restrict nexus_info,ExceptionInfo *exception)
+  NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
 {
   MagickOffsetType
     count,
@@ -5020,7 +5307,7 @@ static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
     length;
 
   register const unsigned char
-    *restrict p;
+    *magick_restrict p;
 
   register ssize_t
     y;
@@ -5046,7 +5333,7 @@ static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
     case MapCache:
     {
       register unsigned char
-        *restrict q;
+        *magick_restrict q;
 
       /*
         Write associated pixels to memory.
@@ -5178,8 +5465,9 @@ static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
 %    o exception: return any errors or warnings in this structure.
 %
 */
-static MagickBooleanType WritePixelCachePixels(CacheInfo *restrict cache_info,
-  NexusInfo *restrict nexus_info,ExceptionInfo *exception)
+static MagickBooleanType WritePixelCachePixels(
+  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
+  ExceptionInfo *exception)
 {
   MagickOffsetType
     count,
@@ -5190,7 +5478,7 @@ static MagickBooleanType WritePixelCachePixels(CacheInfo *restrict cache_info,
     length;
 
   register const Quantum
-    *restrict p;
+    *magick_restrict p;
 
   register ssize_t
     y;
@@ -5214,7 +5502,7 @@ static MagickBooleanType WritePixelCachePixels(CacheInfo *restrict cache_info,
     case MapCache:
     {
       register Quantum
-        *restrict q;
+        *magick_restrict q;
 
       /*
         Write pixels to memory.