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