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