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