]> 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 != (const 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     {
1498       char
1499         *limit;
1500
1501       /*
1502         Set CPU throttle in milleseconds.
1503       */
1504       cpu_throttle=MagickResourceInfinity;
1505       limit=GetEnvironmentValue("MAGICK_THROTTLE");
1506       if (limit == (char *) NULL)
1507         limit=GetPolicyValue("throttle");
1508       if (limit != (char *) NULL)
1509         {
1510           cpu_throttle=(MagickSizeType) StringToInteger(limit);
1511           limit=DestroyString(limit);
1512         }
1513     }
1514   if ((cpu_throttle != MagickResourceInfinity) && ((cycles++ % 32) == 0))
1515     MagickDelay(cpu_throttle);
1516   if (time_limit == 0)
1517     {
1518       /*
1519         Set the expire time in seconds.
1520       */
1521       time_limit=GetMagickResourceLimit(TimeResource);
1522       cache_timestamp=time((time_t *) NULL);
1523     }
1524   if ((time_limit != MagickResourceInfinity) &&
1525       ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
1526     ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
1527   assert(image->cache != (Cache) NULL);
1528   cache_info=(CacheInfo *) image->cache;
1529   destroy=MagickFalse;
1530   if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1531     {
1532       LockSemaphoreInfo(cache_info->semaphore);
1533       if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1534         {
1535           CacheInfo
1536             *clone_info;
1537
1538           Image
1539             clone_image;
1540
1541           /*
1542             Clone pixel cache.
1543           */
1544           clone_image=(*image);
1545           clone_image.semaphore=AllocateSemaphoreInfo();
1546           clone_image.reference_count=1;
1547           clone_image.cache=ClonePixelCache(cache_info);
1548           clone_info=(CacheInfo *) clone_image.cache;
1549           status=OpenPixelCache(&clone_image,IOMode,exception);
1550           if (status != MagickFalse)
1551             {
1552               if (clone != MagickFalse)
1553                 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
1554               if (status != MagickFalse)
1555                 {
1556                   if (cache_info->reference_count == 1)
1557                     cache_info->nexus_info=(NexusInfo **) NULL;
1558                   destroy=MagickTrue;
1559                   image->cache=clone_image.cache;
1560                 }
1561             }
1562           DestroySemaphoreInfo(&clone_image.semaphore);
1563         }
1564       UnlockSemaphoreInfo(cache_info->semaphore);
1565     }
1566   if (destroy != MagickFalse)
1567     cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1568   if (status != MagickFalse)
1569     {
1570       /*
1571         Ensure the image matches the pixel cache morphology.
1572       */
1573       image->taint=MagickTrue;
1574       image->type=UndefinedType;
1575       if (ValidatePixelCacheMorphology(image) == MagickFalse)
1576         {
1577           status=OpenPixelCache(image,IOMode,exception);
1578           cache_info=(CacheInfo *) image->cache;
1579           if (cache_info->type == DiskCache)
1580             (void) ClosePixelCacheOnDisk(cache_info);
1581         }
1582     }
1583   UnlockSemaphoreInfo(image->semaphore);
1584   if (status == MagickFalse)
1585     return((Cache) NULL);
1586   return(image->cache);
1587 }
1588 \f
1589 /*
1590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1591 %                                                                             %
1592 %                                                                             %
1593 %                                                                             %
1594 +   G e t I m a g e P i x e l C a c h e T y p e                               %
1595 %                                                                             %
1596 %                                                                             %
1597 %                                                                             %
1598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1599 %
1600 %  GetImagePixelCacheType() returns the pixel cache type: UndefinedCache,
1601 %  DiskCache, MemoryCache, MapCache, or PingCache.
1602 %
1603 %  The format of the GetImagePixelCacheType() method is:
1604 %
1605 %      CacheType GetImagePixelCacheType(const Image *image)
1606 %
1607 %  A description of each parameter follows:
1608 %
1609 %    o image: the image.
1610 %
1611 */
1612 MagickExport CacheType GetImagePixelCacheType(const Image *image)
1613 {
1614   CacheInfo
1615     *cache_info;
1616
1617   assert(image != (Image *) NULL);
1618   assert(image->signature == MagickSignature);
1619   assert(image->cache != (Cache) NULL);
1620   cache_info=(CacheInfo *) image->cache;
1621   assert(cache_info->signature == MagickSignature);
1622   return(cache_info->type);
1623 }
1624 \f
1625 /*
1626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1627 %                                                                             %
1628 %                                                                             %
1629 %                                                                             %
1630 %   G e t O n e A u t h e n t i c P i x e l                                   %
1631 %                                                                             %
1632 %                                                                             %
1633 %                                                                             %
1634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1635 %
1636 %  GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
1637 %  location.  The image background color is returned if an error occurs.
1638 %
1639 %  The format of the GetOneAuthenticPixel() method is:
1640 %
1641 %      MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
1642 %        const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1643 %
1644 %  A description of each parameter follows:
1645 %
1646 %    o image: the image.
1647 %
1648 %    o x,y:  These values define the location of the pixel to return.
1649 %
1650 %    o pixel: return a pixel at the specified (x,y) location.
1651 %
1652 %    o exception: return any errors or warnings in this structure.
1653 %
1654 */
1655 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
1656   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1657 {
1658   CacheInfo
1659     *cache_info;
1660
1661   register Quantum
1662     *restrict q;
1663
1664   register ssize_t
1665     i;
1666
1667   assert(image != (Image *) NULL);
1668   assert(image->signature == MagickSignature);
1669   assert(image->cache != (Cache) NULL);
1670   cache_info=(CacheInfo *) image->cache;
1671   assert(cache_info->signature == MagickSignature);
1672   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
1673   if (cache_info->methods.get_one_authentic_pixel_from_handler !=
1674        (GetOneAuthenticPixelFromHandler) NULL)
1675     return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
1676       pixel,exception));
1677   q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1678   if (q == (Quantum *) NULL)
1679     {
1680       pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1681       pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
1682       pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
1683       pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
1684       pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
1685       return(MagickFalse);
1686     }
1687   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1688   {
1689     PixelChannel
1690       channel;
1691
1692     channel=GetPixelChannelChannel(image,i);
1693     pixel[channel]=q[i];
1694   }
1695   return(MagickTrue);
1696 }
1697 \f
1698 /*
1699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1700 %                                                                             %
1701 %                                                                             %
1702 %                                                                             %
1703 +   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                 %
1704 %                                                                             %
1705 %                                                                             %
1706 %                                                                             %
1707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1708 %
1709 %  GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
1710 %  location.  The image background color is returned if an error occurs.
1711 %
1712 %  The format of the GetOneAuthenticPixelFromCache() method is:
1713 %
1714 %      MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
1715 %        const ssize_t x,const ssize_t y,Quantum *pixel,
1716 %        ExceptionInfo *exception)
1717 %
1718 %  A description of each parameter follows:
1719 %
1720 %    o image: the image.
1721 %
1722 %    o x,y:  These values define the location of the pixel to return.
1723 %
1724 %    o pixel: return a pixel at the specified (x,y) location.
1725 %
1726 %    o exception: return any errors or warnings in this structure.
1727 %
1728 */
1729 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
1730   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1731 {
1732   CacheInfo
1733     *cache_info;
1734
1735   const int
1736     id = GetOpenMPThreadId();
1737
1738   register Quantum
1739     *restrict q;
1740
1741   register ssize_t
1742     i;
1743
1744   assert(image != (const Image *) NULL);
1745   assert(image->signature == MagickSignature);
1746   assert(image->cache != (Cache) NULL);
1747   cache_info=(CacheInfo *) image->cache;
1748   assert(cache_info->signature == MagickSignature);
1749   assert(id < (int) cache_info->number_threads);
1750   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
1751   q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
1752     exception);
1753   if (q == (Quantum *) NULL)
1754     {
1755       pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1756       pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
1757       pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
1758       pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
1759       pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
1760       return(MagickFalse);
1761     }
1762   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1763   {
1764     PixelChannel
1765       channel;
1766
1767     channel=GetPixelChannelChannel(image,i);
1768     pixel[channel]=q[i];
1769   }
1770   return(MagickTrue);
1771 }
1772 \f
1773 /*
1774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775 %                                                                             %
1776 %                                                                             %
1777 %                                                                             %
1778 %   G e t O n e V i r t u a l P i x e l                                       %
1779 %                                                                             %
1780 %                                                                             %
1781 %                                                                             %
1782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1783 %
1784 %  GetOneVirtualPixel() returns a single virtual pixel at the specified
1785 %  (x,y) location.  The image background color is returned if an error occurs.
1786 %  If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
1787 %
1788 %  The format of the GetOneVirtualPixel() method is:
1789 %
1790 %      MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
1791 %        const ssize_t y,Quantum *pixel,ExceptionInfo exception)
1792 %
1793 %  A description of each parameter follows:
1794 %
1795 %    o image: the image.
1796 %
1797 %    o x,y:  These values define the location of the pixel to return.
1798 %
1799 %    o pixel: return a pixel at the specified (x,y) location.
1800 %
1801 %    o exception: return any errors or warnings in this structure.
1802 %
1803 */
1804 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
1805   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1806 {
1807   CacheInfo
1808     *cache_info;
1809
1810   const int
1811     id = GetOpenMPThreadId();
1812
1813   const Quantum
1814     *p;
1815
1816   register ssize_t
1817     i;
1818
1819   assert(image != (const Image *) NULL);
1820   assert(image->signature == MagickSignature);
1821   assert(image->cache != (Cache) NULL);
1822   cache_info=(CacheInfo *) image->cache;
1823   assert(cache_info->signature == MagickSignature);
1824   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
1825   if (cache_info->methods.get_one_virtual_pixel_from_handler !=
1826        (GetOneVirtualPixelFromHandler) NULL)
1827     return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
1828       GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
1829   assert(id < (int) cache_info->number_threads);
1830   p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
1831     1UL,1UL,cache_info->nexus_info[id],exception);
1832   if (p == (const Quantum *) NULL)
1833     {
1834       pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1835       pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
1836       pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
1837       pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
1838       pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
1839       return(MagickFalse);
1840     }
1841   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1842   {
1843     PixelChannel
1844       channel;
1845
1846     channel=GetPixelChannelChannel(image,i);
1847     pixel[channel]=p[i];
1848   }
1849   return(MagickTrue);
1850 }
1851 \f
1852 /*
1853 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1854 %                                                                             %
1855 %                                                                             %
1856 %                                                                             %
1857 +   G e t O n e V i r t u a l P i x e l F r o m C a c h e                     %
1858 %                                                                             %
1859 %                                                                             %
1860 %                                                                             %
1861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1862 %
1863 %  GetOneVirtualPixelFromCache() returns a single virtual pixel at the
1864 %  specified (x,y) location.  The image background color is returned if an
1865 %  error occurs.
1866 %
1867 %  The format of the GetOneVirtualPixelFromCache() method is:
1868 %
1869 %      MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
1870 %        const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
1871 %        Quantum *pixel,ExceptionInfo *exception)
1872 %
1873 %  A description of each parameter follows:
1874 %
1875 %    o image: the image.
1876 %
1877 %    o virtual_pixel_method: the virtual pixel method.
1878 %
1879 %    o x,y:  These values define the location of the pixel to return.
1880 %
1881 %    o pixel: return a pixel at the specified (x,y) location.
1882 %
1883 %    o exception: return any errors or warnings in this structure.
1884 %
1885 */
1886 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
1887   const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
1888   Quantum *pixel,ExceptionInfo *exception)
1889 {
1890   CacheInfo
1891     *cache_info;
1892
1893   const int
1894     id = GetOpenMPThreadId();
1895
1896   const Quantum
1897     *p;
1898
1899   register ssize_t
1900     i;
1901
1902   assert(image != (const Image *) NULL);
1903   assert(image->signature == MagickSignature);
1904   assert(image->cache != (Cache) NULL);
1905   cache_info=(CacheInfo *) image->cache;
1906   assert(cache_info->signature == MagickSignature);
1907   assert(id < (int) cache_info->number_threads);
1908   (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
1909   p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
1910     cache_info->nexus_info[id],exception);
1911   if (p == (const Quantum *) NULL)
1912     {
1913       pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1914       pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
1915       pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
1916       pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
1917       pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
1918       return(MagickFalse);
1919     }
1920   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1921   {
1922     PixelChannel
1923       channel;
1924
1925     channel=GetPixelChannelChannel(image,i);
1926     pixel[channel]=p[i];
1927   }
1928   return(MagickTrue);
1929 }
1930 \f
1931 /*
1932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1933 %                                                                             %
1934 %                                                                             %
1935 %                                                                             %
1936 %   G e t O n e V i r t u a l P i x e l I n f o                               %
1937 %                                                                             %
1938 %                                                                             %
1939 %                                                                             %
1940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1941 %
1942 %  GetOneVirtualPixelInfo() returns a single pixel at the specified (x,y)
1943 %  location.  The image background color is returned if an error occurs.  If
1944 %  you plan to modify the pixel, use GetOneAuthenticPixel() instead.
1945 %
1946 %  The format of the GetOneVirtualPixelInfo() method is:
1947 %
1948 %      MagickBooleanType GetOneVirtualPixelInfo(const Image image,
1949 %        const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
1950 %        const ssize_t y,PixelInfo *pixel,ExceptionInfo exception)
1951 %
1952 %  A description of each parameter follows:
1953 %
1954 %    o image: the image.
1955 %
1956 %    o virtual_pixel_method: the virtual pixel method.
1957 %
1958 %    o x,y:  these values define the location of the pixel to return.
1959 %
1960 %    o pixel: return a pixel at the specified (x,y) location.
1961 %
1962 %    o exception: return any errors or warnings in this structure.
1963 %
1964 */
1965 MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
1966   const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
1967   PixelInfo *pixel,ExceptionInfo *exception)
1968 {
1969   CacheInfo
1970     *cache_info;
1971
1972   const int
1973     id = GetOpenMPThreadId();
1974
1975   register const Quantum
1976     *p;
1977
1978   assert(image != (const Image *) NULL);
1979   assert(image->signature == MagickSignature);
1980   assert(image->cache != (Cache) NULL);
1981   cache_info=(CacheInfo *) image->cache;
1982   assert(cache_info->signature == MagickSignature);
1983   assert(id < (int) cache_info->number_threads);
1984   GetPixelInfo(image,pixel);
1985   p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
1986     cache_info->nexus_info[id],exception);
1987   if (p == (const Quantum *) NULL)
1988     return(MagickFalse);
1989   GetPixelInfoPixel(image,p,pixel);
1990   return(MagickTrue);
1991 }
1992 \f
1993 /*
1994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1995 %                                                                             %
1996 %                                                                             %
1997 %                                                                             %
1998 +   G e t P i x e l C a c h e C o l o r s p a c e                             %
1999 %                                                                             %
2000 %                                                                             %
2001 %                                                                             %
2002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2003 %
2004 %  GetPixelCacheColorspace() returns the class type of the pixel cache.
2005 %
2006 %  The format of the GetPixelCacheColorspace() method is:
2007 %
2008 %      Colorspace GetPixelCacheColorspace(Cache cache)
2009 %
2010 %  A description of each parameter follows:
2011 %
2012 %    o cache: the pixel cache.
2013 %
2014 */
2015 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
2016 {
2017   CacheInfo
2018     *cache_info;
2019
2020   assert(cache != (Cache) NULL);
2021   cache_info=(CacheInfo *) cache;
2022   assert(cache_info->signature == MagickSignature);
2023   if (cache_info->debug != MagickFalse)
2024     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2025       cache_info->filename);
2026   return(cache_info->colorspace);
2027 }
2028 \f
2029 /*
2030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2031 %                                                                             %
2032 %                                                                             %
2033 %                                                                             %
2034 +   G e t P i x e l C a c h e M e t h o d s                                   %
2035 %                                                                             %
2036 %                                                                             %
2037 %                                                                             %
2038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2039 %
2040 %  GetPixelCacheMethods() initializes the CacheMethods structure.
2041 %
2042 %  The format of the GetPixelCacheMethods() method is:
2043 %
2044 %      void GetPixelCacheMethods(CacheMethods *cache_methods)
2045 %
2046 %  A description of each parameter follows:
2047 %
2048 %    o cache_methods: Specifies a pointer to a CacheMethods structure.
2049 %
2050 */
2051 MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
2052 {
2053   assert(cache_methods != (CacheMethods *) NULL);
2054   (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2055   cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2056   cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2057   cache_methods->get_virtual_metacontent_from_handler=
2058     GetVirtualMetacontentFromCache;
2059   cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2060   cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2061   cache_methods->get_authentic_metacontent_from_handler=
2062     GetAuthenticMetacontentFromCache;
2063   cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2064   cache_methods->get_one_authentic_pixel_from_handler=
2065     GetOneAuthenticPixelFromCache;
2066   cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2067   cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2068   cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2069 }
2070 \f
2071 /*
2072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2073 %                                                                             %
2074 %                                                                             %
2075 %                                                                             %
2076 +   G e t P i x e l C a c h e N e x u s E x t e n t                           %
2077 %                                                                             %
2078 %                                                                             %
2079 %                                                                             %
2080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2081 %
2082 %  GetPixelCacheNexusExtent() returns the extent of the pixels associated
2083 %  corresponding with the last call to SetPixelCacheNexusPixels() or
2084 %  GetPixelCacheNexusPixels().
2085 %
2086 %  The format of the GetPixelCacheNexusExtent() method is:
2087 %
2088 %      MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2089 %        NexusInfo *nexus_info)
2090 %
2091 %  A description of each parameter follows:
2092 %
2093 %    o nexus_info: the nexus info.
2094 %
2095 */
2096 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2097   NexusInfo *nexus_info)
2098 {
2099   CacheInfo
2100     *cache_info;
2101
2102   MagickSizeType
2103     extent;
2104
2105   assert(cache != NULL);
2106   cache_info=(CacheInfo *) cache;
2107   assert(cache_info->signature == MagickSignature);
2108   extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2109   if (extent == 0)
2110     return((MagickSizeType) cache_info->columns*cache_info->rows);
2111   return(extent);
2112 }
2113 \f
2114 /*
2115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2116 %                                                                             %
2117 %                                                                             %
2118 %                                                                             %
2119 +   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                 %
2120 %                                                                             %
2121 %                                                                             %
2122 %                                                                             %
2123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2124 %
2125 %  GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2126 %  cache nexus.
2127 %
2128 %  The format of the GetPixelCacheNexusMetacontent() method is:
2129 %
2130 %      void *GetPixelCacheNexusMetacontent(const Cache cache,
2131 %        NexusInfo *nexus_info)
2132 %
2133 %  A description of each parameter follows:
2134 %
2135 %    o cache: the pixel cache.
2136 %
2137 %    o nexus_info: the cache nexus to return the meta-content.
2138 %
2139 */
2140 MagickPrivate void *GetPixelCacheNexusMetacontent(const Cache cache,
2141   NexusInfo *nexus_info)
2142 {
2143   CacheInfo
2144     *cache_info;
2145
2146   assert(cache != NULL);
2147   cache_info=(CacheInfo *) cache;
2148   assert(cache_info->signature == MagickSignature);
2149   if (cache_info->storage_class == UndefinedClass)
2150     return((void *) NULL);
2151   return(nexus_info->metacontent);
2152 }
2153 \f
2154 /*
2155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2156 %                                                                             %
2157 %                                                                             %
2158 %                                                                             %
2159 +   G e t P i x e l C a c h e N e x u s P i x e l s                           %
2160 %                                                                             %
2161 %                                                                             %
2162 %                                                                             %
2163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2164 %
2165 %  GetPixelCacheNexusPixels() returns the pixels associated with the specified
2166 %  cache nexus.
2167 %
2168 %  The format of the GetPixelCacheNexusPixels() method is:
2169 %
2170 %      Quantum *GetPixelCacheNexusPixels(const Cache cache,
2171 %        NexusInfo *nexus_info)
2172 %
2173 %  A description of each parameter follows:
2174 %
2175 %    o cache: the pixel cache.
2176 %
2177 %    o nexus_info: the cache nexus to return the pixels.
2178 %
2179 */
2180 MagickPrivate Quantum *GetPixelCacheNexusPixels(const Cache cache,
2181   NexusInfo *nexus_info)
2182 {
2183   CacheInfo
2184     *cache_info;
2185
2186   assert(cache != NULL);
2187   cache_info=(CacheInfo *) cache;
2188   assert(cache_info->signature == MagickSignature);
2189   if (cache_info->storage_class == UndefinedClass)
2190     return((Quantum *) NULL);
2191   return(nexus_info->pixels);
2192 }
2193 \f
2194 /*
2195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2196 %                                                                             %
2197 %                                                                             %
2198 %                                                                             %
2199 +   G e t P i x e l C a c h e P i x e l s                                     %
2200 %                                                                             %
2201 %                                                                             %
2202 %                                                                             %
2203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2204 %
2205 %  GetPixelCachePixels() returns the pixels associated with the specified image.
2206 %
2207 %  The format of the GetPixelCachePixels() method is:
2208 %
2209 %      void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2210 %        ExceptionInfo *exception)
2211 %
2212 %  A description of each parameter follows:
2213 %
2214 %    o image: the image.
2215 %
2216 %    o length: the pixel cache length.
2217 %
2218 %    o exception: return any errors or warnings in this structure.
2219 %
2220 */
2221 MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2222   ExceptionInfo *exception)
2223 {
2224   CacheInfo
2225     *cache_info;
2226
2227   assert(image != (const Image *) NULL);
2228   assert(image->signature == MagickSignature);
2229   assert(image->cache != (Cache) NULL);
2230   assert(length != (MagickSizeType *) NULL);
2231   assert(exception != (ExceptionInfo *) NULL);
2232   assert(exception->signature == MagickSignature);
2233   cache_info=(CacheInfo *) image->cache;
2234   assert(cache_info->signature == MagickSignature);
2235   *length=0;
2236   if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2237     return((void *) NULL);
2238   *length=cache_info->length;
2239   return((void *) cache_info->pixels);
2240 }
2241 \f
2242 /*
2243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2244 %                                                                             %
2245 %                                                                             %
2246 %                                                                             %
2247 +   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                         %
2248 %                                                                             %
2249 %                                                                             %
2250 %                                                                             %
2251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2252 %
2253 %  GetPixelCacheStorageClass() returns the class type of the pixel cache.
2254 %
2255 %  The format of the GetPixelCacheStorageClass() method is:
2256 %
2257 %      ClassType GetPixelCacheStorageClass(Cache cache)
2258 %
2259 %  A description of each parameter follows:
2260 %
2261 %    o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2262 %
2263 %    o cache: the pixel cache.
2264 %
2265 */
2266 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
2267 {
2268   CacheInfo
2269     *cache_info;
2270
2271   assert(cache != (Cache) NULL);
2272   cache_info=(CacheInfo *) cache;
2273   assert(cache_info->signature == MagickSignature);
2274   if (cache_info->debug != MagickFalse)
2275     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2276       cache_info->filename);
2277   return(cache_info->storage_class);
2278 }
2279 \f
2280 /*
2281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282 %                                                                             %
2283 %                                                                             %
2284 %                                                                             %
2285 +   G e t P i x e l C a c h e T i l e S i z e                                 %
2286 %                                                                             %
2287 %                                                                             %
2288 %                                                                             %
2289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2290 %
2291 %  GetPixelCacheTileSize() returns the pixel cache tile size.
2292 %
2293 %  The format of the GetPixelCacheTileSize() method is:
2294 %
2295 %      void GetPixelCacheTileSize(const Image *image,size_t *width,
2296 %        size_t *height)
2297 %
2298 %  A description of each parameter follows:
2299 %
2300 %    o image: the image.
2301 %
2302 %    o width: the optimize cache tile width in pixels.
2303 %
2304 %    o height: the optimize cache tile height in pixels.
2305 %
2306 */
2307 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
2308   size_t *height)
2309 {
2310   CacheInfo
2311     *cache_info;
2312
2313   assert(image != (Image *) NULL);
2314   assert(image->signature == MagickSignature);
2315   if (image->debug != MagickFalse)
2316     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2317   cache_info=(CacheInfo *) image->cache;
2318   assert(cache_info->signature == MagickSignature);
2319   *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2320   if (GetImagePixelCacheType(image) == DiskCache)
2321     *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2322   *height=(*width);
2323 }
2324 \f
2325 /*
2326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2327 %                                                                             %
2328 %                                                                             %
2329 %                                                                             %
2330 +   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                       %
2331 %                                                                             %
2332 %                                                                             %
2333 %                                                                             %
2334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2335 %
2336 %  GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2337 %  pixel cache.  A virtual pixel is any pixel access that is outside the
2338 %  boundaries of the image cache.
2339 %
2340 %  The format of the GetPixelCacheVirtualMethod() method is:
2341 %
2342 %      VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2343 %
2344 %  A description of each parameter follows:
2345 %
2346 %    o image: the image.
2347 %
2348 */
2349 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2350 {
2351   CacheInfo
2352     *cache_info;
2353
2354   assert(image != (Image *) NULL);
2355   assert(image->signature == MagickSignature);
2356   assert(image->cache != (Cache) NULL);
2357   cache_info=(CacheInfo *) image->cache;
2358   assert(cache_info->signature == MagickSignature);
2359   return(cache_info->virtual_pixel_method);
2360 }
2361 \f
2362 /*
2363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2364 %                                                                             %
2365 %                                                                             %
2366 %                                                                             %
2367 +   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               %
2368 %                                                                             %
2369 %                                                                             %
2370 %                                                                             %
2371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2372 %
2373 %  GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2374 %  the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2375 %
2376 %  The format of the GetVirtualMetacontentFromCache() method is:
2377 %
2378 %      void *GetVirtualMetacontentFromCache(const Image *image)
2379 %
2380 %  A description of each parameter follows:
2381 %
2382 %    o image: the image.
2383 %
2384 */
2385 static const void *GetVirtualMetacontentFromCache(const Image *image)
2386 {
2387   CacheInfo
2388     *cache_info;
2389
2390   const int
2391     id = GetOpenMPThreadId();
2392
2393   const void
2394     *metacontent;
2395
2396   assert(image != (const Image *) NULL);
2397   assert(image->signature == MagickSignature);
2398   assert(image->cache != (Cache) NULL);
2399   cache_info=(CacheInfo *) image->cache;
2400   assert(cache_info->signature == MagickSignature);
2401   assert(id < (int) cache_info->number_threads);
2402   metacontent=GetVirtualMetacontentFromNexus(cache_info,
2403     cache_info->nexus_info[id]);
2404   return(metacontent);
2405 }
2406 \f
2407 /*
2408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2409 %                                                                             %
2410 %                                                                             %
2411 %                                                                             %
2412 +   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               %
2413 %                                                                             %
2414 %                                                                             %
2415 %                                                                             %
2416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2417 %
2418 %  GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2419 %  cache nexus.
2420 %
2421 %  The format of the GetVirtualMetacontentFromNexus() method is:
2422 %
2423 %      const void *GetVirtualMetacontentFromNexus(const Cache cache,
2424 %        NexusInfo *nexus_info)
2425 %
2426 %  A description of each parameter follows:
2427 %
2428 %    o cache: the pixel cache.
2429 %
2430 %    o nexus_info: the cache nexus to return the meta-content.
2431 %
2432 */
2433 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
2434   NexusInfo *nexus_info)
2435 {
2436   CacheInfo
2437     *cache_info;
2438
2439   assert(cache != (Cache) NULL);
2440   cache_info=(CacheInfo *) cache;
2441   assert(cache_info->signature == MagickSignature);
2442   if (cache_info->storage_class == UndefinedClass)
2443     return((void *) NULL);
2444   return(nexus_info->metacontent);
2445 }
2446 \f
2447 /*
2448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2449 %                                                                             %
2450 %                                                                             %
2451 %                                                                             %
2452 %   G e t V i r t u a l M e t a c o n t e n t                                 %
2453 %                                                                             %
2454 %                                                                             %
2455 %                                                                             %
2456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2457 %
2458 %  GetVirtualMetacontent() returns the virtual metacontent corresponding with
2459 %  the last call to QueueAuthenticPixels() or GetVirtualPixels().  NULL is
2460 %  returned if the meta-content are not available.
2461 %
2462 %  The format of the GetVirtualMetacontent() method is:
2463 %
2464 %      const void *GetVirtualMetacontent(const Image *image)
2465 %
2466 %  A description of each parameter follows:
2467 %
2468 %    o image: the image.
2469 %
2470 */
2471 MagickExport const void *GetVirtualMetacontent(const Image *image)
2472 {
2473   CacheInfo
2474     *cache_info;
2475
2476   const int
2477     id = GetOpenMPThreadId();
2478
2479   const void
2480     *metacontent;
2481
2482   assert(image != (const Image *) NULL);
2483   assert(image->signature == MagickSignature);
2484   assert(image->cache != (Cache) NULL);
2485   cache_info=(CacheInfo *) image->cache;
2486   assert(cache_info->signature == MagickSignature);
2487   metacontent=cache_info->methods.get_virtual_metacontent_from_handler(image);
2488   if (metacontent != (void *) NULL)
2489     return(metacontent);
2490   assert(id < (int) cache_info->number_threads);
2491   metacontent=GetVirtualMetacontentFromNexus(cache_info,
2492     cache_info->nexus_info[id]);
2493   return(metacontent);
2494 }
2495 \f
2496 /*
2497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2498 %                                                                             %
2499 %                                                                             %
2500 %                                                                             %
2501 +   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                         %
2502 %                                                                             %
2503 %                                                                             %
2504 %                                                                             %
2505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2506 %
2507 %  GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
2508 %  pixel cache as defined by the geometry parameters.   A pointer to the pixels
2509 %  is returned if the pixels are transferred, otherwise a NULL is returned.
2510 %
2511 %  The format of the GetVirtualPixelsFromNexus() method is:
2512 %
2513 %      Quantum *GetVirtualPixelsFromNexus(const Image *image,
2514 %        const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2515 %        const size_t columns,const size_t rows,NexusInfo *nexus_info,
2516 %        ExceptionInfo *exception)
2517 %
2518 %  A description of each parameter follows:
2519 %
2520 %    o image: the image.
2521 %
2522 %    o virtual_pixel_method: the virtual pixel method.
2523 %
2524 %    o x,y,columns,rows:  These values define the perimeter of a region of
2525 %      pixels.
2526 %
2527 %    o nexus_info: the cache nexus to acquire.
2528 %
2529 %    o exception: return any errors or warnings in this structure.
2530 %
2531 */
2532
2533 static ssize_t
2534   DitherMatrix[64] =
2535   {
2536      0,  48,  12,  60,   3,  51,  15,  63,
2537     32,  16,  44,  28,  35,  19,  47,  31,
2538      8,  56,   4,  52,  11,  59,   7,  55,
2539     40,  24,  36,  20,  43,  27,  39,  23,
2540      2,  50,  14,  62,   1,  49,  13,  61,
2541     34,  18,  46,  30,  33,  17,  45,  29,
2542     10,  58,   6,  54,   9,  57,   5,  53,
2543     42,  26,  38,  22,  41,  25,  37,  21
2544   };
2545
2546 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
2547 {
2548   ssize_t
2549     index;
2550
2551   index=x+DitherMatrix[x & 0x07]-32L;
2552   if (index < 0L)
2553     return(0L);
2554   if (index >= (ssize_t) columns)
2555     return((ssize_t) columns-1L);
2556   return(index);
2557 }
2558
2559 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
2560 {
2561   ssize_t
2562     index;
2563
2564   index=y+DitherMatrix[y & 0x07]-32L;
2565   if (index < 0L)
2566     return(0L);
2567   if (index >= (ssize_t) rows)
2568     return((ssize_t) rows-1L);
2569   return(index);
2570 }
2571
2572 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
2573 {
2574   if (x < 0L)
2575     return(0L);
2576   if (x >= (ssize_t) columns)
2577     return((ssize_t) (columns-1));
2578   return(x);
2579 }
2580
2581 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
2582 {
2583   if (y < 0L)
2584     return(0L);
2585   if (y >= (ssize_t) rows)
2586     return((ssize_t) (rows-1));
2587   return(y);
2588 }
2589
2590 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
2591 {
2592   return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2593 }
2594
2595 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
2596 {
2597   return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2598 }
2599
2600 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
2601   const size_t extent)
2602 {
2603   MagickModulo
2604     modulo;
2605
2606   /*
2607     Compute the remainder of dividing offset by extent.  It returns not only
2608     the quotient (tile the offset falls in) but also the positive remainer
2609     within that tile such that 0 <= remainder < extent.  This method is
2610     essentially a ldiv() using a floored modulo division rather than the
2611     normal default truncated modulo division.
2612   */
2613   modulo.quotient=offset/(ssize_t) extent;
2614   if (offset < 0L)
2615     modulo.quotient--;
2616   modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
2617   return(modulo);
2618 }
2619
2620 MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
2621   const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2622   const size_t columns,const size_t rows,NexusInfo *nexus_info,
2623   ExceptionInfo *exception)
2624 {
2625   CacheInfo
2626     *cache_info;
2627
2628   MagickOffsetType
2629     offset;
2630
2631   MagickSizeType
2632     length,
2633     number_pixels;
2634
2635   NexusInfo
2636     **virtual_nexus;
2637
2638   Quantum
2639     *pixels,
2640     virtual_pixel[CompositePixelChannel];
2641
2642   RectangleInfo
2643     region;
2644
2645   register const Quantum
2646     *restrict p;
2647
2648   register const void
2649     *restrict r;
2650
2651   register Quantum
2652     *restrict q;
2653
2654   register ssize_t
2655     i,
2656     u;
2657
2658   register unsigned char
2659     *restrict s;
2660
2661   ssize_t
2662     v;
2663
2664   void
2665     *virtual_metacontent;
2666
2667   /*
2668     Acquire pixels.
2669   */
2670   assert(image != (const Image *) NULL);
2671   assert(image->signature == MagickSignature);
2672   assert(image->cache != (Cache) NULL);
2673   cache_info=(CacheInfo *) image->cache;
2674   assert(cache_info->signature == MagickSignature);
2675   if (cache_info->type == UndefinedCache)
2676     return((const Quantum *) NULL);
2677   region.x=x;
2678   region.y=y;
2679   region.width=columns;
2680   region.height=rows;
2681   pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,nexus_info,
2682     exception);
2683   if (pixels == (Quantum *) NULL)
2684     return((const Quantum *) NULL);
2685   q=pixels;
2686   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
2687     nexus_info->region.x;
2688   length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2689     nexus_info->region.width-1L;
2690   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2691   if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2692     if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
2693         (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
2694       {
2695         MagickBooleanType
2696           status;
2697
2698         /*
2699           Pixel request is inside cache extents.
2700         */
2701         if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
2702           return(q);
2703         status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2704         if (status == MagickFalse)
2705           return((const Quantum *) NULL);
2706         if (cache_info->metacontent_extent != 0)
2707           {
2708             status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2709             if (status == MagickFalse)
2710               return((const Quantum *) NULL);
2711           }
2712         return(q);
2713       }
2714   /*
2715     Pixel request is outside cache extents.
2716   */
2717   s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
2718   virtual_nexus=AcquirePixelCacheNexus(1);
2719   if (virtual_nexus == (NexusInfo **) NULL)
2720     {
2721       if (virtual_nexus != (NexusInfo **) NULL)
2722         virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
2723       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
2724         "UnableToGetCacheNexus","`%s'",image->filename);
2725       return((const Quantum *) NULL);
2726     }
2727   (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
2728     sizeof(*virtual_pixel));
2729   virtual_metacontent=(void *) NULL;
2730   switch (virtual_pixel_method)
2731   {
2732     case BackgroundVirtualPixelMethod:
2733     case BlackVirtualPixelMethod:
2734     case GrayVirtualPixelMethod:
2735     case TransparentVirtualPixelMethod:
2736     case MaskVirtualPixelMethod:
2737     case WhiteVirtualPixelMethod:
2738     case EdgeVirtualPixelMethod:
2739     case CheckerTileVirtualPixelMethod:
2740     case HorizontalTileVirtualPixelMethod:
2741     case VerticalTileVirtualPixelMethod:
2742     {
2743       if (cache_info->metacontent_extent != 0)
2744         {
2745           /*
2746             Acquire a metacontent buffer.
2747           */
2748           virtual_metacontent=(void *) AcquireQuantumMemory(1,
2749             cache_info->metacontent_extent);
2750           if (virtual_metacontent == (void *) NULL)
2751             {
2752               virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
2753               (void) ThrowMagickException(exception,GetMagickModule(),
2754                 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
2755               return((const Quantum *) NULL);
2756             }
2757           (void) ResetMagickMemory(virtual_metacontent,0,
2758             cache_info->metacontent_extent);
2759         }
2760       switch (virtual_pixel_method)
2761       {
2762         case BlackVirtualPixelMethod:
2763         {
2764           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2765             SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
2766           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2767           break;
2768         }
2769         case GrayVirtualPixelMethod:
2770         {
2771           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2772             SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2773               virtual_pixel);
2774           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2775           break;
2776         }
2777         case TransparentVirtualPixelMethod:
2778         {
2779           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2780             SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
2781           SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2782           break;
2783         }
2784         case MaskVirtualPixelMethod:
2785         case WhiteVirtualPixelMethod:
2786         {
2787           for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2788             SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2789           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2790           break;
2791         }
2792         default:
2793         {
2794           SetPixelRed(image,ClampToQuantum(image->background_color.red),
2795             virtual_pixel);
2796           SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2797             virtual_pixel);
2798           SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2799             virtual_pixel);
2800           SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2801             virtual_pixel);
2802           SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2803             virtual_pixel);
2804           break;
2805         }
2806       }
2807       break;
2808     }
2809     default:
2810       break;
2811   }
2812   for (v=0; v < (ssize_t) rows; v++)
2813   {
2814     for (u=0; u < (ssize_t) columns; u+=length)
2815     {
2816       length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
2817       if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
2818           (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
2819           (length == 0))
2820         {
2821           MagickModulo
2822             x_modulo,
2823             y_modulo;
2824
2825           /*
2826             Transfer a single pixel.
2827           */
2828           length=(MagickSizeType) 1;
2829           switch (virtual_pixel_method)
2830           {
2831             default:
2832             {
2833               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2834                 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
2835                 1UL,1UL,*virtual_nexus,exception);
2836               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2837               break;
2838             }
2839             case RandomVirtualPixelMethod:
2840             {
2841               if (cache_info->random_info == (RandomInfo *) NULL)
2842                 cache_info->random_info=AcquireRandomInfo();
2843               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2844                 RandomX(cache_info->random_info,cache_info->columns),
2845                 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
2846                 *virtual_nexus,exception);
2847               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2848               break;
2849             }
2850             case DitherVirtualPixelMethod:
2851             {
2852               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2853                 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
2854                 1UL,1UL,*virtual_nexus,exception);
2855               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2856               break;
2857             }
2858             case TileVirtualPixelMethod:
2859             {
2860               x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
2861               y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
2862               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2863                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2864                 exception);
2865               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2866               break;
2867             }
2868             case MirrorVirtualPixelMethod:
2869             {
2870               x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
2871               if ((x_modulo.quotient & 0x01) == 1L)
2872                 x_modulo.remainder=(ssize_t) cache_info->columns-
2873                   x_modulo.remainder-1L;
2874               y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
2875               if ((y_modulo.quotient & 0x01) == 1L)
2876                 y_modulo.remainder=(ssize_t) cache_info->rows-
2877                   y_modulo.remainder-1L;
2878               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2879                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2880                 exception);
2881               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2882               break;
2883             }
2884             case HorizontalTileEdgeVirtualPixelMethod:
2885             {
2886               x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
2887               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2888                 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
2889                 *virtual_nexus,exception);
2890               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2891               break;
2892             }
2893             case VerticalTileEdgeVirtualPixelMethod:
2894             {
2895               y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
2896               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2897                 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
2898                 *virtual_nexus,exception);
2899               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2900               break;
2901             }
2902             case BackgroundVirtualPixelMethod:
2903             case BlackVirtualPixelMethod:
2904             case GrayVirtualPixelMethod:
2905             case TransparentVirtualPixelMethod:
2906             case MaskVirtualPixelMethod:
2907             case WhiteVirtualPixelMethod:
2908             {
2909               p=virtual_pixel;
2910               r=virtual_metacontent;
2911               break;
2912             }
2913             case EdgeVirtualPixelMethod:
2914             case CheckerTileVirtualPixelMethod:
2915             {
2916               x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
2917               y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
2918               if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
2919                 {
2920                   p=virtual_pixel;
2921                   r=virtual_metacontent;
2922                   break;
2923                 }
2924               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2925                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2926                 exception);
2927               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2928               break;
2929             }
2930             case HorizontalTileVirtualPixelMethod:
2931             {
2932               if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
2933                 {
2934                   p=virtual_pixel;
2935                   r=virtual_metacontent;
2936                   break;
2937                 }
2938               x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
2939               y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
2940               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2941                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2942                 exception);
2943               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2944               break;
2945             }
2946             case VerticalTileVirtualPixelMethod:
2947             {
2948               if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
2949                 {
2950                   p=virtual_pixel;
2951                   r=virtual_metacontent;
2952                   break;
2953                 }
2954               x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
2955               y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
2956               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
2957                 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2958                 exception);
2959               r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2960               break;
2961             }
2962           }
2963           if (p == (const Quantum *) NULL)
2964             break;
2965           (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
2966             sizeof(*p));
2967           q+=cache_info->number_channels;
2968           if ((s != (void *) NULL) && (r != (const void *) NULL))
2969             {
2970               (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
2971               s+=cache_info->metacontent_extent;
2972             }
2973           continue;
2974         }
2975       /*
2976         Transfer a run of pixels.
2977       */
2978       p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
2979         length,1UL,*virtual_nexus,exception);
2980       if (p == (const Quantum *) NULL)
2981         break;
2982       r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2983       (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
2984       q+=length*cache_info->number_channels;
2985       if ((r != (void *) NULL) && (s != (const void *) NULL))
2986         {
2987           (void) memcpy(s,r,(size_t) length);
2988           s+=length*cache_info->metacontent_extent;
2989         }
2990     }
2991   }
2992   /*
2993     Free resources.
2994   */
2995   if (virtual_metacontent != (void *) NULL)
2996     virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
2997   virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
2998   return(pixels);
2999 }
3000 \f
3001 /*
3002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3003 %                                                                             %
3004 %                                                                             %
3005 %                                                                             %
3006 +   G e t V i r t u a l P i x e l C a c h e                                   %
3007 %                                                                             %
3008 %                                                                             %
3009 %                                                                             %
3010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3011 %
3012 %  GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3013 %  cache as defined by the geometry parameters.   A pointer to the pixels
3014 %  is returned if the pixels are transferred, otherwise a NULL is returned.
3015 %
3016 %  The format of the GetVirtualPixelCache() method is:
3017 %
3018 %      const Quantum *GetVirtualPixelCache(const Image *image,
3019 %        const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3020 %        const ssize_t y,const size_t columns,const size_t rows,
3021 %        ExceptionInfo *exception)
3022 %
3023 %  A description of each parameter follows:
3024 %
3025 %    o image: the image.
3026 %
3027 %    o virtual_pixel_method: the virtual pixel method.
3028 %
3029 %    o x,y,columns,rows:  These values define the perimeter of a region of
3030 %      pixels.
3031 %
3032 %    o exception: return any errors or warnings in this structure.
3033 %
3034 */
3035 static const Quantum *GetVirtualPixelCache(const Image *image,
3036   const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3037   const size_t columns,const size_t rows,ExceptionInfo *exception)
3038 {
3039   CacheInfo
3040     *cache_info;
3041
3042   const int
3043     id = GetOpenMPThreadId();
3044
3045   const Quantum
3046     *p;
3047
3048   assert(image != (const Image *) NULL);
3049   assert(image->signature == MagickSignature);
3050   assert(image->cache != (Cache) NULL);
3051   cache_info=(CacheInfo *) image->cache;
3052   assert(cache_info->signature == MagickSignature);
3053   assert(id < (int) cache_info->number_threads);
3054   p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3055     cache_info->nexus_info[id],exception);
3056   return(p);
3057 }
3058 \f
3059 /*
3060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3061 %                                                                             %
3062 %                                                                             %
3063 %                                                                             %
3064 %   G e t V i r t u a l P i x e l Q u e u e                                   %
3065 %                                                                             %
3066 %                                                                             %
3067 %                                                                             %
3068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3069 %
3070 %  GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3071 %  with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3072 %
3073 %  The format of the GetVirtualPixelQueue() method is:
3074 %
3075 %      const Quantum *GetVirtualPixelQueue(const Image image)
3076 %
3077 %  A description of each parameter follows:
3078 %
3079 %    o image: the image.
3080 %
3081 */
3082 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3083 {
3084   CacheInfo
3085     *cache_info;
3086
3087   const int
3088     id = GetOpenMPThreadId();
3089
3090   assert(image != (const Image *) NULL);
3091   assert(image->signature == MagickSignature);
3092   assert(image->cache != (Cache) NULL);
3093   cache_info=(CacheInfo *) image->cache;
3094   assert(cache_info->signature == MagickSignature);
3095   if (cache_info->methods.get_virtual_pixels_handler !=
3096        (GetVirtualPixelsHandler) NULL)
3097     return(cache_info->methods.get_virtual_pixels_handler(image));
3098   assert(id < (int) cache_info->number_threads);
3099   return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3100 }
3101 \f
3102 /*
3103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3104 %                                                                             %
3105 %                                                                             %
3106 %                                                                             %
3107 %   G e t V i r t u a l P i x e l s                                           %
3108 %                                                                             %
3109 %                                                                             %
3110 %                                                                             %
3111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3112 %
3113 %  GetVirtualPixels() returns an immutable pixel region. If the
3114 %  region is successfully accessed, a pointer to it is returned, otherwise
3115 %  NULL is returned.  The returned pointer may point to a temporary working
3116 %  copy of the pixels or it may point to the original pixels in memory.
3117 %  Performance is maximized if the selected region is part of one row, or one
3118 %  or more full rows, since there is opportunity to access the pixels in-place
3119 %  (without a copy) if the image is in memory, or in a memory-mapped file.  The
3120 %  returned pointer must *never* be deallocated by the user.
3121 %
3122 %  Pixels accessed via the returned pointer represent a simple array of type
3123 %  Quantum.  If the image type is CMYK or the storage class is PseudoClass,
3124 %  call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3125 %  access the meta-content (of type void) corresponding to the the
3126 %  region.
3127 %
3128 %  If you plan to modify the pixels, use GetAuthenticPixels() instead.
3129 %
3130 %  Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3131 %  safe.  In a threaded environment, use GetCacheViewVirtualPixels() or
3132 %  GetCacheViewAuthenticPixels() instead.
3133 %
3134 %  The format of the GetVirtualPixels() method is:
3135 %
3136 %      const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3137 %        const ssize_t y,const size_t columns,const size_t rows,
3138 %        ExceptionInfo *exception)
3139 %
3140 %  A description of each parameter follows:
3141 %
3142 %    o image: the image.
3143 %
3144 %    o x,y,columns,rows:  These values define the perimeter of a region of
3145 %      pixels.
3146 %
3147 %    o exception: return any errors or warnings in this structure.
3148 %
3149 */
3150 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3151   const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3152   ExceptionInfo *exception)
3153 {
3154   CacheInfo
3155     *cache_info;
3156
3157   const int
3158     id = GetOpenMPThreadId();
3159
3160   const Quantum
3161     *p;
3162
3163   assert(image != (const Image *) NULL);
3164   assert(image->signature == MagickSignature);
3165   assert(image->cache != (Cache) NULL);
3166   cache_info=(CacheInfo *) image->cache;
3167   assert(cache_info->signature == MagickSignature);
3168   if (cache_info->methods.get_virtual_pixel_handler !=
3169        (GetVirtualPixelHandler) NULL)
3170     return(cache_info->methods.get_virtual_pixel_handler(image,
3171       GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3172   assert(id < (int) cache_info->number_threads);
3173   p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3174     columns,rows,cache_info->nexus_info[id],exception);
3175   return(p);
3176 }
3177 \f
3178 /*
3179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3180 %                                                                             %
3181 %                                                                             %
3182 %                                                                             %
3183 +   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                         %
3184 %                                                                             %
3185 %                                                                             %
3186 %                                                                             %
3187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3188 %
3189 %  GetVirtualPixelsCache() returns the pixels associated corresponding with the
3190 %  last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3191 %
3192 %  The format of the GetVirtualPixelsCache() method is:
3193 %
3194 %      Quantum *GetVirtualPixelsCache(const Image *image)
3195 %
3196 %  A description of each parameter follows:
3197 %
3198 %    o image: the image.
3199 %
3200 */
3201 static const Quantum *GetVirtualPixelsCache(const Image *image)
3202 {
3203   CacheInfo
3204     *cache_info;
3205
3206   const int
3207     id = GetOpenMPThreadId();
3208
3209   assert(image != (const Image *) NULL);
3210   assert(image->signature == MagickSignature);
3211   assert(image->cache != (Cache) NULL);
3212   cache_info=(CacheInfo *) image->cache;
3213   assert(cache_info->signature == MagickSignature);
3214   assert(id < (int) cache_info->number_threads);
3215   return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3216 }
3217 \f
3218 /*
3219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3220 %                                                                             %
3221 %                                                                             %
3222 %                                                                             %
3223 +   G e t V i r t u a l P i x e l s N e x u s                                 %
3224 %                                                                             %
3225 %                                                                             %
3226 %                                                                             %
3227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3228 %
3229 %  GetVirtualPixelsNexus() returns the pixels associated with the specified
3230 %  cache nexus.
3231 %
3232 %  The format of the GetVirtualPixelsNexus() method is:
3233 %
3234 %      const Quantum *GetVirtualPixelsNexus(const Cache cache,
3235 %        NexusInfo *nexus_info)
3236 %
3237 %  A description of each parameter follows:
3238 %
3239 %    o cache: the pixel cache.
3240 %
3241 %    o nexus_info: the cache nexus to return the colormap pixels.
3242 %
3243 */
3244 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
3245   NexusInfo *nexus_info)
3246 {
3247   CacheInfo
3248     *cache_info;
3249
3250   assert(cache != (Cache) NULL);
3251   cache_info=(CacheInfo *) cache;
3252   assert(cache_info->signature == MagickSignature);
3253   if (cache_info->storage_class == UndefinedClass)
3254     return((Quantum *) NULL);
3255   return((const Quantum *) nexus_info->pixels);
3256 }
3257 \f
3258 /*
3259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3260 %                                                                             %
3261 %                                                                             %
3262 %                                                                             %
3263 +   O p e n P i x e l C a c h e                                               %
3264 %                                                                             %
3265 %                                                                             %
3266 %                                                                             %
3267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3268 %
3269 %  OpenPixelCache() allocates the pixel cache.  This includes defining the cache
3270 %  dimensions, allocating space for the image pixels and optionally the
3271 %  metacontent, and memory mapping the cache if it is disk based.  The cache
3272 %  nexus array is initialized as well.
3273 %
3274 %  The format of the OpenPixelCache() method is:
3275 %
3276 %      MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3277 %        ExceptionInfo *exception)
3278 %
3279 %  A description of each parameter follows:
3280 %
3281 %    o image: the image.
3282 %
3283 %    o mode: ReadMode, WriteMode, or IOMode.
3284 %
3285 %    o exception: return any errors or warnings in this structure.
3286 %
3287 */
3288
3289 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3290 {
3291   cache_info->mapped=MagickFalse;
3292   cache_info->pixels=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
3293     (size_t) cache_info->length));
3294   if (cache_info->pixels == (Quantum *) NULL)
3295     {
3296       cache_info->mapped=MagickTrue;
3297       cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3298         cache_info->length);
3299     }
3300 }
3301
3302 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3303   const MapMode mode)
3304 {
3305   int
3306     file;
3307
3308   /*
3309     Open pixel cache on disk.
3310   */
3311   if (cache_info->file != -1)
3312     return(MagickTrue);  /* cache already open */
3313   if (*cache_info->cache_filename == '\0')
3314     file=AcquireUniqueFileResource(cache_info->cache_filename);
3315   else
3316     switch (mode)
3317     {
3318       case ReadMode:
3319       {
3320         file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3321         break;
3322       }
3323       case WriteMode:
3324       {
3325         file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3326           O_BINARY | O_EXCL,S_MODE);
3327         if (file == -1)
3328           file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3329         break;
3330       }
3331       case IOMode:
3332       default:
3333       {
3334         file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3335           O_EXCL,S_MODE);
3336         if (file == -1)
3337           file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3338         break;
3339       }
3340     }
3341   if (file == -1)
3342     return(MagickFalse);
3343   (void) AcquireMagickResource(FileResource,1);
3344   cache_info->file=file;
3345   cache_info->mode=mode;
3346   return(MagickTrue);
3347 }
3348
3349 static inline MagickOffsetType WritePixelCacheRegion(
3350   const CacheInfo *restrict cache_info,const MagickOffsetType offset,
3351   const MagickSizeType length,const unsigned char *restrict buffer)
3352 {
3353   register MagickOffsetType
3354     i;
3355
3356   ssize_t
3357     count;
3358
3359 #if !defined(MAGICKCORE_HAVE_PWRITE)
3360   if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3361     return((MagickOffsetType) -1);
3362 #endif
3363   count=0;
3364   for (i=0; i < (MagickOffsetType) length; i+=count)
3365   {
3366 #if !defined(MAGICKCORE_HAVE_PWRITE)
3367     count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
3368       (MagickSizeType) SSIZE_MAX));
3369 #else
3370     count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
3371       (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
3372 #endif
3373     if (count <= 0)
3374       {
3375         count=0;
3376         if (errno != EINTR)
3377           break;
3378       }
3379   }
3380   return(i);
3381 }
3382
3383 static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3384 {
3385   CacheInfo
3386     *cache_info;
3387
3388   MagickOffsetType
3389     count,
3390     extent,
3391     offset;
3392
3393   cache_info=(CacheInfo *) image->cache;
3394   if (image->debug != MagickFalse)
3395     {
3396       char
3397         format[MaxTextExtent],
3398         message[MaxTextExtent];
3399
3400       (void) FormatMagickSize(length,MagickFalse,format);
3401       (void) FormatLocaleString(message,MaxTextExtent,
3402         "extend %s (%s[%d], disk, %s)",cache_info->filename,
3403         cache_info->cache_filename,cache_info->file,format);
3404       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3405     }
3406   if (length != (MagickSizeType) ((MagickOffsetType) length))
3407     return(MagickFalse);
3408   offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3409   if (offset < 0)
3410     return(MagickFalse);
3411   if ((MagickSizeType) offset >= length)
3412     return(MagickTrue);
3413   extent=(MagickOffsetType) length-1;
3414   count=WritePixelCacheRegion(cache_info,extent,1,(const unsigned char *) "");
3415 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3416   if (cache_info->synchronize != MagickFalse)
3417     {
3418       int
3419         status;
3420
3421       status=posix_fallocate(cache_info->file,offset+1,extent-offset);
3422       if (status != 0)
3423         return(MagickFalse);
3424     }
3425 #endif
3426   return(count != (MagickOffsetType) 1 ? MagickFalse : MagickTrue);
3427 }
3428
3429 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3430   ExceptionInfo *exception)
3431 {
3432   CacheInfo
3433     *cache_info,
3434     source_info;
3435
3436   char
3437     format[MaxTextExtent],
3438     message[MaxTextExtent];
3439
3440   const char
3441     *type;
3442
3443   MagickBooleanType
3444     status;
3445
3446   MagickSizeType
3447     length,
3448     number_pixels;
3449
3450   size_t
3451     columns,
3452     packet_size;
3453
3454   assert(image != (const Image *) NULL);
3455   assert(image->signature == MagickSignature);
3456   assert(image->cache != (Cache) NULL);
3457   if (image->debug != MagickFalse)
3458     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3459   if ((image->columns == 0) || (image->rows == 0))
3460     ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3461   cache_info=(CacheInfo *) image->cache;
3462   assert(cache_info->signature == MagickSignature);
3463   source_info=(*cache_info);
3464   source_info.file=(-1);
3465   (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
3466     image->filename,(double) GetImageIndexInList(image));
3467   cache_info->storage_class=image->storage_class;
3468   cache_info->colorspace=image->colorspace;
3469   cache_info->alpha_trait=image->alpha_trait;
3470   cache_info->mask=image->mask;
3471   cache_info->rows=image->rows;
3472   cache_info->columns=image->columns;
3473   InitializePixelChannelMap(image);
3474   cache_info->number_channels=GetPixelChannels(image);
3475   (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3476     sizeof(*image->channel_map));
3477   cache_info->metacontent_extent=image->metacontent_extent;
3478   cache_info->mode=mode;
3479   if (image->ping != MagickFalse)
3480     {
3481       cache_info->type=PingCache;
3482       cache_info->pixels=(Quantum *) NULL;
3483       cache_info->metacontent=(void *) NULL;
3484       cache_info->length=0;
3485       return(MagickTrue);
3486     }
3487   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3488   packet_size=cache_info->number_channels*sizeof(Quantum);
3489   if (image->metacontent_extent != 0)
3490     packet_size+=cache_info->metacontent_extent;
3491   length=number_pixels*packet_size;
3492   columns=(size_t) (length/cache_info->rows/packet_size);
3493   if (cache_info->columns != columns)
3494     ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
3495       image->filename);
3496   cache_info->length=length;
3497   status=AcquireMagickResource(AreaResource,cache_info->length);
3498   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3499     cache_info->metacontent_extent);
3500   if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
3501     {
3502       status=AcquireMagickResource(MemoryResource,cache_info->length);
3503       if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
3504           (cache_info->type == MemoryCache))
3505         {
3506           AllocatePixelCachePixels(cache_info);
3507           if (cache_info->pixels == (Quantum *) NULL)
3508             cache_info->pixels=source_info.pixels;
3509           else
3510             {
3511               /*
3512                 Create memory pixel cache.
3513               */
3514               status=MagickTrue;
3515               cache_info->type=MemoryCache;
3516               cache_info->metacontent=(void *) NULL;
3517               if (cache_info->metacontent_extent != 0)
3518                 cache_info->metacontent=(void *) (cache_info->pixels+
3519                   number_pixels*cache_info->number_channels);
3520               if ((source_info.storage_class != UndefinedClass) &&
3521                   (mode != ReadMode))
3522                 {
3523                   status=ClonePixelCacheRepository(cache_info,&source_info,
3524                     exception);
3525                   RelinquishPixelCachePixels(&source_info);
3526                 }
3527               if (image->debug != MagickFalse)
3528                 {
3529                   (void) FormatMagickSize(cache_info->length,MagickTrue,format);
3530                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3531                     cache_info->type);
3532                   (void) FormatLocaleString(message,MaxTextExtent,
3533                     "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3534                     cache_info->filename,cache_info->mapped != MagickFalse ?
3535                     "Anonymous" : "Heap",type,(double) cache_info->columns,
3536                     (double) cache_info->rows,(double)
3537                     cache_info->number_channels,format);
3538                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3539                     message);
3540                 }
3541               return(status);
3542             }
3543         }
3544       RelinquishMagickResource(MemoryResource,cache_info->length);
3545     }
3546   /*
3547     Create pixel cache on disk.
3548   */
3549   status=AcquireMagickResource(DiskResource,cache_info->length);
3550   if ((status == MagickFalse) || (cache_info->type == DistributedCache))
3551     {
3552       DistributeCacheInfo
3553         *server_info;
3554
3555       if (cache_info->type == DistributedCache)
3556         RelinquishMagickResource(DiskResource,cache_info->length);
3557       server_info=AcquireDistributeCacheInfo(exception);
3558       if (server_info != (DistributeCacheInfo *) NULL)
3559         {
3560           status=OpenDistributePixelCache(server_info,image);
3561           if (status == MagickFalse)
3562             {
3563               ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3564                 GetDistributeCacheHostname(server_info));
3565               server_info=DestroyDistributeCacheInfo(server_info);
3566             }
3567           else
3568             {
3569               /*
3570                 Create a distributed pixel cache.
3571               */
3572               cache_info->type=DistributedCache;
3573               cache_info->server_info=server_info;
3574               (void) FormatLocaleString(cache_info->cache_filename,
3575                 MaxTextExtent,"%s:%d",
3576                 GetDistributeCacheHostname(cache_info->server_info),
3577                 GetDistributeCachePort(cache_info->server_info));
3578               if ((source_info.storage_class != UndefinedClass) &&
3579                   (mode != ReadMode))
3580                 {
3581                   status=ClonePixelCacheRepository(cache_info,&source_info,
3582                     exception);
3583                   RelinquishPixelCachePixels(&source_info);
3584                 }
3585               if (image->debug != MagickFalse)
3586                 {
3587                   (void) FormatMagickSize(cache_info->length,MagickFalse,
3588                     format);
3589                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3590                     cache_info->type);
3591                   (void) FormatLocaleString(message,MaxTextExtent,
3592                     "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3593                     cache_info->filename,cache_info->cache_filename,
3594                     GetDistributeCacheFile(cache_info->server_info),type,
3595                     (double) cache_info->columns,(double) cache_info->rows,
3596                     (double) cache_info->number_channels,format);
3597                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3598                     message);
3599                 }
3600               return(status);
3601             }
3602         }
3603       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3604         "CacheResourcesExhausted","`%s'",image->filename);
3605       return(MagickFalse);
3606     }
3607   if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3608     {
3609       (void) ClosePixelCacheOnDisk(cache_info);
3610       *cache_info->cache_filename='\0';
3611     }
3612   if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3613     {
3614       RelinquishMagickResource(DiskResource,cache_info->length);
3615       ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3616         image->filename);
3617       return(MagickFalse);
3618     }
3619   status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3620     cache_info->length);
3621   if (status == MagickFalse)
3622     {
3623       ThrowFileException(exception,CacheError,"UnableToExtendCache",
3624         image->filename);
3625       return(MagickFalse);
3626     }
3627   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3628     cache_info->metacontent_extent);
3629   if (length != (MagickSizeType) ((size_t) length))
3630     cache_info->type=DiskCache;
3631   else
3632     {
3633       status=AcquireMagickResource(MapResource,cache_info->length);
3634       if ((status == MagickFalse) && (cache_info->type != MapCache) &&
3635           (cache_info->type != MemoryCache))
3636         cache_info->type=DiskCache;
3637       else
3638         {
3639           cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3640             cache_info->offset,(size_t) cache_info->length);
3641           if (cache_info->pixels == (Quantum *) NULL)
3642             {
3643               cache_info->type=DiskCache;
3644               cache_info->pixels=source_info.pixels;
3645             }
3646           else
3647             {
3648               /*
3649                 Create file-backed memory-mapped pixel cache.
3650               */
3651               status=MagickTrue;
3652               (void) ClosePixelCacheOnDisk(cache_info);
3653               cache_info->type=MapCache;
3654               cache_info->mapped=MagickTrue;
3655               cache_info->metacontent=(void *) NULL;
3656               if (cache_info->metacontent_extent != 0)
3657                 cache_info->metacontent=(void *) (cache_info->pixels+
3658                   number_pixels*cache_info->number_channels);
3659               if ((source_info.storage_class != UndefinedClass) &&
3660                   (mode != ReadMode))
3661                 {
3662                   status=ClonePixelCacheRepository(cache_info,&source_info,
3663                     exception);
3664                   RelinquishPixelCachePixels(&source_info);
3665                 }
3666               if (image->debug != MagickFalse)
3667                 {
3668                   (void) FormatMagickSize(cache_info->length,MagickTrue,format);
3669                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3670                     cache_info->type);
3671                   (void) FormatLocaleString(message,MaxTextExtent,
3672                     "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3673                     cache_info->filename,cache_info->cache_filename,
3674                     cache_info->file,type,(double) cache_info->columns,(double)
3675                     cache_info->rows,(double) cache_info->number_channels,
3676                     format);
3677                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3678                     message);
3679                 }
3680               return(status);
3681             }
3682         }
3683       RelinquishMagickResource(MapResource,cache_info->length);
3684     }
3685   status=MagickTrue;
3686   if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3687     {
3688       status=ClonePixelCacheRepository(cache_info,&source_info,exception);
3689       RelinquishPixelCachePixels(&source_info);
3690     }
3691   if (image->debug != MagickFalse)
3692     {
3693       (void) FormatMagickSize(cache_info->length,MagickFalse,format);
3694       type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3695         cache_info->type);
3696       (void) FormatLocaleString(message,MaxTextExtent,
3697         "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
3698         cache_info->cache_filename,cache_info->file,type,(double)
3699         cache_info->columns,(double) cache_info->rows,(double)
3700         cache_info->number_channels,format);
3701       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3702     }
3703   return(status);
3704 }
3705 \f
3706 /*
3707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3708 %                                                                             %
3709 %                                                                             %
3710 %                                                                             %
3711 +   P e r s i s t P i x e l C a c h e                                         %
3712 %                                                                             %
3713 %                                                                             %
3714 %                                                                             %
3715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3716 %
3717 %  PersistPixelCache() attaches to or initializes a persistent pixel cache.  A
3718 %  persistent pixel cache is one that resides on disk and is not destroyed
3719 %  when the program exits.
3720 %
3721 %  The format of the PersistPixelCache() method is:
3722 %
3723 %      MagickBooleanType PersistPixelCache(Image *image,const char *filename,
3724 %        const MagickBooleanType attach,MagickOffsetType *offset,
3725 %        ExceptionInfo *exception)
3726 %
3727 %  A description of each parameter follows:
3728 %
3729 %    o image: the image.
3730 %
3731 %    o filename: the persistent pixel cache filename.
3732 %
3733 %    o attach: A value other than zero initializes the persistent pixel cache.
3734 %
3735 %    o initialize: A value other than zero initializes the persistent pixel
3736 %      cache.
3737 %
3738 %    o offset: the offset in the persistent cache to store pixels.
3739 %
3740 %    o exception: return any errors or warnings in this structure.
3741 %
3742 */
3743 MagickExport MagickBooleanType PersistPixelCache(Image *image,
3744   const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
3745   ExceptionInfo *exception)
3746 {
3747   CacheInfo
3748     *cache_info,
3749     *clone_info;
3750
3751   Image
3752     clone_image;
3753
3754   MagickBooleanType
3755     status;
3756
3757   ssize_t
3758     page_size;
3759
3760   assert(image != (Image *) NULL);
3761   assert(image->signature == MagickSignature);
3762   if (image->debug != MagickFalse)
3763     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3764   assert(image->cache != (void *) NULL);
3765   assert(filename != (const char *) NULL);
3766   assert(offset != (MagickOffsetType *) NULL);
3767   page_size=GetMagickPageSize();
3768   cache_info=(CacheInfo *) image->cache;
3769   assert(cache_info->signature == MagickSignature);
3770   if (attach != MagickFalse)
3771     {
3772       /*
3773         Attach existing persistent pixel cache.
3774       */
3775       if (image->debug != MagickFalse)
3776         (void) LogMagickEvent(CacheEvent,GetMagickModule(),
3777           "attach persistent cache");
3778       (void) CopyMagickString(cache_info->cache_filename,filename,
3779         MaxTextExtent);
3780       cache_info->type=DiskCache;
3781       cache_info->offset=(*offset);
3782       if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
3783         return(MagickFalse);
3784       *offset+=cache_info->length+page_size-(cache_info->length % page_size);
3785       return(MagickTrue);
3786     }
3787   if ((cache_info->mode != ReadMode) &&
3788       ((cache_info->type == DiskCache) || (cache_info->type == MapCache)) &&
3789       (cache_info->reference_count == 1))
3790     {
3791       LockSemaphoreInfo(cache_info->semaphore);
3792       if ((cache_info->mode != ReadMode) &&
3793           ((cache_info->type == DiskCache) || (cache_info->type == MapCache)) &&
3794           (cache_info->reference_count == 1))
3795         {
3796           int
3797             status;
3798
3799           /*
3800             Usurp existing persistent pixel cache.
3801           */
3802           status=rename_utf8(cache_info->cache_filename,filename);
3803           if (status == 0)
3804             {
3805               (void) CopyMagickString(cache_info->cache_filename,filename,
3806                 MaxTextExtent);
3807               *offset+=cache_info->length+page_size-(cache_info->length %
3808                 page_size);
3809               UnlockSemaphoreInfo(cache_info->semaphore);
3810               cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
3811               if (image->debug != MagickFalse)
3812                 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
3813                   "Usurp resident persistent cache");
3814               return(MagickTrue);
3815             }
3816         }
3817       UnlockSemaphoreInfo(cache_info->semaphore);
3818     }
3819   /*
3820     Clone persistent pixel cache.
3821   */
3822   clone_image=(*image);
3823   clone_info=(CacheInfo *) clone_image.cache;
3824   image->cache=ClonePixelCache(cache_info);
3825   cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
3826   (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
3827   cache_info->type=DiskCache;
3828   cache_info->offset=(*offset);
3829   cache_info=(CacheInfo *) image->cache;
3830   status=OpenPixelCache(image,IOMode,exception);
3831   if (status != MagickFalse)
3832     status=ClonePixelCacheRepository(cache_info,clone_info,exception);
3833   *offset+=cache_info->length+page_size-(cache_info->length % page_size);
3834   clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
3835   return(status);
3836 }
3837 \f
3838 /*
3839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3840 %                                                                             %
3841 %                                                                             %
3842 %                                                                             %
3843 +   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                 %
3844 %                                                                             %
3845 %                                                                             %
3846 %                                                                             %
3847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3848 %
3849 %  QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
3850 %  defined by the region rectangle and returns a pointer to the region.  This
3851 %  region is subsequently transferred from the pixel cache with
3852 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
3853 %  pixels are transferred, otherwise a NULL is returned.
3854 %
3855 %  The format of the QueueAuthenticPixelCacheNexus() method is:
3856 %
3857 %      Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
3858 %        const ssize_t y,const size_t columns,const size_t rows,
3859 %        const MagickBooleanType clone,NexusInfo *nexus_info,
3860 %        ExceptionInfo *exception)
3861 %
3862 %  A description of each parameter follows:
3863 %
3864 %    o image: the image.
3865 %
3866 %    o x,y,columns,rows:  These values define the perimeter of a region of
3867 %      pixels.
3868 %
3869 %    o nexus_info: the cache nexus to set.
3870 %
3871 %    o clone: clone the pixel cache.
3872 %
3873 %    o exception: return any errors or warnings in this structure.
3874 %
3875 */
3876 MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
3877   const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3878   const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
3879 {
3880   CacheInfo
3881     *cache_info;
3882
3883   MagickOffsetType
3884     offset;
3885
3886   MagickSizeType
3887     number_pixels;
3888
3889   Quantum
3890     *pixels;
3891
3892   RectangleInfo
3893     region;
3894
3895   /*
3896     Validate pixel cache geometry.
3897   */
3898   assert(image != (const Image *) NULL);
3899   assert(image->signature == MagickSignature);
3900   assert(image->cache != (Cache) NULL);
3901   cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
3902   if (cache_info == (Cache) NULL)
3903     return((Quantum *) NULL);
3904   assert(cache_info->signature == MagickSignature);
3905   if ((cache_info->columns == 0) && (cache_info->rows == 0))
3906     {
3907       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3908         "NoPixelsDefinedInCache","`%s'",image->filename);
3909       return((Quantum *) NULL);
3910     }
3911   if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
3912       (y >= (ssize_t) cache_info->rows))
3913     {
3914       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3915         "PixelsAreNotAuthentic","`%s'",image->filename);
3916       return((Quantum *) NULL);
3917     }
3918   offset=(MagickOffsetType) y*cache_info->columns+x;
3919   if (offset < 0)
3920     return((Quantum *) NULL);
3921   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3922   offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
3923   if ((MagickSizeType) offset >= number_pixels)
3924     return((Quantum *) NULL);
3925   /*
3926     Return pixel cache.
3927   */
3928   region.x=x;
3929   region.y=y;
3930   region.width=columns;
3931   region.height=rows;
3932   pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,&region,nexus_info,
3933     exception);
3934   return(pixels);
3935 }
3936 \f
3937 /*
3938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3939 %                                                                             %
3940 %                                                                             %
3941 %                                                                             %
3942 +   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                         %
3943 %                                                                             %
3944 %                                                                             %
3945 %                                                                             %
3946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3947 %
3948 %  QueueAuthenticPixelsCache() allocates an region to store image pixels as
3949 %  defined by the region rectangle and returns a pointer to the region.  This
3950 %  region is subsequently transferred from the pixel cache with
3951 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
3952 %  pixels are transferred, otherwise a NULL is returned.
3953 %
3954 %  The format of the QueueAuthenticPixelsCache() method is:
3955 %
3956 %      Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
3957 %        const ssize_t y,const size_t columns,const size_t rows,
3958 %        ExceptionInfo *exception)
3959 %
3960 %  A description of each parameter follows:
3961 %
3962 %    o image: the image.
3963 %
3964 %    o x,y,columns,rows:  These values define the perimeter of a region of
3965 %      pixels.
3966 %
3967 %    o exception: return any errors or warnings in this structure.
3968 %
3969 */
3970 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
3971   const ssize_t y,const size_t columns,const size_t rows,
3972   ExceptionInfo *exception)
3973 {
3974   CacheInfo
3975     *cache_info;
3976
3977   const int
3978     id = GetOpenMPThreadId();
3979
3980   Quantum
3981     *q;
3982
3983   assert(image != (const Image *) NULL);
3984   assert(image->signature == MagickSignature);
3985   assert(image->cache != (Cache) NULL);
3986   cache_info=(CacheInfo *) image->cache;
3987   assert(cache_info->signature == MagickSignature);
3988   assert(id < (int) cache_info->number_threads);
3989   q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
3990     cache_info->nexus_info[id],exception);
3991   return(q);
3992 }
3993 \f
3994 /*
3995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3996 %                                                                             %
3997 %                                                                             %
3998 %                                                                             %
3999 %   Q u e u e A u t h e n t i c P i x e l s                                   %
4000 %                                                                             %
4001 %                                                                             %
4002 %                                                                             %
4003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4004 %
4005 %  QueueAuthenticPixels() queues a mutable pixel region.  If the region is
4006 %  successfully initialized a pointer to a Quantum array representing the
4007 %  region is returned, otherwise NULL is returned.  The returned pointer may
4008 %  point to a temporary working buffer for the pixels or it may point to the
4009 %  final location of the pixels in memory.
4010 %
4011 %  Write-only access means that any existing pixel values corresponding to
4012 %  the region are ignored.  This is useful if the initial image is being
4013 %  created from scratch, or if the existing pixel values are to be
4014 %  completely replaced without need to refer to their pre-existing values.
4015 %  The application is free to read and write the pixel buffer returned by
4016 %  QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4017 %  initialize the pixel array values. Initializing pixel array values is the
4018 %  application's responsibility.
4019 %
4020 %  Performance is maximized if the selected region is part of one row, or
4021 %  one or more full rows, since then there is opportunity to access the
4022 %  pixels in-place (without a copy) if the image is in memory, or in a
4023 %  memory-mapped file. The returned pointer must *never* be deallocated
4024 %  by the user.
4025 %
4026 %  Pixels accessed via the returned pointer represent a simple array of type
4027 %  Quantum. If the image type is CMYK or the storage class is PseudoClass,
4028 %  call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4029 %  obtain the meta-content (of type void) corresponding to the region.
4030 %  Once the Quantum (and/or Quantum) array has been updated, the
4031 %  changes must be saved back to the underlying image using
4032 %  SyncAuthenticPixels() or they may be lost.
4033 %
4034 %  The format of the QueueAuthenticPixels() method is:
4035 %
4036 %      Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4037 %        const ssize_t y,const size_t columns,const size_t rows,
4038 %        ExceptionInfo *exception)
4039 %
4040 %  A description of each parameter follows:
4041 %
4042 %    o image: the image.
4043 %
4044 %    o x,y,columns,rows:  These values define the perimeter of a region of
4045 %      pixels.
4046 %
4047 %    o exception: return any errors or warnings in this structure.
4048 %
4049 */
4050 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4051   const ssize_t y,const size_t columns,const size_t rows,
4052   ExceptionInfo *exception)
4053 {
4054   CacheInfo
4055     *cache_info;
4056
4057   const int
4058     id = GetOpenMPThreadId();
4059
4060   Quantum
4061     *q;
4062
4063   assert(image != (Image *) NULL);
4064   assert(image->signature == MagickSignature);
4065   assert(image->cache != (Cache) NULL);
4066   cache_info=(CacheInfo *) image->cache;
4067   assert(cache_info->signature == MagickSignature);
4068   if (cache_info->methods.queue_authentic_pixels_handler !=
4069       (QueueAuthenticPixelsHandler) NULL)
4070     {
4071       q=cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4072         rows,exception);
4073       return(q);
4074     }
4075   assert(id < (int) cache_info->number_threads);
4076   q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4077     cache_info->nexus_info[id],exception);
4078   return(q);
4079 }
4080 \f
4081 /*
4082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4083 %                                                                             %
4084 %                                                                             %
4085 %                                                                             %
4086 +   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                         %
4087 %                                                                             %
4088 %                                                                             %
4089 %                                                                             %
4090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4091 %
4092 %  ReadPixelCacheMetacontent() reads metacontent from the specified region of
4093 %  the pixel cache.
4094 %
4095 %  The format of the ReadPixelCacheMetacontent() method is:
4096 %
4097 %      MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4098 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4099 %
4100 %  A description of each parameter follows:
4101 %
4102 %    o cache_info: the pixel cache.
4103 %
4104 %    o nexus_info: the cache nexus to read the metacontent.
4105 %
4106 %    o exception: return any errors or warnings in this structure.
4107 %
4108 */
4109
4110 static inline MagickOffsetType ReadPixelCacheRegion(
4111   const CacheInfo *restrict cache_info,const MagickOffsetType offset,
4112   const MagickSizeType length,unsigned char *restrict buffer)
4113 {
4114   register MagickOffsetType
4115     i;
4116
4117   ssize_t
4118     count;
4119
4120 #if !defined(MAGICKCORE_HAVE_PREAD)
4121   if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4122     return((MagickOffsetType) -1);
4123 #endif
4124   count=0;
4125   for (i=0; i < (MagickOffsetType) length; i+=count)
4126   {
4127 #if !defined(MAGICKCORE_HAVE_PREAD)
4128     count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
4129       (MagickSizeType) SSIZE_MAX));
4130 #else
4131     count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
4132       (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
4133 #endif
4134     if (count <= 0)
4135       {
4136         count=0;
4137         if (errno != EINTR)
4138           break;
4139       }
4140   }
4141   return(i);
4142 }
4143
4144 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4145   NexusInfo *nexus_info,ExceptionInfo *exception)
4146 {
4147   MagickOffsetType
4148     count,
4149     offset;
4150
4151   MagickSizeType
4152     extent,
4153     length;
4154
4155   register ssize_t
4156     y;
4157
4158   register unsigned char
4159     *restrict q;
4160
4161   size_t
4162     rows;
4163
4164   if (cache_info->metacontent_extent == 0)
4165     return(MagickFalse);
4166   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4167     return(MagickTrue);
4168   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4169     nexus_info->region.x;
4170   length=(MagickSizeType) nexus_info->region.width*
4171     cache_info->metacontent_extent;
4172   extent=length*nexus_info->region.height;
4173   rows=nexus_info->region.height;
4174   y=0;
4175   q=(unsigned char *) nexus_info->metacontent;
4176   switch (cache_info->type)
4177   {
4178     case MemoryCache:
4179     case MapCache:
4180     {
4181       register unsigned char
4182         *restrict p;
4183
4184       /*
4185         Read meta-content from memory.
4186       */
4187       if ((cache_info->columns == nexus_info->region.width) &&
4188           (extent == (MagickSizeType) ((size_t) extent)))
4189         {
4190           length=extent;
4191           rows=1UL;
4192         }
4193       p=(unsigned char *) cache_info->metacontent+offset*
4194         cache_info->metacontent_extent;
4195       for (y=0; y < (ssize_t) rows; y++)
4196       {
4197         (void) memcpy(q,p,(size_t) length);
4198         p+=cache_info->metacontent_extent*cache_info->columns;
4199         q+=cache_info->metacontent_extent*nexus_info->region.width;
4200       }
4201       break;
4202     }
4203     case DiskCache:
4204     {
4205       /*
4206         Read meta content from disk.
4207       */
4208       LockSemaphoreInfo(cache_info->file_semaphore);
4209       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4210         {
4211           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4212             cache_info->cache_filename);
4213           UnlockSemaphoreInfo(cache_info->file_semaphore);
4214           return(MagickFalse);
4215         }
4216       if ((cache_info->columns == nexus_info->region.width) &&
4217           (extent <= MagickMaxBufferExtent))
4218         {
4219           length=extent;
4220           rows=1UL;
4221         }
4222       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4223       for (y=0; y < (ssize_t) rows; y++)
4224       {
4225         count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4226           cache_info->number_channels*sizeof(Quantum)+offset*
4227           cache_info->metacontent_extent,length,(unsigned char *) q);
4228         if (count != (MagickOffsetType) length)
4229           break;
4230         offset+=cache_info->columns;
4231         q+=cache_info->metacontent_extent*nexus_info->region.width;
4232       }
4233       if (IsFileDescriptorLimitExceeded() != MagickFalse)
4234         (void) ClosePixelCacheOnDisk(cache_info);
4235       UnlockSemaphoreInfo(cache_info->file_semaphore);
4236       break;
4237     }
4238     case DistributedCache:
4239     {
4240       RectangleInfo
4241         region;
4242
4243       /*
4244         Read metacontent from distributed cache.
4245       */
4246       LockSemaphoreInfo(cache_info->file_semaphore);
4247       region=nexus_info->region;
4248       if ((cache_info->columns != nexus_info->region.width) ||
4249           (extent > MagickMaxBufferExtent))
4250         region.height=1UL;
4251       else
4252         {
4253           length=extent;
4254           rows=1UL;
4255         }
4256       for (y=0; y < (ssize_t) rows; y++)
4257       {
4258         count=ReadDistributePixelCacheMetacontent(cache_info->server_info,
4259           &region,length,(unsigned char *) q);
4260         if (count != (MagickOffsetType) length)
4261           break;
4262         q+=cache_info->metacontent_extent*nexus_info->region.width;
4263         region.y++;
4264       }
4265       UnlockSemaphoreInfo(cache_info->file_semaphore);
4266       break;
4267     }
4268     default:
4269       break;
4270   }
4271   if (y < (ssize_t) rows)
4272     {
4273       ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4274         cache_info->cache_filename);
4275       return(MagickFalse);
4276     }
4277   if ((cache_info->debug != MagickFalse) &&
4278       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4279     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4280       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4281       nexus_info->region.width,(double) nexus_info->region.height,(double)
4282       nexus_info->region.x,(double) nexus_info->region.y);
4283   return(MagickTrue);
4284 }
4285 \f
4286 /*
4287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4288 %                                                                             %
4289 %                                                                             %
4290 %                                                                             %
4291 +   R e a d P i x e l C a c h e P i x e l s                                   %
4292 %                                                                             %
4293 %                                                                             %
4294 %                                                                             %
4295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4296 %
4297 %  ReadPixelCachePixels() reads pixels from the specified region of the pixel
4298 %  cache.
4299 %
4300 %  The format of the ReadPixelCachePixels() method is:
4301 %
4302 %      MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4303 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4304 %
4305 %  A description of each parameter follows:
4306 %
4307 %    o cache_info: the pixel cache.
4308 %
4309 %    o nexus_info: the cache nexus to read the pixels.
4310 %
4311 %    o exception: return any errors or warnings in this structure.
4312 %
4313 */
4314 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4315   NexusInfo *nexus_info,ExceptionInfo *exception)
4316 {
4317   MagickOffsetType
4318     count,
4319     offset;
4320
4321   MagickSizeType
4322     extent,
4323     length;
4324
4325   register Quantum
4326     *restrict q;
4327
4328   register ssize_t
4329     y;
4330
4331   size_t
4332     rows;
4333
4334   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4335     return(MagickTrue);
4336   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4337     nexus_info->region.x;
4338   length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
4339     sizeof(Quantum);
4340   extent=length*nexus_info->region.height;
4341   rows=nexus_info->region.height;
4342   y=0;
4343   q=nexus_info->pixels;
4344   switch (cache_info->type)
4345   {
4346     case MemoryCache:
4347     case MapCache:
4348     {
4349       register Quantum
4350         *restrict p;
4351
4352       /*
4353         Read pixels from memory.
4354       */
4355       if ((cache_info->columns == nexus_info->region.width) &&
4356           (extent == (MagickSizeType) ((size_t) extent)))
4357         {
4358           length=extent;
4359           rows=1UL;
4360         }
4361       p=cache_info->pixels+offset*cache_info->number_channels;
4362       for (y=0; y < (ssize_t) rows; y++)
4363       {
4364         (void) memcpy(q,p,(size_t) length);
4365         p+=cache_info->number_channels*cache_info->columns;
4366         q+=cache_info->number_channels*nexus_info->region.width;
4367       }
4368       break;
4369     }
4370     case DiskCache:
4371     {
4372       /*
4373         Read pixels from disk.
4374       */
4375       LockSemaphoreInfo(cache_info->file_semaphore);
4376       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4377         {
4378           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4379             cache_info->cache_filename);
4380           UnlockSemaphoreInfo(cache_info->file_semaphore);
4381           return(MagickFalse);
4382         }
4383       if ((cache_info->columns == nexus_info->region.width) &&
4384           (extent <= MagickMaxBufferExtent))
4385         {
4386           length=extent;
4387           rows=1UL;
4388         }
4389       for (y=0; y < (ssize_t) rows; y++)
4390       {
4391         count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4392           cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4393         if (count != (MagickOffsetType) length)
4394           break;
4395         offset+=cache_info->columns;
4396         q+=cache_info->number_channels*nexus_info->region.width;
4397       }
4398       if (IsFileDescriptorLimitExceeded() != MagickFalse)
4399         (void) ClosePixelCacheOnDisk(cache_info);
4400       UnlockSemaphoreInfo(cache_info->file_semaphore);
4401       break;
4402     }
4403     case DistributedCache:
4404     {
4405       RectangleInfo
4406         region;
4407
4408       /*
4409         Read pixels from distributed cache.
4410       */
4411       LockSemaphoreInfo(cache_info->file_semaphore);
4412       region=nexus_info->region;
4413       if ((cache_info->columns != nexus_info->region.width) ||
4414           (extent > MagickMaxBufferExtent))
4415         region.height=1UL;
4416       else
4417         {
4418           length=extent;
4419           rows=1UL;
4420         }
4421       for (y=0; y < (ssize_t) rows; y++)
4422       {
4423         count=ReadDistributePixelCachePixels(cache_info->server_info,&region,
4424           length,(unsigned char *) q);
4425         if (count != (MagickOffsetType) length)
4426           break;
4427         q+=cache_info->number_channels*nexus_info->region.width;
4428         region.y++;
4429       }
4430       UnlockSemaphoreInfo(cache_info->file_semaphore);
4431       break;
4432     }
4433     default:
4434       break;
4435   }
4436   if (y < (ssize_t) rows)
4437     {
4438       ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4439         cache_info->cache_filename);
4440       return(MagickFalse);
4441     }
4442   if ((cache_info->debug != MagickFalse) &&
4443       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4444     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4445       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4446       nexus_info->region.width,(double) nexus_info->region.height,(double)
4447       nexus_info->region.x,(double) nexus_info->region.y);
4448   return(MagickTrue);
4449 }
4450 \f
4451 /*
4452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4453 %                                                                             %
4454 %                                                                             %
4455 %                                                                             %
4456 +   R e f e r e n c e P i x e l C a c h e                                     %
4457 %                                                                             %
4458 %                                                                             %
4459 %                                                                             %
4460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4461 %
4462 %  ReferencePixelCache() increments the reference count associated with the
4463 %  pixel cache returning a pointer to the cache.
4464 %
4465 %  The format of the ReferencePixelCache method is:
4466 %
4467 %      Cache ReferencePixelCache(Cache cache_info)
4468 %
4469 %  A description of each parameter follows:
4470 %
4471 %    o cache_info: the pixel cache.
4472 %
4473 */
4474 MagickPrivate Cache ReferencePixelCache(Cache cache)
4475 {
4476   CacheInfo
4477     *cache_info;
4478
4479   assert(cache != (Cache *) NULL);
4480   cache_info=(CacheInfo *) cache;
4481   assert(cache_info->signature == MagickSignature);
4482   LockSemaphoreInfo(cache_info->semaphore);
4483   cache_info->reference_count++;
4484   UnlockSemaphoreInfo(cache_info->semaphore);
4485   return(cache_info);
4486 }
4487 \f
4488 /*
4489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4490 %                                                                             %
4491 %                                                                             %
4492 %                                                                             %
4493 +   S e t P i x e l C a c h e M e t h o d s                                   %
4494 %                                                                             %
4495 %                                                                             %
4496 %                                                                             %
4497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4498 %
4499 %  SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4500 %
4501 %  The format of the SetPixelCacheMethods() method is:
4502 %
4503 %      SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4504 %
4505 %  A description of each parameter follows:
4506 %
4507 %    o cache: the pixel cache.
4508 %
4509 %    o cache_methods: Specifies a pointer to a CacheMethods structure.
4510 %
4511 */
4512 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4513 {
4514   CacheInfo
4515     *cache_info;
4516
4517   GetOneAuthenticPixelFromHandler
4518     get_one_authentic_pixel_from_handler;
4519
4520   GetOneVirtualPixelFromHandler
4521     get_one_virtual_pixel_from_handler;
4522
4523   /*
4524     Set cache pixel methods.
4525   */
4526   assert(cache != (Cache) NULL);
4527   assert(cache_methods != (CacheMethods *) NULL);
4528   cache_info=(CacheInfo *) cache;
4529   assert(cache_info->signature == MagickSignature);
4530   if (cache_info->debug != MagickFalse)
4531     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4532       cache_info->filename);
4533   if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4534     cache_info->methods.get_virtual_pixel_handler=
4535       cache_methods->get_virtual_pixel_handler;
4536   if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4537     cache_info->methods.destroy_pixel_handler=
4538       cache_methods->destroy_pixel_handler;
4539   if (cache_methods->get_virtual_metacontent_from_handler !=
4540       (GetVirtualMetacontentFromHandler) NULL)
4541     cache_info->methods.get_virtual_metacontent_from_handler=
4542       cache_methods->get_virtual_metacontent_from_handler;
4543   if (cache_methods->get_authentic_pixels_handler !=
4544       (GetAuthenticPixelsHandler) NULL)
4545     cache_info->methods.get_authentic_pixels_handler=
4546       cache_methods->get_authentic_pixels_handler;
4547   if (cache_methods->queue_authentic_pixels_handler !=
4548       (QueueAuthenticPixelsHandler) NULL)
4549     cache_info->methods.queue_authentic_pixels_handler=
4550       cache_methods->queue_authentic_pixels_handler;
4551   if (cache_methods->sync_authentic_pixels_handler !=
4552       (SyncAuthenticPixelsHandler) NULL)
4553     cache_info->methods.sync_authentic_pixels_handler=
4554       cache_methods->sync_authentic_pixels_handler;
4555   if (cache_methods->get_authentic_pixels_from_handler !=
4556       (GetAuthenticPixelsFromHandler) NULL)
4557     cache_info->methods.get_authentic_pixels_from_handler=
4558       cache_methods->get_authentic_pixels_from_handler;
4559   if (cache_methods->get_authentic_metacontent_from_handler !=
4560       (GetAuthenticMetacontentFromHandler) NULL)
4561     cache_info->methods.get_authentic_metacontent_from_handler=
4562       cache_methods->get_authentic_metacontent_from_handler;
4563   get_one_virtual_pixel_from_handler=
4564     cache_info->methods.get_one_virtual_pixel_from_handler;
4565   if (get_one_virtual_pixel_from_handler !=
4566       (GetOneVirtualPixelFromHandler) NULL)
4567     cache_info->methods.get_one_virtual_pixel_from_handler=
4568       cache_methods->get_one_virtual_pixel_from_handler;
4569   get_one_authentic_pixel_from_handler=
4570     cache_methods->get_one_authentic_pixel_from_handler;
4571   if (get_one_authentic_pixel_from_handler !=
4572       (GetOneAuthenticPixelFromHandler) NULL)
4573     cache_info->methods.get_one_authentic_pixel_from_handler=
4574       cache_methods->get_one_authentic_pixel_from_handler;
4575 }
4576 \f
4577 /*
4578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4579 %                                                                             %
4580 %                                                                             %
4581 %                                                                             %
4582 +   S e t P i x e l C a c h e N e x u s P i x e l s                           %
4583 %                                                                             %
4584 %                                                                             %
4585 %                                                                             %
4586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4587 %
4588 %  SetPixelCacheNexusPixels() defines the region of the cache for the
4589 %  specified cache nexus.
4590 %
4591 %  The format of the SetPixelCacheNexusPixels() method is:
4592 %
4593 %      Quantum SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4594 %        const MapMode mode,const RectangleInfo *region,NexusInfo *nexus_info,
4595 %        ExceptionInfo *exception)
4596 %
4597 %  A description of each parameter follows:
4598 %
4599 %    o cache_info: the pixel cache.
4600 %
4601 %    o mode: ReadMode, WriteMode, or IOMode.
4602 %
4603 %    o region: A pointer to the RectangleInfo structure that defines the
4604 %      region of this particular cache nexus.
4605 %
4606 %    o nexus_info: the cache nexus to set.
4607 %
4608 %    o exception: return any errors or warnings in this structure.
4609 %
4610 */
4611
4612 static inline MagickBooleanType AcquireCacheNexusPixels(
4613   const CacheInfo *restrict cache_info,NexusInfo *nexus_info,
4614   ExceptionInfo *exception)
4615 {
4616   if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4617     return(MagickFalse);
4618   nexus_info->mapped=MagickFalse;
4619   nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
4620     (size_t) nexus_info->length));
4621   if (nexus_info->cache == (Quantum *) NULL)
4622     {
4623       nexus_info->mapped=MagickTrue;
4624       nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4625         nexus_info->length);
4626     }
4627   if (nexus_info->cache == (Quantum *) NULL)
4628     {
4629       (void) ThrowMagickException(exception,GetMagickModule(),
4630         ResourceLimitError,"MemoryAllocationFailed","`%s'",
4631         cache_info->filename);
4632       return(MagickFalse);
4633     }
4634   return(MagickTrue);
4635 }
4636
4637 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
4638   const MapMode mode)
4639 {
4640   if (mode == ReadMode)
4641     {
4642       MagickCachePrefetch((unsigned char *) nexus_info->pixels,0,1);
4643       return;
4644     }
4645   MagickCachePrefetch((unsigned char *) nexus_info->pixels,1,1);
4646 }
4647
4648 static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4649   const MapMode mode,const RectangleInfo *region,NexusInfo *nexus_info,
4650   ExceptionInfo *exception)
4651 {
4652   MagickBooleanType
4653     status;
4654
4655   MagickSizeType
4656     length,
4657     number_pixels;
4658
4659   assert(cache_info != (const CacheInfo *) NULL);
4660   assert(cache_info->signature == MagickSignature);
4661   if (cache_info->type == UndefinedCache)
4662     return((Quantum *) NULL);
4663   nexus_info->region=(*region);
4664   if ((cache_info->type == MemoryCache) || (cache_info->type == MapCache))
4665     {
4666       ssize_t
4667         x,
4668         y;
4669
4670       x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
4671       y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
4672       if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
4673            (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
4674           ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
4675            ((nexus_info->region.width == cache_info->columns) ||
4676             ((nexus_info->region.width % cache_info->columns) == 0)))))
4677         {
4678           MagickOffsetType
4679             offset;
4680
4681           /*
4682             Pixels are accessed directly from memory.
4683           */
4684           offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4685             nexus_info->region.x;
4686           nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
4687             offset;
4688           nexus_info->metacontent=(void *) NULL;
4689           if (cache_info->metacontent_extent != 0)
4690             nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
4691               offset*cache_info->metacontent_extent;
4692           PrefetchPixelCacheNexusPixels(nexus_info,mode);
4693           return(nexus_info->pixels);
4694         }
4695     }
4696   /*
4697     Pixels are stored in a cache region until they are synced to the cache.
4698   */
4699   number_pixels=(MagickSizeType) nexus_info->region.width*
4700     nexus_info->region.height;
4701   length=number_pixels*cache_info->number_channels*sizeof(Quantum);
4702   if (cache_info->metacontent_extent != 0)
4703     length+=number_pixels*cache_info->metacontent_extent;
4704   if (nexus_info->cache == (Quantum *) NULL)
4705     {
4706       nexus_info->length=length;
4707       status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4708       if (status == MagickFalse)
4709         {
4710           nexus_info->length=0;
4711           return((Quantum *) NULL);
4712         }
4713     }
4714   else
4715     if (nexus_info->length != length)
4716       {
4717         RelinquishCacheNexusPixels(nexus_info);
4718         nexus_info->length=length;
4719         status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4720         if (status == MagickFalse)
4721           {
4722             nexus_info->length=0;
4723             return((Quantum *) NULL);
4724           }
4725       }
4726   nexus_info->pixels=nexus_info->cache;
4727   nexus_info->metacontent=(void *) NULL;
4728   if (cache_info->metacontent_extent != 0)
4729     nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
4730       cache_info->number_channels);
4731   PrefetchPixelCacheNexusPixels(nexus_info,mode);
4732   return(nexus_info->pixels);
4733 }
4734 \f
4735 /*
4736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4737 %                                                                             %
4738 %                                                                             %
4739 %                                                                             %
4740 %   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                       %
4741 %                                                                             %
4742 %                                                                             %
4743 %                                                                             %
4744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4745 %
4746 %  SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
4747 %  pixel cache and returns the previous setting.  A virtual pixel is any pixel
4748 %  access that is outside the boundaries of the image cache.
4749 %
4750 %  The format of the SetPixelCacheVirtualMethod() method is:
4751 %
4752 %      VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4753 %        const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4754 %
4755 %  A description of each parameter follows:
4756 %
4757 %    o image: the image.
4758 %
4759 %    o virtual_pixel_method: choose the type of virtual pixel.
4760 %
4761 %    o exception: return any errors or warnings in this structure.
4762 %
4763 */
4764
4765 static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
4766   ExceptionInfo *exception)
4767 {
4768   CacheInfo
4769     *cache_info;
4770
4771   CacheView
4772     *image_view;
4773
4774   MagickBooleanType
4775     status;
4776
4777   ssize_t
4778     y;
4779
4780   assert(image != (Image *) NULL);
4781   assert(image->signature == MagickSignature);
4782   if (image->debug != MagickFalse)
4783     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4784   assert(image->cache != (Cache) NULL);
4785   cache_info=(CacheInfo *) image->cache;
4786   assert(cache_info->signature == MagickSignature);
4787   image->alpha_trait=BlendPixelTrait;
4788   status=MagickTrue;
4789   image_view=AcquireVirtualCacheView(image,exception);  /* must be virtual */
4790 #if defined(MAGICKCORE_OPENMP_SUPPORT)
4791   #pragma omp parallel for schedule(static,4) shared(status) \
4792     magick_threads(image,image,1,1)
4793 #endif
4794   for (y=0; y < (ssize_t) image->rows; y++)
4795   {
4796     register Quantum
4797       *restrict q;
4798
4799     register ssize_t
4800       x;
4801
4802     if (status == MagickFalse)
4803       continue;
4804     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
4805     if (q == (Quantum *) NULL)
4806       {
4807         status=MagickFalse;
4808         continue;
4809       }
4810     for (x=0; x < (ssize_t) image->columns; x++)
4811     {
4812       SetPixelAlpha(image,alpha,q);
4813       q+=GetPixelChannels(image);
4814     }
4815     status=SyncCacheViewAuthenticPixels(image_view,exception);
4816   }
4817   image_view=DestroyCacheView(image_view);
4818   return(status);
4819 }
4820
4821 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4822   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4823 {
4824   CacheInfo
4825     *cache_info;
4826
4827   VirtualPixelMethod
4828     method;
4829
4830   assert(image != (Image *) NULL);
4831   assert(image->signature == MagickSignature);
4832   if (image->debug != MagickFalse)
4833     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4834   assert(image->cache != (Cache) NULL);
4835   cache_info=(CacheInfo *) image->cache;
4836   assert(cache_info->signature == MagickSignature);
4837   method=cache_info->virtual_pixel_method;
4838   cache_info->virtual_pixel_method=virtual_pixel_method;
4839   if ((image->columns != 0) && (image->rows != 0))
4840     switch (virtual_pixel_method)
4841     {
4842       case BackgroundVirtualPixelMethod:
4843       {
4844         if ((image->background_color.alpha_trait == BlendPixelTrait) &&
4845             (image->alpha_trait != BlendPixelTrait))
4846           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
4847         if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
4848             (IsGrayColorspace(image->colorspace) != MagickFalse))
4849           (void) TransformImageColorspace(image,RGBColorspace,exception);
4850         break;
4851       }
4852       case TransparentVirtualPixelMethod:
4853       {
4854         if (image->alpha_trait != BlendPixelTrait)
4855           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
4856         break;
4857       }
4858       default:
4859         break;
4860     }
4861   return(method);
4862 }
4863 \f
4864 /*
4865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4866 %                                                                             %
4867 %                                                                             %
4868 %                                                                             %
4869 +   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                   %
4870 %                                                                             %
4871 %                                                                             %
4872 %                                                                             %
4873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4874 %
4875 %  SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
4876 %  in-memory or disk cache.  The method returns MagickTrue if the pixel region
4877 %  is synced, otherwise MagickFalse.
4878 %
4879 %  The format of the SyncAuthenticPixelCacheNexus() method is:
4880 %
4881 %      MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
4882 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4883 %
4884 %  A description of each parameter follows:
4885 %
4886 %    o image: the image.
4887 %
4888 %    o nexus_info: the cache nexus to sync.
4889 %
4890 %    o exception: return any errors or warnings in this structure.
4891 %
4892 */
4893 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
4894   NexusInfo *nexus_info,ExceptionInfo *exception)
4895 {
4896   CacheInfo
4897     *cache_info;
4898
4899   MagickBooleanType
4900     status;
4901
4902   /*
4903     Transfer pixels to the cache.
4904   */
4905   assert(image != (Image *) NULL);
4906   assert(image->signature == MagickSignature);
4907   if (image->cache == (Cache) NULL)
4908     ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
4909   cache_info=(CacheInfo *) image->cache;
4910   assert(cache_info->signature == MagickSignature);
4911   if (cache_info->type == UndefinedCache)
4912     return(MagickFalse);
4913   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4914     return(MagickTrue);
4915   assert(cache_info->signature == MagickSignature);
4916   status=WritePixelCachePixels(cache_info,nexus_info,exception);
4917   if ((cache_info->metacontent_extent != 0) &&
4918       (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
4919     return(MagickFalse);
4920   return(status);
4921 }
4922 \f
4923 /*
4924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4925 %                                                                             %
4926 %                                                                             %
4927 %                                                                             %
4928 +   S y n c A u t h e n t i c P i x e l C a c h e                             %
4929 %                                                                             %
4930 %                                                                             %
4931 %                                                                             %
4932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4933 %
4934 %  SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
4935 %  or disk cache.  The method returns MagickTrue if the pixel region is synced,
4936 %  otherwise MagickFalse.
4937 %
4938 %  The format of the SyncAuthenticPixelsCache() method is:
4939 %
4940 %      MagickBooleanType SyncAuthenticPixelsCache(Image *image,
4941 %        ExceptionInfo *exception)
4942 %
4943 %  A description of each parameter follows:
4944 %
4945 %    o image: the image.
4946 %
4947 %    o exception: return any errors or warnings in this structure.
4948 %
4949 */
4950 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
4951   ExceptionInfo *exception)
4952 {
4953   CacheInfo
4954     *cache_info;
4955
4956   const int
4957     id = GetOpenMPThreadId();
4958
4959   MagickBooleanType
4960     status;
4961
4962   assert(image != (Image *) NULL);
4963   assert(image->signature == MagickSignature);
4964   assert(image->cache != (Cache) NULL);
4965   cache_info=(CacheInfo *) image->cache;
4966   assert(cache_info->signature == MagickSignature);
4967   assert(id < (int) cache_info->number_threads);
4968   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
4969     exception);
4970   return(status);
4971 }
4972 \f
4973 /*
4974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4975 %                                                                             %
4976 %                                                                             %
4977 %                                                                             %
4978 %   S y n c A u t h e n t i c P i x e l s                                     %
4979 %                                                                             %
4980 %                                                                             %
4981 %                                                                             %
4982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4983 %
4984 %  SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
4985 %  The method returns MagickTrue if the pixel region is flushed, otherwise
4986 %  MagickFalse.
4987 %
4988 %  The format of the SyncAuthenticPixels() method is:
4989 %
4990 %      MagickBooleanType SyncAuthenticPixels(Image *image,
4991 %        ExceptionInfo *exception)
4992 %
4993 %  A description of each parameter follows:
4994 %
4995 %    o image: the image.
4996 %
4997 %    o exception: return any errors or warnings in this structure.
4998 %
4999 */
5000 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5001   ExceptionInfo *exception)
5002 {
5003   CacheInfo
5004     *cache_info;
5005
5006   const int
5007     id = GetOpenMPThreadId();
5008
5009   MagickBooleanType
5010     status;
5011
5012   assert(image != (Image *) NULL);
5013   assert(image->signature == MagickSignature);
5014   assert(image->cache != (Cache) NULL);
5015   cache_info=(CacheInfo *) image->cache;
5016   assert(cache_info->signature == MagickSignature);
5017   if (cache_info->methods.sync_authentic_pixels_handler !=
5018        (SyncAuthenticPixelsHandler) NULL)
5019     {
5020       status=cache_info->methods.sync_authentic_pixels_handler(image,
5021         exception);
5022       return(status);
5023     }
5024   assert(id < (int) cache_info->number_threads);
5025   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5026     exception);
5027   return(status);
5028 }
5029 \f
5030 /*
5031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5032 %                                                                             %
5033 %                                                                             %
5034 %                                                                             %
5035 +   S y n c I m a g e P i x e l C a c h e                                     %
5036 %                                                                             %
5037 %                                                                             %
5038 %                                                                             %
5039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5040 %
5041 %  SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5042 %  The method returns MagickTrue if the pixel region is flushed, otherwise
5043 %  MagickFalse.
5044 %
5045 %  The format of the SyncImagePixelCache() method is:
5046 %
5047 %      MagickBooleanType SyncImagePixelCache(Image *image,
5048 %        ExceptionInfo *exception)
5049 %
5050 %  A description of each parameter follows:
5051 %
5052 %    o image: the image.
5053 %
5054 %    o exception: return any errors or warnings in this structure.
5055 %
5056 */
5057 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5058   ExceptionInfo *exception)
5059 {
5060   CacheInfo
5061     *cache_info;
5062
5063   assert(image != (Image *) NULL);
5064   assert(exception != (ExceptionInfo *) NULL);
5065   cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5066   return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5067 }
5068 \f
5069 /*
5070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5071 %                                                                             %
5072 %                                                                             %
5073 %                                                                             %
5074 +   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                       %
5075 %                                                                             %
5076 %                                                                             %
5077 %                                                                             %
5078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5079 %
5080 %  WritePixelCacheMetacontent() writes the meta-content to the specified region
5081 %  of the pixel cache.
5082 %
5083 %  The format of the WritePixelCacheMetacontent() method is:
5084 %
5085 %      MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5086 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5087 %
5088 %  A description of each parameter follows:
5089 %
5090 %    o cache_info: the pixel cache.
5091 %
5092 %    o nexus_info: the cache nexus to write the meta-content.
5093 %
5094 %    o exception: return any errors or warnings in this structure.
5095 %
5096 */
5097 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5098   NexusInfo *nexus_info,ExceptionInfo *exception)
5099 {
5100   MagickOffsetType
5101     count,
5102     offset;
5103
5104   MagickSizeType
5105     extent,
5106     length;
5107
5108   register const unsigned char
5109     *restrict p;
5110
5111   register ssize_t
5112     y;
5113
5114   size_t
5115     rows;
5116
5117   if (cache_info->metacontent_extent == 0)
5118     return(MagickFalse);
5119   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5120     return(MagickTrue);
5121   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5122     nexus_info->region.x;
5123   length=(MagickSizeType) nexus_info->region.width*
5124     cache_info->metacontent_extent;
5125   extent=(MagickSizeType) length*nexus_info->region.height;
5126   rows=nexus_info->region.height;
5127   y=0;
5128   p=(unsigned char *) nexus_info->metacontent;
5129   switch (cache_info->type)
5130   {
5131     case MemoryCache:
5132     case MapCache:
5133     {
5134       register unsigned char
5135         *restrict q;
5136
5137       /*
5138         Write associated pixels to memory.
5139       */
5140       if ((cache_info->columns == nexus_info->region.width) &&
5141           (extent == (MagickSizeType) ((size_t) extent)))
5142         {
5143           length=extent;
5144           rows=1UL;
5145         }
5146       q=(unsigned char *) cache_info->metacontent+offset*
5147         cache_info->metacontent_extent;
5148       for (y=0; y < (ssize_t) rows; y++)
5149       {
5150         (void) memcpy(q,p,(size_t) length);
5151         p+=nexus_info->region.width*cache_info->metacontent_extent;
5152         q+=cache_info->columns*cache_info->metacontent_extent;
5153       }
5154       break;
5155     }
5156     case DiskCache:
5157     {
5158       /*
5159         Write associated pixels to disk.
5160       */
5161       LockSemaphoreInfo(cache_info->file_semaphore);
5162       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5163         {
5164           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5165             cache_info->cache_filename);
5166           UnlockSemaphoreInfo(cache_info->file_semaphore);
5167           return(MagickFalse);
5168         }
5169       if ((cache_info->columns == nexus_info->region.width) &&
5170           (extent <= MagickMaxBufferExtent))
5171         {
5172           length=extent;
5173           rows=1UL;
5174         }
5175       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5176       for (y=0; y < (ssize_t) rows; y++)
5177       {
5178         count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5179           cache_info->number_channels*sizeof(Quantum)+offset*
5180           cache_info->metacontent_extent,length,(const unsigned char *) p);
5181         if (count != (MagickOffsetType) length)
5182           break;
5183         p+=cache_info->metacontent_extent*nexus_info->region.width;
5184         offset+=cache_info->columns;
5185       }
5186       if (IsFileDescriptorLimitExceeded() != MagickFalse)
5187         (void) ClosePixelCacheOnDisk(cache_info);
5188       UnlockSemaphoreInfo(cache_info->file_semaphore);
5189       break;
5190     }
5191     case DistributedCache:
5192     {
5193       RectangleInfo
5194         region;
5195
5196       /*
5197         Write metacontent to distributed cache.
5198       */
5199       LockSemaphoreInfo(cache_info->file_semaphore);
5200       region=nexus_info->region;
5201       if ((cache_info->columns != nexus_info->region.width) ||
5202           (extent > MagickMaxBufferExtent))
5203         region.height=1UL;
5204       else
5205         {
5206           length=extent;
5207           rows=1UL;
5208         }
5209       for (y=0; y < (ssize_t) rows; y++)
5210       {
5211         count=WriteDistributePixelCacheMetacontent(cache_info->server_info,
5212           &region,length,(const unsigned char *) p);
5213         if (count != (MagickOffsetType) length)
5214           break;
5215         p+=cache_info->metacontent_extent*nexus_info->region.width;
5216         region.y++;
5217       }
5218       UnlockSemaphoreInfo(cache_info->file_semaphore);
5219       break;
5220     }
5221     default:
5222       break;
5223   }
5224   if (y < (ssize_t) rows)
5225     {
5226       ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5227         cache_info->cache_filename);
5228       return(MagickFalse);
5229     }
5230   if ((cache_info->debug != MagickFalse) &&
5231       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5232     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5233       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5234       nexus_info->region.width,(double) nexus_info->region.height,(double)
5235       nexus_info->region.x,(double) nexus_info->region.y);
5236   return(MagickTrue);
5237 }
5238 \f
5239 /*
5240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5241 %                                                                             %
5242 %                                                                             %
5243 %                                                                             %
5244 +   W r i t e C a c h e P i x e l s                                           %
5245 %                                                                             %
5246 %                                                                             %
5247 %                                                                             %
5248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5249 %
5250 %  WritePixelCachePixels() writes image pixels to the specified region of the
5251 %  pixel cache.
5252 %
5253 %  The format of the WritePixelCachePixels() method is:
5254 %
5255 %      MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5256 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5257 %
5258 %  A description of each parameter follows:
5259 %
5260 %    o cache_info: the pixel cache.
5261 %
5262 %    o nexus_info: the cache nexus to write the pixels.
5263 %
5264 %    o exception: return any errors or warnings in this structure.
5265 %
5266 */
5267 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5268   NexusInfo *nexus_info,ExceptionInfo *exception)
5269 {
5270   MagickOffsetType
5271     count,
5272     offset;
5273
5274   MagickSizeType
5275     extent,
5276     length;
5277
5278   register const Quantum
5279     *restrict p;
5280
5281   register ssize_t
5282     y;
5283
5284   size_t
5285     rows;
5286
5287   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5288     return(MagickTrue);
5289   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5290     nexus_info->region.x;
5291   length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5292     sizeof(Quantum);
5293   extent=length*nexus_info->region.height;
5294   rows=nexus_info->region.height;
5295   y=0;
5296   p=nexus_info->pixels;
5297   switch (cache_info->type)
5298   {
5299     case MemoryCache:
5300     case MapCache:
5301     {
5302       register Quantum
5303         *restrict q;
5304
5305       /*
5306         Write pixels to memory.
5307       */
5308       if ((cache_info->columns == nexus_info->region.width) &&
5309           (extent == (MagickSizeType) ((size_t) extent)))
5310         {
5311           length=extent;
5312           rows=1UL;
5313         }
5314       q=cache_info->pixels+offset*cache_info->number_channels;
5315       for (y=0; y < (ssize_t) rows; y++)
5316       {
5317         (void) memcpy(q,p,(size_t) length);
5318         p+=cache_info->number_channels*nexus_info->region.width;
5319         q+=cache_info->columns*cache_info->number_channels;
5320       }
5321       break;
5322     }
5323     case DiskCache:
5324     {
5325       /*
5326         Write pixels to disk.
5327       */
5328       LockSemaphoreInfo(cache_info->file_semaphore);
5329       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5330         {
5331           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5332             cache_info->cache_filename);
5333           UnlockSemaphoreInfo(cache_info->file_semaphore);
5334           return(MagickFalse);
5335         }
5336       if ((cache_info->columns == nexus_info->region.width) &&
5337           (extent <= MagickMaxBufferExtent))
5338         {
5339           length=extent;
5340           rows=1UL;
5341         }
5342       for (y=0; y < (ssize_t) rows; y++)
5343       {
5344         count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5345           cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5346           p);
5347         if (count != (MagickOffsetType) length)
5348           break;
5349         p+=cache_info->number_channels*nexus_info->region.width;
5350         offset+=cache_info->columns;
5351       }
5352       if (IsFileDescriptorLimitExceeded() != MagickFalse)
5353         (void) ClosePixelCacheOnDisk(cache_info);
5354       UnlockSemaphoreInfo(cache_info->file_semaphore);
5355       break;
5356     }
5357     case DistributedCache:
5358     {
5359       RectangleInfo
5360         region;
5361
5362       /*
5363         Write pixels to distributed cache.
5364       */
5365       LockSemaphoreInfo(cache_info->file_semaphore);
5366       region=nexus_info->region;
5367       if ((cache_info->columns != nexus_info->region.width) ||
5368           (extent > MagickMaxBufferExtent))
5369         region.height=1UL;
5370       else
5371         {
5372           length=extent;
5373           rows=1UL;
5374         }
5375       for (y=0; y < (ssize_t) rows; y++)
5376       {
5377         count=WriteDistributePixelCachePixels(cache_info->server_info,&region,
5378           length,(const unsigned char *) p);
5379         if (count != (MagickOffsetType) length)
5380           break;
5381         p+=cache_info->number_channels*nexus_info->region.width;
5382         region.y++;
5383       }
5384       UnlockSemaphoreInfo(cache_info->file_semaphore);
5385       break;
5386     }
5387     default:
5388       break;
5389   }
5390   if (y < (ssize_t) rows)
5391     {
5392       ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5393         cache_info->cache_filename);
5394       return(MagickFalse);
5395     }
5396   if ((cache_info->debug != MagickFalse) &&
5397       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5398     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5399       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5400       nexus_info->region.width,(double) nexus_info->region.height,(double)
5401       nexus_info->region.x,(double) nexus_info->region.y);
5402   return(MagickTrue);
5403 }