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