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