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