]> 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->type=DistributedCache;
3866               cache_info->server_info=server_info;
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) &&
4081       ((cache_info->type == DiskCache) || (cache_info->type == MapCache)) &&
4082       (cache_info->reference_count == 1))
4083     {
4084       LockSemaphoreInfo(cache_info->semaphore);
4085       if ((cache_info->mode != ReadMode) &&
4086           ((cache_info->type == DiskCache) || (cache_info->type == MapCache)) &&
4087           (cache_info->reference_count == 1))
4088         {
4089           int
4090             status;
4091
4092           /*
4093             Usurp existing persistent pixel cache.
4094           */
4095           status=rename_utf8(cache_info->cache_filename,filename);
4096           if (status == 0)
4097             {
4098               (void) CopyMagickString(cache_info->cache_filename,filename,
4099                 MaxTextExtent);
4100               *offset+=cache_info->length+page_size-(cache_info->length %
4101                 page_size);
4102               UnlockSemaphoreInfo(cache_info->semaphore);
4103               cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4104               if (image->debug != MagickFalse)
4105                 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4106                   "Usurp resident persistent cache");
4107               return(MagickTrue);
4108             }
4109         }
4110       UnlockSemaphoreInfo(cache_info->semaphore);
4111     }
4112   /*
4113     Clone persistent pixel cache.
4114   */
4115   clone_image=(*image);
4116   clone_info=(CacheInfo *) clone_image.cache;
4117   image->cache=ClonePixelCache(cache_info);
4118   cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4119   (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4120   cache_info->type=DiskCache;
4121   cache_info->offset=(*offset);
4122   cache_info=(CacheInfo *) image->cache;
4123   status=OpenPixelCache(image,IOMode,exception);
4124   if (status != MagickFalse)
4125     status=ClonePixelCachePixels(cache_info,clone_info,exception);
4126   *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4127   clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4128   return(status);
4129 }
4130 \f
4131 /*
4132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4133 %                                                                             %
4134 %                                                                             %
4135 %                                                                             %
4136 +   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                 %
4137 %                                                                             %
4138 %                                                                             %
4139 %                                                                             %
4140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4141 %
4142 %  QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
4143 %  defined by the region rectangle and returns a pointer to the region.  This
4144 %  region is subsequently transferred from the pixel cache with
4145 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
4146 %  pixels are transferred, otherwise a NULL is returned.
4147 %
4148 %  The format of the QueueAuthenticPixelCacheNexus() method is:
4149 %
4150 %      Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
4151 %        const ssize_t y,const size_t columns,const size_t rows,
4152 %        const MagickBooleanType clone,NexusInfo *nexus_info,
4153 %        ExceptionInfo *exception)
4154 %
4155 %  A description of each parameter follows:
4156 %
4157 %    o image: the image.
4158 %
4159 %    o x,y,columns,rows:  These values define the perimeter of a region of
4160 %      pixels.
4161 %
4162 %    o nexus_info: the cache nexus to set.
4163 %
4164 %    o clone: clone the pixel cache.
4165 %
4166 %    o exception: return any errors or warnings in this structure.
4167 %
4168 */
4169 MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4170   const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
4171   const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4172 {
4173   CacheInfo
4174     *cache_info;
4175
4176   MagickOffsetType
4177     offset;
4178
4179   MagickSizeType
4180     number_pixels;
4181
4182   RectangleInfo
4183     region;
4184
4185   /*
4186     Validate pixel cache geometry.
4187   */
4188   assert(image != (const Image *) NULL);
4189   assert(image->signature == MagickSignature);
4190   assert(image->cache != (Cache) NULL);
4191   cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4192   if (cache_info == (Cache) NULL)
4193     return((Quantum *) NULL);
4194   assert(cache_info->signature == MagickSignature);
4195   if ((cache_info->columns == 0) && (cache_info->rows == 0))
4196     {
4197       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4198         "NoPixelsDefinedInCache","`%s'",image->filename);
4199       return((Quantum *) NULL);
4200     }
4201   if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4202       (y >= (ssize_t) cache_info->rows))
4203     {
4204       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4205         "PixelsAreNotAuthentic","`%s'",image->filename);
4206       return((Quantum *) NULL);
4207     }
4208   offset=(MagickOffsetType) y*cache_info->columns+x;
4209   if (offset < 0)
4210     return((Quantum *) NULL);
4211   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4212   offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4213   if ((MagickSizeType) offset >= number_pixels)
4214     return((Quantum *) NULL);
4215   /*
4216     Return pixel cache.
4217   */
4218   region.x=x;
4219   region.y=y;
4220   region.width=columns;
4221   region.height=rows;
4222   return(SetPixelCacheNexusPixels(image,WriteMode,&region,nexus_info,exception));
4223 }
4224 \f
4225 /*
4226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4227 %                                                                             %
4228 %                                                                             %
4229 %                                                                             %
4230 +   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                         %
4231 %                                                                             %
4232 %                                                                             %
4233 %                                                                             %
4234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4235 %
4236 %  QueueAuthenticPixelsCache() allocates an region to store image pixels as
4237 %  defined by the region rectangle and returns a pointer to the region.  This
4238 %  region is subsequently transferred from the pixel cache with
4239 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
4240 %  pixels are transferred, otherwise a NULL is returned.
4241 %
4242 %  The format of the QueueAuthenticPixelsCache() method is:
4243 %
4244 %      Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4245 %        const ssize_t y,const size_t columns,const size_t rows,
4246 %        ExceptionInfo *exception)
4247 %
4248 %  A description of each parameter follows:
4249 %
4250 %    o image: the image.
4251 %
4252 %    o x,y,columns,rows:  These values define the perimeter of a region of
4253 %      pixels.
4254 %
4255 %    o exception: return any errors or warnings in this structure.
4256 %
4257 */
4258 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4259   const ssize_t y,const size_t columns,const size_t rows,
4260   ExceptionInfo *exception)
4261 {
4262   CacheInfo
4263     *cache_info;
4264
4265   const int
4266     id = GetOpenMPThreadId();
4267
4268   Quantum
4269     *q;
4270
4271   assert(image != (const Image *) NULL);
4272   assert(image->signature == MagickSignature);
4273   assert(image->cache != (Cache) NULL);
4274   cache_info=(CacheInfo *) image->cache;
4275   assert(cache_info->signature == MagickSignature);
4276   assert(id < (int) cache_info->number_threads);
4277   q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4278     cache_info->nexus_info[id],exception);
4279   return(q);
4280 }
4281 \f
4282 /*
4283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4284 %                                                                             %
4285 %                                                                             %
4286 %                                                                             %
4287 %   Q u e u e A u t h e n t i c P i x e l s                                   %
4288 %                                                                             %
4289 %                                                                             %
4290 %                                                                             %
4291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4292 %
4293 %  QueueAuthenticPixels() queues a mutable pixel region.  If the region is
4294 %  successfully initialized a pointer to a Quantum array representing the
4295 %  region is returned, otherwise NULL is returned.  The returned pointer may
4296 %  point to a temporary working buffer for the pixels or it may point to the
4297 %  final location of the pixels in memory.
4298 %
4299 %  Write-only access means that any existing pixel values corresponding to
4300 %  the region are ignored.  This is useful if the initial image is being
4301 %  created from scratch, or if the existing pixel values are to be
4302 %  completely replaced without need to refer to their pre-existing values.
4303 %  The application is free to read and write the pixel buffer returned by
4304 %  QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4305 %  initialize the pixel array values. Initializing pixel array values is the
4306 %  application's responsibility.
4307 %
4308 %  Performance is maximized if the selected region is part of one row, or
4309 %  one or more full rows, since then there is opportunity to access the
4310 %  pixels in-place (without a copy) if the image is in memory, or in a
4311 %  memory-mapped file. The returned pointer must *never* be deallocated
4312 %  by the user.
4313 %
4314 %  Pixels accessed via the returned pointer represent a simple array of type
4315 %  Quantum. If the image type is CMYK or the storage class is PseudoClass,
4316 %  call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4317 %  obtain the meta-content (of type void) corresponding to the region.
4318 %  Once the Quantum (and/or Quantum) array has been updated, the
4319 %  changes must be saved back to the underlying image using
4320 %  SyncAuthenticPixels() or they may be lost.
4321 %
4322 %  The format of the QueueAuthenticPixels() method is:
4323 %
4324 %      Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4325 %        const ssize_t y,const size_t columns,const size_t rows,
4326 %        ExceptionInfo *exception)
4327 %
4328 %  A description of each parameter follows:
4329 %
4330 %    o image: the image.
4331 %
4332 %    o x,y,columns,rows:  These values define the perimeter of a region of
4333 %      pixels.
4334 %
4335 %    o exception: return any errors or warnings in this structure.
4336 %
4337 */
4338 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4339   const ssize_t y,const size_t columns,const size_t rows,
4340   ExceptionInfo *exception)
4341 {
4342   CacheInfo
4343     *cache_info;
4344
4345   const int
4346     id = GetOpenMPThreadId();
4347
4348   Quantum
4349     *q;
4350
4351   assert(image != (Image *) NULL);
4352   assert(image->signature == MagickSignature);
4353   assert(image->cache != (Cache) NULL);
4354   cache_info=(CacheInfo *) image->cache;
4355   assert(cache_info->signature == MagickSignature);
4356   if (cache_info->methods.queue_authentic_pixels_handler !=
4357       (QueueAuthenticPixelsHandler) NULL)
4358     {
4359       q=cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4360         rows,exception);
4361       return(q);
4362     }
4363   assert(id < (int) cache_info->number_threads);
4364   q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4365     cache_info->nexus_info[id],exception);
4366   return(q);
4367 }
4368 \f
4369 /*
4370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4371 %                                                                             %
4372 %                                                                             %
4373 %                                                                             %
4374 +   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                         %
4375 %                                                                             %
4376 %                                                                             %
4377 %                                                                             %
4378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4379 %
4380 %  ReadPixelCacheMetacontent() reads metacontent from the specified region of
4381 %  the pixel cache.
4382 %
4383 %  The format of the ReadPixelCacheMetacontent() method is:
4384 %
4385 %      MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4386 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4387 %
4388 %  A description of each parameter follows:
4389 %
4390 %    o cache_info: the pixel cache.
4391 %
4392 %    o nexus_info: the cache nexus to read the metacontent.
4393 %
4394 %    o exception: return any errors or warnings in this structure.
4395 %
4396 */
4397 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4398   NexusInfo *nexus_info,ExceptionInfo *exception)
4399 {
4400   MagickOffsetType
4401     count,
4402     offset;
4403
4404   MagickSizeType
4405     extent,
4406     length;
4407
4408   RectangleInfo
4409     region;
4410
4411   register ssize_t
4412     y;
4413
4414   register unsigned char
4415     *restrict q;
4416
4417   if (cache_info->metacontent_extent == 0)
4418     return(MagickFalse);
4419   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4420     return(MagickTrue);
4421   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4422     nexus_info->region.x;
4423   length=(MagickSizeType) nexus_info->region.width*
4424     cache_info->metacontent_extent;
4425   extent=length*nexus_info->region.height;
4426   region=nexus_info->region;
4427   y=0;
4428   q=(unsigned char *) nexus_info->metacontent;
4429   switch (cache_info->type)
4430   {
4431     case MemoryCache:
4432     case MapCache:
4433     {
4434       register unsigned char
4435         *restrict p;
4436
4437       /*
4438         Read meta-content from memory.
4439       */
4440       if ((cache_info->columns == nexus_info->region.width) &&
4441           (extent == (MagickSizeType) ((size_t) extent)))
4442         {
4443           length=extent;
4444           region.height=1UL;
4445         }
4446       p=(unsigned char *) cache_info->metacontent+offset*
4447         cache_info->metacontent_extent;
4448       for (y=0; y < (ssize_t) region.height; y++)
4449       {
4450         (void) memcpy(q,p,(size_t) length);
4451         p+=cache_info->metacontent_extent*cache_info->columns;
4452         q+=cache_info->metacontent_extent*nexus_info->region.width;
4453       }
4454       break;
4455     }
4456     case DiskCache:
4457     {
4458       /*
4459         Read meta content from disk.
4460       */
4461       LockSemaphoreInfo(cache_info->file_semaphore);
4462       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4463         {
4464           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4465             cache_info->cache_filename);
4466           UnlockSemaphoreInfo(cache_info->file_semaphore);
4467           return(MagickFalse);
4468         }
4469       if ((cache_info->columns == nexus_info->region.width) &&
4470           (extent <= MagickMaxBufferExtent))
4471         {
4472           length=extent;
4473           region.height=1UL;
4474         }
4475       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4476       for (y=0; y < (ssize_t) region.height; y++)
4477       {
4478         count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4479           cache_info->number_channels*sizeof(Quantum)+offset*
4480           cache_info->metacontent_extent,length,(unsigned char *) q);
4481         if (count != (MagickOffsetType) length)
4482           break;
4483         offset+=cache_info->columns;
4484         q+=cache_info->metacontent_extent*nexus_info->region.width;
4485       }
4486       if (IsFileDescriptorLimitExceeded() != MagickFalse)
4487         (void) ClosePixelCacheOnDisk(cache_info);
4488       UnlockSemaphoreInfo(cache_info->file_semaphore);
4489       break;
4490     }
4491     case DistributedCache:
4492     {
4493       /*
4494         Read metacontent from distributed cache.
4495       */
4496       LockSemaphoreInfo(cache_info->file_semaphore);
4497       region.height=1UL;
4498       for (y=0; y < (ssize_t) region.height; y++)
4499       {
4500         count=ReadDistributePixelCachePixels(cache_info->server_info,&region,
4501           length,(unsigned char *) q);
4502         if (count != (MagickOffsetType) length)
4503           break;
4504         q+=cache_info->metacontent_extent*nexus_info->region.width;
4505         region.y++;
4506       }
4507       UnlockSemaphoreInfo(cache_info->file_semaphore);
4508       break;
4509     }
4510     default:
4511       break;
4512   }
4513   if (y < (ssize_t) region.height)
4514     {
4515       ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4516         cache_info->cache_filename);
4517       return(MagickFalse);
4518     }
4519   if ((cache_info->debug != MagickFalse) &&
4520       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4521     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4522       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4523       nexus_info->region.width,(double) nexus_info->region.height,(double)
4524       nexus_info->region.x,(double) nexus_info->region.y);
4525   return(MagickTrue);
4526 }
4527 \f
4528 /*
4529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4530 %                                                                             %
4531 %                                                                             %
4532 %                                                                             %
4533 +   R e a d P i x e l C a c h e P i x e l s                                   %
4534 %                                                                             %
4535 %                                                                             %
4536 %                                                                             %
4537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4538 %
4539 %  ReadPixelCachePixels() reads pixels from the specified region of the pixel
4540 %  cache.
4541 %
4542 %  The format of the ReadPixelCachePixels() method is:
4543 %
4544 %      MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4545 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4546 %
4547 %  A description of each parameter follows:
4548 %
4549 %    o cache_info: the pixel cache.
4550 %
4551 %    o nexus_info: the cache nexus to read the pixels.
4552 %
4553 %    o exception: return any errors or warnings in this structure.
4554 %
4555 */
4556 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4557   NexusInfo *nexus_info,ExceptionInfo *exception)
4558 {
4559   MagickOffsetType
4560     count,
4561     offset;
4562
4563   MagickSizeType
4564     extent,
4565     length;
4566
4567   RectangleInfo
4568     region;
4569
4570   register Quantum
4571     *restrict q;
4572
4573   register ssize_t
4574     y;
4575
4576   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4577     return(MagickTrue);
4578   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4579     nexus_info->region.x;
4580   length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
4581     sizeof(Quantum);
4582   extent=length*nexus_info->region.height;
4583   region=nexus_info->region;
4584   y=0;
4585   q=nexus_info->pixels;
4586   switch (cache_info->type)
4587   {
4588     case MemoryCache:
4589     case MapCache:
4590     {
4591       register Quantum
4592         *restrict p;
4593
4594       /*
4595         Read pixels from memory.
4596       */
4597       if ((cache_info->columns == nexus_info->region.width) &&
4598           (extent == (MagickSizeType) ((size_t) extent)))
4599         {
4600           length=extent;
4601           region.height=1UL;
4602         }
4603       p=cache_info->pixels+offset*cache_info->number_channels;
4604       for (y=0; y < (ssize_t) region.height; y++)
4605       {
4606         (void) memcpy(q,p,(size_t) length);
4607         p+=cache_info->number_channels*cache_info->columns;
4608         q+=cache_info->number_channels*nexus_info->region.width;
4609       }
4610       break;
4611     }
4612     case DiskCache:
4613     {
4614       /*
4615         Read pixels from disk.
4616       */
4617       LockSemaphoreInfo(cache_info->file_semaphore);
4618       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4619         {
4620           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4621             cache_info->cache_filename);
4622           UnlockSemaphoreInfo(cache_info->file_semaphore);
4623           return(MagickFalse);
4624         }
4625       if ((cache_info->columns == nexus_info->region.width) &&
4626           (extent <= MagickMaxBufferExtent))
4627         {
4628           length=extent;
4629           region.height=1UL;
4630         }
4631       for (y=0; y < (ssize_t) region.height; y++)
4632       {
4633         count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4634           cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4635         if (count != (MagickOffsetType) length)
4636           break;
4637         offset+=cache_info->columns;
4638         q+=cache_info->number_channels*nexus_info->region.width;
4639       }
4640       if (IsFileDescriptorLimitExceeded() != MagickFalse)
4641         (void) ClosePixelCacheOnDisk(cache_info);
4642       UnlockSemaphoreInfo(cache_info->file_semaphore);
4643       break;
4644     }
4645     case DistributedCache:
4646     {
4647       /*
4648         Read pixels from distributed cache.
4649       */
4650       LockSemaphoreInfo(cache_info->file_semaphore);
4651       region.height=1UL;
4652       for (y=0; y < (ssize_t) region.height; y++)
4653       {
4654         count=ReadDistributePixelCachePixels(cache_info->server_info,&region,
4655           length,(unsigned char *) q);
4656         if (count != (MagickOffsetType) length)
4657           break;
4658         q+=cache_info->number_channels*nexus_info->region.width;
4659         region.y++;
4660       }
4661       UnlockSemaphoreInfo(cache_info->file_semaphore);
4662       break;
4663     }
4664     default:
4665       break;
4666   }
4667   if (y < (ssize_t) region.height)
4668     {
4669       ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4670         cache_info->cache_filename);
4671       return(MagickFalse);
4672     }
4673   if ((cache_info->debug != MagickFalse) &&
4674       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4675     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4676       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4677       nexus_info->region.width,(double) nexus_info->region.height,(double)
4678       nexus_info->region.x,(double) nexus_info->region.y);
4679   return(MagickTrue);
4680 }
4681 \f
4682 /*
4683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4684 %                                                                             %
4685 %                                                                             %
4686 %                                                                             %
4687 +   R e f e r e n c e P i x e l C a c h e                                     %
4688 %                                                                             %
4689 %                                                                             %
4690 %                                                                             %
4691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4692 %
4693 %  ReferencePixelCache() increments the reference count associated with the
4694 %  pixel cache returning a pointer to the cache.
4695 %
4696 %  The format of the ReferencePixelCache method is:
4697 %
4698 %      Cache ReferencePixelCache(Cache cache_info)
4699 %
4700 %  A description of each parameter follows:
4701 %
4702 %    o cache_info: the pixel cache.
4703 %
4704 */
4705 MagickPrivate Cache ReferencePixelCache(Cache cache)
4706 {
4707   CacheInfo
4708     *cache_info;
4709
4710   assert(cache != (Cache *) NULL);
4711   cache_info=(CacheInfo *) cache;
4712   assert(cache_info->signature == MagickSignature);
4713   LockSemaphoreInfo(cache_info->semaphore);
4714   cache_info->reference_count++;
4715   UnlockSemaphoreInfo(cache_info->semaphore);
4716   return(cache_info);
4717 }
4718 \f
4719 /*
4720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4721 %                                                                             %
4722 %                                                                             %
4723 %                                                                             %
4724 +   S e t P i x e l C a c h e M e t h o d s                                   %
4725 %                                                                             %
4726 %                                                                             %
4727 %                                                                             %
4728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4729 %
4730 %  SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4731 %
4732 %  The format of the SetPixelCacheMethods() method is:
4733 %
4734 %      SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4735 %
4736 %  A description of each parameter follows:
4737 %
4738 %    o cache: the pixel cache.
4739 %
4740 %    o cache_methods: Specifies a pointer to a CacheMethods structure.
4741 %
4742 */
4743 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4744 {
4745   CacheInfo
4746     *cache_info;
4747
4748   GetOneAuthenticPixelFromHandler
4749     get_one_authentic_pixel_from_handler;
4750
4751   GetOneVirtualPixelFromHandler
4752     get_one_virtual_pixel_from_handler;
4753
4754   /*
4755     Set cache pixel methods.
4756   */
4757   assert(cache != (Cache) NULL);
4758   assert(cache_methods != (CacheMethods *) NULL);
4759   cache_info=(CacheInfo *) cache;
4760   assert(cache_info->signature == MagickSignature);
4761   if (cache_info->debug != MagickFalse)
4762     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4763       cache_info->filename);
4764   if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4765     cache_info->methods.get_virtual_pixel_handler=
4766       cache_methods->get_virtual_pixel_handler;
4767   if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4768     cache_info->methods.destroy_pixel_handler=
4769       cache_methods->destroy_pixel_handler;
4770   if (cache_methods->get_virtual_metacontent_from_handler !=
4771       (GetVirtualMetacontentFromHandler) NULL)
4772     cache_info->methods.get_virtual_metacontent_from_handler=
4773       cache_methods->get_virtual_metacontent_from_handler;
4774   if (cache_methods->get_authentic_pixels_handler !=
4775       (GetAuthenticPixelsHandler) NULL)
4776     cache_info->methods.get_authentic_pixels_handler=
4777       cache_methods->get_authentic_pixels_handler;
4778   if (cache_methods->queue_authentic_pixels_handler !=
4779       (QueueAuthenticPixelsHandler) NULL)
4780     cache_info->methods.queue_authentic_pixels_handler=
4781       cache_methods->queue_authentic_pixels_handler;
4782   if (cache_methods->sync_authentic_pixels_handler !=
4783       (SyncAuthenticPixelsHandler) NULL)
4784     cache_info->methods.sync_authentic_pixels_handler=
4785       cache_methods->sync_authentic_pixels_handler;
4786   if (cache_methods->get_authentic_pixels_from_handler !=
4787       (GetAuthenticPixelsFromHandler) NULL)
4788     cache_info->methods.get_authentic_pixels_from_handler=
4789       cache_methods->get_authentic_pixels_from_handler;
4790   if (cache_methods->get_authentic_metacontent_from_handler !=
4791       (GetAuthenticMetacontentFromHandler) NULL)
4792     cache_info->methods.get_authentic_metacontent_from_handler=
4793       cache_methods->get_authentic_metacontent_from_handler;
4794   get_one_virtual_pixel_from_handler=
4795     cache_info->methods.get_one_virtual_pixel_from_handler;
4796   if (get_one_virtual_pixel_from_handler !=
4797       (GetOneVirtualPixelFromHandler) NULL)
4798     cache_info->methods.get_one_virtual_pixel_from_handler=
4799       cache_methods->get_one_virtual_pixel_from_handler;
4800   get_one_authentic_pixel_from_handler=
4801     cache_methods->get_one_authentic_pixel_from_handler;
4802   if (get_one_authentic_pixel_from_handler !=
4803       (GetOneAuthenticPixelFromHandler) NULL)
4804     cache_info->methods.get_one_authentic_pixel_from_handler=
4805       cache_methods->get_one_authentic_pixel_from_handler;
4806 }
4807 \f
4808 /*
4809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4810 %                                                                             %
4811 %                                                                             %
4812 %                                                                             %
4813 +   S e t P i x e l C a c h e N e x u s P i x e l s                           %
4814 %                                                                             %
4815 %                                                                             %
4816 %                                                                             %
4817 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4818 %
4819 %  SetPixelCacheNexusPixels() defines the region of the cache for the
4820 %  specified cache nexus.
4821 %
4822 %  The format of the SetPixelCacheNexusPixels() method is:
4823 %
4824 %      Quantum SetPixelCacheNexusPixels(const Image *image,const MapMode mode,
4825 %        const RectangleInfo *region,NexusInfo *nexus_info,
4826 %        ExceptionInfo *exception)
4827 %
4828 %  A description of each parameter follows:
4829 %
4830 %    o image: the image.
4831 %
4832 %    o mode: ReadMode, WriteMode, or IOMode.
4833 %
4834 %    o region: A pointer to the RectangleInfo structure that defines the
4835 %      region of this particular cache nexus.
4836 %
4837 %    o nexus_info: the cache nexus to set.
4838 %
4839 %    o exception: return any errors or warnings in this structure.
4840 %
4841 */
4842
4843 static inline MagickBooleanType AcquireCacheNexusPixels(
4844   const CacheInfo *restrict cache_info,NexusInfo *nexus_info,
4845   ExceptionInfo *exception)
4846 {
4847   if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4848     return(MagickFalse);
4849   nexus_info->mapped=MagickFalse;
4850   nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
4851     (size_t) nexus_info->length));
4852   if (nexus_info->cache == (Quantum *) NULL)
4853     {
4854       nexus_info->mapped=MagickTrue;
4855       nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4856         nexus_info->length);
4857     }
4858   if (nexus_info->cache == (Quantum *) NULL)
4859     {
4860       (void) ThrowMagickException(exception,GetMagickModule(),
4861         ResourceLimitError,"MemoryAllocationFailed","`%s'",
4862         cache_info->filename);
4863       return(MagickFalse);
4864     }
4865   return(MagickTrue);
4866 }
4867
4868 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
4869   const MapMode mode)
4870 {
4871   if (mode == ReadMode)
4872     {
4873       MagickCachePrefetch((unsigned char *) nexus_info->pixels,0,1);
4874       return;
4875     }
4876   MagickCachePrefetch((unsigned char *) nexus_info->pixels,1,1);
4877 }
4878
4879 static Quantum *SetPixelCacheNexusPixels(const Image *image,const MapMode mode,
4880   const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
4881 {
4882   CacheInfo
4883     *cache_info;
4884
4885   MagickBooleanType
4886     status;
4887
4888   MagickSizeType
4889     length,
4890     number_pixels;
4891
4892   cache_info=(CacheInfo *) image->cache;
4893   assert(cache_info->signature == MagickSignature);
4894   if (cache_info->type == UndefinedCache)
4895     return((Quantum *) NULL);
4896   nexus_info->region=(*region);
4897   if ((cache_info->type == MemoryCache) || (cache_info->type == MapCache))
4898     {
4899       ssize_t
4900         x,
4901         y;
4902
4903       x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
4904       y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
4905       if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
4906            (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
4907           ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
4908            ((nexus_info->region.width == cache_info->columns) ||
4909             ((nexus_info->region.width % cache_info->columns) == 0)))))
4910         {
4911           MagickOffsetType
4912             offset;
4913
4914           /*
4915             Pixels are accessed directly from memory.
4916           */
4917           offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4918             nexus_info->region.x;
4919           nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
4920             offset;
4921           nexus_info->metacontent=(void *) NULL;
4922           if (cache_info->metacontent_extent != 0)
4923             nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
4924               offset*cache_info->metacontent_extent;
4925           PrefetchPixelCacheNexusPixels(nexus_info,mode);
4926           return(nexus_info->pixels);
4927         }
4928     }
4929   /*
4930     Pixels are stored in a cache region until they are synced to the cache.
4931   */
4932   number_pixels=(MagickSizeType) nexus_info->region.width*
4933     nexus_info->region.height;
4934   length=number_pixels*cache_info->number_channels*sizeof(Quantum);
4935   if (cache_info->metacontent_extent != 0)
4936     length+=number_pixels*cache_info->metacontent_extent;
4937   if (nexus_info->cache == (Quantum *) NULL)
4938     {
4939       nexus_info->length=length;
4940       status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4941       if (status == MagickFalse)
4942         {
4943           nexus_info->length=0;
4944           return((Quantum *) NULL);
4945         }
4946     }
4947   else
4948     if (nexus_info->length != length)
4949       {
4950         RelinquishCacheNexusPixels(nexus_info);
4951         nexus_info->length=length;
4952         status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4953         if (status == MagickFalse)
4954           {
4955             nexus_info->length=0;
4956             return((Quantum *) NULL);
4957           }
4958       }
4959   nexus_info->pixels=nexus_info->cache;
4960   nexus_info->metacontent=(void *) NULL;
4961   if (cache_info->metacontent_extent != 0)
4962     nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
4963       cache_info->number_channels);
4964   PrefetchPixelCacheNexusPixels(nexus_info,mode);
4965   return(nexus_info->pixels);
4966 }
4967 \f
4968 /*
4969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4970 %                                                                             %
4971 %                                                                             %
4972 %                                                                             %
4973 %   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                       %
4974 %                                                                             %
4975 %                                                                             %
4976 %                                                                             %
4977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4978 %
4979 %  SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
4980 %  pixel cache and returns the previous setting.  A virtual pixel is any pixel
4981 %  access that is outside the boundaries of the image cache.
4982 %
4983 %  The format of the SetPixelCacheVirtualMethod() method is:
4984 %
4985 %      VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4986 %        const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4987 %
4988 %  A description of each parameter follows:
4989 %
4990 %    o image: the image.
4991 %
4992 %    o virtual_pixel_method: choose the type of virtual pixel.
4993 %
4994 %    o exception: return any errors or warnings in this structure.
4995 %
4996 */
4997
4998 static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
4999   ExceptionInfo *exception)
5000 {
5001   CacheInfo
5002     *cache_info;
5003
5004   CacheView
5005     *image_view;
5006
5007   MagickBooleanType
5008     status;
5009
5010   ssize_t
5011     y;
5012
5013   assert(image != (Image *) NULL);
5014   assert(image->signature == MagickSignature);
5015   if (image->debug != MagickFalse)
5016     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5017   assert(image->cache != (Cache) NULL);
5018   cache_info=(CacheInfo *) image->cache;
5019   assert(cache_info->signature == MagickSignature);
5020   image->alpha_trait=BlendPixelTrait;
5021   status=MagickTrue;
5022   image_view=AcquireVirtualCacheView(image,exception);  /* must be virtual */
5023 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5024   #pragma omp parallel for schedule(static,4) shared(status) \
5025     magick_threads(image,image,1,1)
5026 #endif
5027   for (y=0; y < (ssize_t) image->rows; y++)
5028   {
5029     register Quantum
5030       *restrict q;
5031
5032     register ssize_t
5033       x;
5034
5035     if (status == MagickFalse)
5036       continue;
5037     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5038     if (q == (Quantum *) NULL)
5039       {
5040         status=MagickFalse;
5041         continue;
5042       }
5043     for (x=0; x < (ssize_t) image->columns; x++)
5044     {
5045       SetPixelAlpha(image,alpha,q);
5046       q+=GetPixelChannels(image);
5047     }
5048     status=SyncCacheViewAuthenticPixels(image_view,exception);
5049   }
5050   image_view=DestroyCacheView(image_view);
5051   return(status);
5052 }
5053
5054 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5055   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5056 {
5057   CacheInfo
5058     *cache_info;
5059
5060   VirtualPixelMethod
5061     method;
5062
5063   assert(image != (Image *) NULL);
5064   assert(image->signature == MagickSignature);
5065   if (image->debug != MagickFalse)
5066     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5067   assert(image->cache != (Cache) NULL);
5068   cache_info=(CacheInfo *) image->cache;
5069   assert(cache_info->signature == MagickSignature);
5070   method=cache_info->virtual_pixel_method;
5071   cache_info->virtual_pixel_method=virtual_pixel_method;
5072   if ((image->columns != 0) && (image->rows != 0))
5073     switch (virtual_pixel_method)
5074     {
5075       case BackgroundVirtualPixelMethod:
5076       {
5077         if ((image->background_color.alpha_trait == BlendPixelTrait) &&
5078             (image->alpha_trait != BlendPixelTrait))
5079           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5080         if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5081             (IsGrayColorspace(image->colorspace) != MagickFalse))
5082           (void) TransformImageColorspace(image,RGBColorspace,exception);
5083         break;
5084       }
5085       case TransparentVirtualPixelMethod:
5086       {
5087         if (image->alpha_trait != BlendPixelTrait)
5088           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5089         break;
5090       }
5091       default:
5092         break;
5093     }
5094   return(method);
5095 }
5096 \f
5097 /*
5098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5099 %                                                                             %
5100 %                                                                             %
5101 %                                                                             %
5102 +   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                   %
5103 %                                                                             %
5104 %                                                                             %
5105 %                                                                             %
5106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5107 %
5108 %  SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5109 %  in-memory or disk cache.  The method returns MagickTrue if the pixel region
5110 %  is synced, otherwise MagickFalse.
5111 %
5112 %  The format of the SyncAuthenticPixelCacheNexus() method is:
5113 %
5114 %      MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5115 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5116 %
5117 %  A description of each parameter follows:
5118 %
5119 %    o image: the image.
5120 %
5121 %    o nexus_info: the cache nexus to sync.
5122 %
5123 %    o exception: return any errors or warnings in this structure.
5124 %
5125 */
5126 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5127   NexusInfo *nexus_info,ExceptionInfo *exception)
5128 {
5129   CacheInfo
5130     *cache_info;
5131
5132   MagickBooleanType
5133     status;
5134
5135   /*
5136     Transfer pixels to the cache.
5137   */
5138   assert(image != (Image *) NULL);
5139   assert(image->signature == MagickSignature);
5140   if (image->cache == (Cache) NULL)
5141     ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5142   cache_info=(CacheInfo *) image->cache;
5143   assert(cache_info->signature == MagickSignature);
5144   if (cache_info->type == UndefinedCache)
5145     return(MagickFalse);
5146   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5147     return(MagickTrue);
5148   assert(cache_info->signature == MagickSignature);
5149   status=WritePixelCachePixels(cache_info,nexus_info,exception);
5150   if ((cache_info->metacontent_extent != 0) &&
5151       (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5152     return(MagickFalse);
5153   return(status);
5154 }
5155 \f
5156 /*
5157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5158 %                                                                             %
5159 %                                                                             %
5160 %                                                                             %
5161 +   S y n c A u t h e n t i c P i x e l C a c h e                             %
5162 %                                                                             %
5163 %                                                                             %
5164 %                                                                             %
5165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5166 %
5167 %  SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5168 %  or disk cache.  The method returns MagickTrue if the pixel region is synced,
5169 %  otherwise MagickFalse.
5170 %
5171 %  The format of the SyncAuthenticPixelsCache() method is:
5172 %
5173 %      MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5174 %        ExceptionInfo *exception)
5175 %
5176 %  A description of each parameter follows:
5177 %
5178 %    o image: the image.
5179 %
5180 %    o exception: return any errors or warnings in this structure.
5181 %
5182 */
5183 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5184   ExceptionInfo *exception)
5185 {
5186   CacheInfo
5187     *cache_info;
5188
5189   const int
5190     id = GetOpenMPThreadId();
5191
5192   MagickBooleanType
5193     status;
5194
5195   assert(image != (Image *) NULL);
5196   assert(image->signature == MagickSignature);
5197   assert(image->cache != (Cache) NULL);
5198   cache_info=(CacheInfo *) image->cache;
5199   assert(cache_info->signature == MagickSignature);
5200   assert(id < (int) cache_info->number_threads);
5201   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5202     exception);
5203   return(status);
5204 }
5205 \f
5206 /*
5207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5208 %                                                                             %
5209 %                                                                             %
5210 %                                                                             %
5211 %   S y n c A u t h e n t i c P i x e l s                                     %
5212 %                                                                             %
5213 %                                                                             %
5214 %                                                                             %
5215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5216 %
5217 %  SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5218 %  The method returns MagickTrue if the pixel region is flushed, otherwise
5219 %  MagickFalse.
5220 %
5221 %  The format of the SyncAuthenticPixels() method is:
5222 %
5223 %      MagickBooleanType SyncAuthenticPixels(Image *image,
5224 %        ExceptionInfo *exception)
5225 %
5226 %  A description of each parameter follows:
5227 %
5228 %    o image: the image.
5229 %
5230 %    o exception: return any errors or warnings in this structure.
5231 %
5232 */
5233 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5234   ExceptionInfo *exception)
5235 {
5236   CacheInfo
5237     *cache_info;
5238
5239   const int
5240     id = GetOpenMPThreadId();
5241
5242   MagickBooleanType
5243     status;
5244
5245   assert(image != (Image *) NULL);
5246   assert(image->signature == MagickSignature);
5247   assert(image->cache != (Cache) NULL);
5248   cache_info=(CacheInfo *) image->cache;
5249   assert(cache_info->signature == MagickSignature);
5250   if (cache_info->methods.sync_authentic_pixels_handler !=
5251        (SyncAuthenticPixelsHandler) NULL)
5252     {
5253       status=cache_info->methods.sync_authentic_pixels_handler(image,
5254         exception);
5255       return(status);
5256     }
5257   assert(id < (int) cache_info->number_threads);
5258   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5259     exception);
5260   return(status);
5261 }
5262 \f
5263 /*
5264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5265 %                                                                             %
5266 %                                                                             %
5267 %                                                                             %
5268 +   S y n c I m a g e P i x e l C a c h e                                     %
5269 %                                                                             %
5270 %                                                                             %
5271 %                                                                             %
5272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5273 %
5274 %  SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5275 %  The method returns MagickTrue if the pixel region is flushed, otherwise
5276 %  MagickFalse.
5277 %
5278 %  The format of the SyncImagePixelCache() method is:
5279 %
5280 %      MagickBooleanType SyncImagePixelCache(Image *image,
5281 %        ExceptionInfo *exception)
5282 %
5283 %  A description of each parameter follows:
5284 %
5285 %    o image: the image.
5286 %
5287 %    o exception: return any errors or warnings in this structure.
5288 %
5289 */
5290 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5291   ExceptionInfo *exception)
5292 {
5293   CacheInfo
5294     *cache_info;
5295
5296   assert(image != (Image *) NULL);
5297   assert(exception != (ExceptionInfo *) NULL);
5298   cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5299   return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5300 }
5301 \f
5302 /*
5303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5304 %                                                                             %
5305 %                                                                             %
5306 %                                                                             %
5307 +   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                       %
5308 %                                                                             %
5309 %                                                                             %
5310 %                                                                             %
5311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5312 %
5313 %  WritePixelCacheMetacontent() writes the meta-content to the specified region
5314 %  of the pixel cache.
5315 %
5316 %  The format of the WritePixelCacheMetacontent() method is:
5317 %
5318 %      MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5319 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5320 %
5321 %  A description of each parameter follows:
5322 %
5323 %    o cache_info: the pixel cache.
5324 %
5325 %    o nexus_info: the cache nexus to write the meta-content.
5326 %
5327 %    o exception: return any errors or warnings in this structure.
5328 %
5329 */
5330 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5331   NexusInfo *nexus_info,ExceptionInfo *exception)
5332 {
5333   MagickOffsetType
5334     count,
5335     offset;
5336
5337   MagickSizeType
5338     extent,
5339     length;
5340
5341   RectangleInfo
5342     region;
5343
5344   register const unsigned char
5345     *restrict p;
5346
5347   register ssize_t
5348     y;
5349
5350   if (cache_info->metacontent_extent == 0)
5351     return(MagickFalse);
5352   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5353     return(MagickTrue);
5354   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5355     nexus_info->region.x;
5356   length=(MagickSizeType) nexus_info->region.width*
5357     cache_info->metacontent_extent;
5358   extent=(MagickSizeType) length*nexus_info->region.height;
5359   region=nexus_info->region;
5360   y=0;
5361   p=(unsigned char *) nexus_info->metacontent;
5362   switch (cache_info->type)
5363   {
5364     case MemoryCache:
5365     case MapCache:
5366     {
5367       register unsigned char
5368         *restrict q;
5369
5370       /*
5371         Write associated pixels to memory.
5372       */
5373       if ((cache_info->columns == nexus_info->region.width) &&
5374           (extent == (MagickSizeType) ((size_t) extent)))
5375         {
5376           length=extent;
5377           region.height=1UL;
5378         }
5379       q=(unsigned char *) cache_info->metacontent+offset*
5380         cache_info->metacontent_extent;
5381       for (y=0; y < (ssize_t) region.height; y++)
5382       {
5383         (void) memcpy(q,p,(size_t) length);
5384         p+=nexus_info->region.width*cache_info->metacontent_extent;
5385         q+=cache_info->columns*cache_info->metacontent_extent;
5386       }
5387       break;
5388     }
5389     case DiskCache:
5390     {
5391       /*
5392         Write associated pixels to disk.
5393       */
5394       LockSemaphoreInfo(cache_info->file_semaphore);
5395       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5396         {
5397           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5398             cache_info->cache_filename);
5399           UnlockSemaphoreInfo(cache_info->file_semaphore);
5400           return(MagickFalse);
5401         }
5402       if ((cache_info->columns == nexus_info->region.width) &&
5403           (extent <= MagickMaxBufferExtent))
5404         {
5405           length=extent;
5406           region.height=1UL;
5407         }
5408       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5409       for (y=0; y < (ssize_t) region.height; y++)
5410       {
5411         count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5412           cache_info->number_channels*sizeof(Quantum)+offset*
5413           cache_info->metacontent_extent,length,(const unsigned char *) p);
5414         if (count != (MagickOffsetType) length)
5415           break;
5416         p+=cache_info->metacontent_extent*nexus_info->region.width;
5417         offset+=cache_info->columns;
5418       }
5419       if (IsFileDescriptorLimitExceeded() != MagickFalse)
5420         (void) ClosePixelCacheOnDisk(cache_info);
5421       UnlockSemaphoreInfo(cache_info->file_semaphore);
5422       break;
5423     }
5424     case DistributedCache:
5425     {
5426       /*
5427         Write metacontent to distributed cache.
5428       */
5429       LockSemaphoreInfo(cache_info->file_semaphore);
5430       region.height=1UL;
5431       for (y=0; y < (ssize_t) region.height; y++)
5432       {
5433         count=WriteDistributePixelCachePixels(cache_info->server_info,&region,
5434           length,(const unsigned char *) p);
5435         if (count != (MagickOffsetType) length)
5436           break;
5437         p+=cache_info->metacontent_extent*nexus_info->region.width;
5438         region.y++;
5439       }
5440       UnlockSemaphoreInfo(cache_info->file_semaphore);
5441       break;
5442     }
5443     default:
5444       break;
5445   }
5446   if (y < (ssize_t) region.height)
5447     {
5448       ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5449         cache_info->cache_filename);
5450       return(MagickFalse);
5451     }
5452   if ((cache_info->debug != MagickFalse) &&
5453       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5454     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5455       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5456       nexus_info->region.width,(double) nexus_info->region.height,(double)
5457       nexus_info->region.x,(double) nexus_info->region.y);
5458   return(MagickTrue);
5459 }
5460 \f
5461 /*
5462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5463 %                                                                             %
5464 %                                                                             %
5465 %                                                                             %
5466 +   W r i t e C a c h e P i x e l s                                           %
5467 %                                                                             %
5468 %                                                                             %
5469 %                                                                             %
5470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5471 %
5472 %  WritePixelCachePixels() writes image pixels to the specified region of the
5473 %  pixel cache.
5474 %
5475 %  The format of the WritePixelCachePixels() method is:
5476 %
5477 %      MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5478 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5479 %
5480 %  A description of each parameter follows:
5481 %
5482 %    o cache_info: the pixel cache.
5483 %
5484 %    o nexus_info: the cache nexus to write the pixels.
5485 %
5486 %    o exception: return any errors or warnings in this structure.
5487 %
5488 */
5489 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5490   NexusInfo *nexus_info,ExceptionInfo *exception)
5491 {
5492   MagickOffsetType
5493     count,
5494     offset;
5495
5496   MagickSizeType
5497     extent,
5498     length;
5499
5500   RectangleInfo
5501     region;
5502
5503   register const Quantum
5504     *restrict p;
5505
5506   register ssize_t
5507     y;
5508
5509   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5510     return(MagickTrue);
5511   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5512     nexus_info->region.x;
5513   length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5514     sizeof(Quantum);
5515   extent=length*nexus_info->region.height;
5516   region=nexus_info->region;
5517   y=0;
5518   p=nexus_info->pixels;
5519   switch (cache_info->type)
5520   {
5521     case MemoryCache:
5522     case MapCache:
5523     {
5524       register Quantum
5525         *restrict q;
5526
5527       /*
5528         Write pixels to memory.
5529       */
5530       if ((cache_info->columns == nexus_info->region.width) &&
5531           (extent == (MagickSizeType) ((size_t) extent)))
5532         {
5533           length=extent;
5534           region.height=1UL;
5535         }
5536       q=cache_info->pixels+offset*cache_info->number_channels;
5537       for (y=0; y < (ssize_t) region.height; y++)
5538       {
5539         (void) memcpy(q,p,(size_t) length);
5540         p+=cache_info->number_channels*nexus_info->region.width;
5541         q+=cache_info->columns*cache_info->number_channels;
5542       }
5543       break;
5544     }
5545     case DiskCache:
5546     {
5547       /*
5548         Write pixels to disk.
5549       */
5550       LockSemaphoreInfo(cache_info->file_semaphore);
5551       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5552         {
5553           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5554             cache_info->cache_filename);
5555           UnlockSemaphoreInfo(cache_info->file_semaphore);
5556           return(MagickFalse);
5557         }
5558       if ((cache_info->columns == nexus_info->region.width) &&
5559           (extent <= MagickMaxBufferExtent))
5560         {
5561           length=extent;
5562           region.height=1UL;
5563         }
5564       for (y=0; y < (ssize_t) region.height; y++)
5565       {
5566         count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5567           cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5568           p);
5569         if (count != (MagickOffsetType) length)
5570           break;
5571         p+=cache_info->number_channels*nexus_info->region.width;
5572         offset+=cache_info->columns;
5573       }
5574       if (IsFileDescriptorLimitExceeded() != MagickFalse)
5575         (void) ClosePixelCacheOnDisk(cache_info);
5576       UnlockSemaphoreInfo(cache_info->file_semaphore);
5577       break;
5578     }
5579     case DistributedCache:
5580     {
5581       /*
5582         Write pixels to distributed cache.
5583       */
5584       LockSemaphoreInfo(cache_info->file_semaphore);
5585       region.height=1UL;
5586       for (y=0; y < (ssize_t) region.height; y++)
5587       {
5588         count=WriteDistributePixelCachePixels(cache_info->server_info,&region,
5589           length,(const unsigned char *) p);
5590         if (count != (MagickOffsetType) length)
5591           break;
5592         p+=cache_info->number_channels*nexus_info->region.width;
5593         region.y++;
5594       }
5595       UnlockSemaphoreInfo(cache_info->file_semaphore);
5596       break;
5597     }
5598     default:
5599       break;
5600   }
5601   if (y < (ssize_t) region.height)
5602     {
5603       ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5604         cache_info->cache_filename);
5605       return(MagickFalse);
5606     }
5607   if ((cache_info->debug != MagickFalse) &&
5608       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5609     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5610       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5611       nexus_info->region.width,(double) nexus_info->region.height,(double)
5612       nexus_info->region.x,(double) nexus_info->region.y);
5613   return(MagickTrue);
5614 }