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