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