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