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