]> 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/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/geometry.h"
54 #include "MagickCore/list.h"
55 #include "MagickCore/log.h"
56 #include "MagickCore/magick.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/memory-private.h"
59 #include "MagickCore/nt-base-private.h"
60 #include "MagickCore/pixel.h"
61 #include "MagickCore/pixel-accessor.h"
62 #include "MagickCore/policy.h"
63 #include "MagickCore/quantum.h"
64 #include "MagickCore/random_.h"
65 #include "MagickCore/registry.h"
66 #include "MagickCore/resource_.h"
67 #include "MagickCore/semaphore.h"
68 #include "MagickCore/splay-tree.h"
69 #include "MagickCore/string_.h"
70 #include "MagickCore/string-private.h"
71 #include "MagickCore/thread-private.h"
72 #include "MagickCore/utility.h"
73 #include "MagickCore/utility-private.h"
74 #if defined(MAGICKCORE_ZLIB_DELEGATE)
75 #include "zlib.h"
76 #endif
77 \f
78 /*
79   Define declarations.
80 */
81 #define CacheTick(offset,extent)  QuantumTick((MagickOffsetType) offset,extent)
82 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
83   GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
84 \f
85 /*
86   Typedef declarations.
87 */
88 typedef struct _MagickModulo
89 {
90   ssize_t
91     quotient,
92     remainder;
93 } MagickModulo;
94
95 struct _NexusInfo
96 {
97   MagickBooleanType
98     mapped;
99
100   RectangleInfo
101     region;
102
103   MagickSizeType
104     length;
105
106   Quantum
107     *cache,
108     *pixels;
109
110   void
111     *metacontent;
112
113   size_t
114     signature;
115 };
116 \f
117 /*
118   Forward declarations.
119 */
120 #if defined(__cplusplus) || defined(c_plusplus)
121 extern "C" {
122 #endif
123
124 static Cache
125   GetImagePixelCache(Image *,const MagickBooleanType,ExceptionInfo *)
126     magick_hot_spot;
127
128 static const Quantum
129   *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
130     const ssize_t,const size_t,const size_t,ExceptionInfo *),
131   *GetVirtualPixelsCache(const Image *);
132
133 static const void
134   *GetVirtualMetacontentFromCache(const Image *);
135
136 static MagickBooleanType
137   GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,Quantum *,
138     ExceptionInfo *),
139   GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
140     const ssize_t,const ssize_t,Quantum *,ExceptionInfo *),
141   OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
142   ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
143   ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
144   SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
145   WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
146   WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
147
148 static Quantum
149   *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
150     const size_t,ExceptionInfo *),
151   *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
152     const size_t,ExceptionInfo *),
153   *SetPixelCacheNexusPixels(const Image *,const MapMode,const RectangleInfo *,
154     NexusInfo *,ExceptionInfo *) magick_hot_spot;
155
156 #if defined(__cplusplus) || defined(c_plusplus)
157 }
158 #endif
159 \f
160 /*
161   Global declarations.
162 */
163 static volatile MagickBooleanType
164   instantiate_cache = MagickFalse;
165
166 static SemaphoreInfo
167   *cache_semaphore = (SemaphoreInfo *) NULL;
168 \f
169 /*
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171 %                                                                             %
172 %                                                                             %
173 %                                                                             %
174 +   A c q u i r e P i x e l C a c h e                                         %
175 %                                                                             %
176 %                                                                             %
177 %                                                                             %
178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179 %
180 %  AcquirePixelCache() acquires a pixel cache.
181 %
182 %  The format of the AcquirePixelCache() method is:
183 %
184 %      Cache AcquirePixelCache(const size_t number_threads)
185 %
186 %  A description of each parameter follows:
187 %
188 %    o number_threads: the number of nexus threads.
189 %
190 */
191 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
192 {
193   CacheInfo
194     *cache_info;
195
196   char
197     *synchronize;
198
199   cache_info=(CacheInfo *) AcquireQuantumMemory(1,sizeof(*cache_info));
200   if (cache_info == (CacheInfo *) NULL)
201     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
202   (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
203   cache_info->type=UndefinedCache;
204   cache_info->mode=IOMode;
205   cache_info->colorspace=sRGBColorspace;
206   cache_info->file=(-1);
207   cache_info->id=GetMagickThreadId();
208   cache_info->number_threads=number_threads;
209   if (GetOpenMPMaximumThreads() > cache_info->number_threads)
210     cache_info->number_threads=GetOpenMPMaximumThreads();
211   if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
212     cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
213   if (cache_info->number_threads == 0)
214     cache_info->number_threads=1;
215   cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
216   if (cache_info->nexus_info == (NexusInfo **) NULL)
217     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
218   synchronize=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
219   if (synchronize != (const char *) NULL)
220     {
221       cache_info->synchronize=IsStringTrue(synchronize);
222       synchronize=DestroyString(synchronize);
223     }
224   cache_info->semaphore=AllocateSemaphoreInfo();
225   cache_info->reference_count=1;
226   cache_info->file_semaphore=AllocateSemaphoreInfo();
227   cache_info->debug=IsEventLogging();
228   cache_info->signature=MagickSignature;
229   return((Cache ) cache_info);
230 }
231 \f
232 /*
233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 %                                                                             %
235 %                                                                             %
236 %                                                                             %
237 %   A c q u i r e P i x e l C a c h e N e x u s                               %
238 %                                                                             %
239 %                                                                             %
240 %                                                                             %
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 %
243 %  AcquirePixelCacheNexus() allocates the NexusInfo structure.
244 %
245 %  The format of the AcquirePixelCacheNexus method is:
246 %
247 %      NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
248 %
249 %  A description of each parameter follows:
250 %
251 %    o number_threads: the number of nexus threads.
252 %
253 */
254 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
255 {
256   NexusInfo
257     **nexus_info;
258
259   register ssize_t
260     i;
261
262   nexus_info=(NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(
263     number_threads,sizeof(*nexus_info)));
264   if (nexus_info == (NexusInfo **) NULL)
265     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
266   nexus_info[0]=(NexusInfo *) AcquireQuantumMemory(number_threads,
267     sizeof(**nexus_info));
268   if (nexus_info[0] == (NexusInfo *) NULL)
269     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
270   (void) ResetMagickMemory(nexus_info[0],0,number_threads*sizeof(**nexus_info));
271   for (i=0; i < (ssize_t) number_threads; i++)
272   {
273     nexus_info[i]=(&nexus_info[0][i]);
274     nexus_info[i]->signature=MagickSignature;
275   }
276   return(nexus_info);
277 }
278 \f
279 /*
280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
281 %                                                                             %
282 %                                                                             %
283 %                                                                             %
284 +   A c q u i r e P i x e l C a c h e P i x e l s                             %
285 %                                                                             %
286 %                                                                             %
287 %                                                                             %
288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 %
290 %  AcquirePixelCachePixels() returns the pixels associated with the specified
291 %  image.
292 %
293 %  The format of the AcquirePixelCachePixels() method is:
294 %
295 %      const void *AcquirePixelCachePixels(const Image *image,
296 %        MagickSizeType *length,ExceptionInfo *exception)
297 %
298 %  A description of each parameter follows:
299 %
300 %    o image: the image.
301 %
302 %    o length: the pixel cache length.
303 %
304 %    o exception: return any errors or warnings in this structure.
305 %
306 */
307 MagickPrivate const void *AcquirePixelCachePixels(const Image *image,
308   MagickSizeType *length,ExceptionInfo *exception)
309 {
310   CacheInfo
311     *cache_info;
312
313   assert(image != (const Image *) NULL);
314   assert(image->signature == MagickSignature);
315   assert(exception != (ExceptionInfo *) NULL);
316   assert(exception->signature == MagickSignature);
317   assert(image->cache != (Cache) NULL);
318   cache_info=(CacheInfo *) image->cache;
319   assert(cache_info->signature == MagickSignature);
320   *length=0;
321   if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
322     return((const void *) NULL);
323   *length=cache_info->length;
324   return((const void *) cache_info->pixels);
325 }
326 \f
327 /*
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 %                                                                             %
330 %                                                                             %
331 %                                                                             %
332 +   C a c h e C o m p o n e n t G e n e s i s                                 %
333 %                                                                             %
334 %                                                                             %
335 %                                                                             %
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %
338 %  CacheComponentGenesis() instantiates the cache component.
339 %
340 %  The format of the CacheComponentGenesis method is:
341 %
342 %      MagickBooleanType CacheComponentGenesis(void)
343 %
344 */
345 MagickPrivate MagickBooleanType CacheComponentGenesis(void)
346 {
347   AcquireSemaphoreInfo(&cache_semaphore);
348   return(MagickTrue);
349 }
350 \f
351 /*
352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353 %                                                                             %
354 %                                                                             %
355 %                                                                             %
356 +   C a c h e C o m p o n e n t T e r m i n u s                               %
357 %                                                                             %
358 %                                                                             %
359 %                                                                             %
360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 %
362 %  CacheComponentTerminus() destroys the cache component.
363 %
364 %  The format of the CacheComponentTerminus() method is:
365 %
366 %      CacheComponentTerminus(void)
367 %
368 */
369 MagickPrivate void CacheComponentTerminus(void)
370 {
371   if (cache_semaphore == (SemaphoreInfo *) NULL)
372     AcquireSemaphoreInfo(&cache_semaphore);
373   LockSemaphoreInfo(cache_semaphore);
374   instantiate_cache=MagickFalse;
375   UnlockSemaphoreInfo(cache_semaphore);
376   DestroySemaphoreInfo(&cache_semaphore);
377 }
378 \f
379 /*
380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381 %                                                                             %
382 %                                                                             %
383 %                                                                             %
384 +   C l o n e P i x e l C a c h e                                             %
385 %                                                                             %
386 %                                                                             %
387 %                                                                             %
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 %
390 %  ClonePixelCache() clones a pixel cache.
391 %
392 %  The format of the ClonePixelCache() method is:
393 %
394 %      Cache ClonePixelCache(const Cache cache)
395 %
396 %  A description of each parameter follows:
397 %
398 %    o cache: the pixel cache.
399 %
400 */
401 MagickPrivate Cache ClonePixelCache(const Cache cache)
402 {
403   CacheInfo
404     *clone_info;
405
406   const CacheInfo
407     *cache_info;
408
409   assert(cache != NULL);
410   cache_info=(const CacheInfo *) cache;
411   assert(cache_info->signature == MagickSignature);
412   if (cache_info->debug != MagickFalse)
413     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
414       cache_info->filename);
415   clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
416   if (clone_info == (Cache) NULL)
417     return((Cache) NULL);
418   clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
419   return((Cache ) clone_info);
420 }
421 \f
422 /*
423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424 %                                                                             %
425 %                                                                             %
426 %                                                                             %
427 +   C l o n e P i x e l C a c h e P i x e l s                                 %
428 %                                                                             %
429 %                                                                             %
430 %                                                                             %
431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
432 %  ClonePixelCachePixels() clones the source pixel cache to the destination
433 %  cache.
434 %
435 %  The format of the ClonePixelCachePixels() method is:
436 %
437 %      MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
438 %        CacheInfo *source_info,ExceptionInfo *exception)
439 %
440 %  A description of each parameter follows:
441 %
442 %    o cache_info: the pixel cache.
443 %
444 %    o source_info: the source pixel cache.
445 %
446 %    o exception: return any errors or warnings in this structure.
447 %
448 */
449
450 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
451 {
452   int
453     status;
454
455   status=(-1);
456   if (cache_info->file != -1)
457     {
458       status=close(cache_info->file);
459       cache_info->file=(-1);
460       RelinquishMagickResource(FileResource,1);
461     }
462   return(status == -1 ? MagickFalse : MagickTrue);
463 }
464
465 static inline MagickSizeType MagickMax(const MagickSizeType x,
466   const MagickSizeType y)
467 {
468   if (x > y)
469     return(x);
470   return(y);
471 }
472
473 static inline MagickSizeType MagickMin(const MagickSizeType x,
474   const MagickSizeType y)
475 {
476   if (x < y)
477     return(x);
478   return(y);
479 }
480
481 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
482   const MapMode mode)
483 {
484   int
485     file;
486
487   /*
488     Open pixel cache on disk.
489   */
490   if (cache_info->file != -1)
491     return(MagickTrue);  /* cache already open */
492   if (*cache_info->cache_filename == '\0')
493     file=AcquireUniqueFileResource(cache_info->cache_filename);
494   else
495     switch (mode)
496     {
497       case ReadMode:
498       {
499         file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
500         break;
501       }
502       case WriteMode:
503       {
504         file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
505           O_BINARY | O_EXCL,S_MODE);
506         if (file == -1)
507           file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
508         break;
509       }
510       case IOMode:
511       default:
512       {
513         file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
514           O_EXCL,S_MODE);
515         if (file == -1)
516           file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
517         break;
518       }
519     }
520   if (file == -1)
521     return(MagickFalse);
522   (void) AcquireMagickResource(FileResource,1);
523   cache_info->file=file;
524   cache_info->mode=mode;
525   return(MagickTrue);
526 }
527
528 static inline MagickOffsetType ReadPixelCacheRegion(
529   const CacheInfo *restrict cache_info,const MagickOffsetType offset,
530   const MagickSizeType length,unsigned char *restrict buffer)
531 {
532   register MagickOffsetType
533     i;
534
535   ssize_t
536     count;
537
538 #if !defined(MAGICKCORE_HAVE_PREAD)
539   if (lseek(cache_info->file,offset,SEEK_SET) < 0)
540     return((MagickOffsetType) -1);
541 #endif
542   count=0;
543   for (i=0; i < (MagickOffsetType) length; i+=count)
544   {
545 #if !defined(MAGICKCORE_HAVE_PREAD)
546     count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
547       (MagickSizeType) SSIZE_MAX));
548 #else
549     count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
550       (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
551 #endif
552     if (count <= 0)
553       {
554         count=0;
555         if (errno != EINTR)
556           break;
557       }
558   }
559   return(i);
560 }
561
562 static inline MagickOffsetType WritePixelCacheRegion(
563   const CacheInfo *restrict cache_info,const MagickOffsetType offset,
564   const MagickSizeType length,const unsigned char *restrict buffer)
565 {
566   register MagickOffsetType
567     i;
568
569   ssize_t
570     count;
571
572 #if !defined(MAGICKCORE_HAVE_PWRITE)
573   if (lseek(cache_info->file,offset,SEEK_SET) < 0)
574     return((MagickOffsetType) -1);
575 #endif
576   count=0;
577   for (i=0; i < (MagickOffsetType) length; i+=count)
578   {
579 #if !defined(MAGICKCORE_HAVE_PWRITE)
580     count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
581       (MagickSizeType) SSIZE_MAX));
582 #else
583     count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
584       (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
585 #endif
586     if (count <= 0)
587       {
588         count=0;
589         if (errno != EINTR)
590           break;
591       }
592   }
593   return(i);
594 }
595
596 static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info,
597   CacheInfo *cache_info,ExceptionInfo *exception)
598 {
599   MagickOffsetType
600     count;
601
602   register MagickOffsetType
603     i;
604
605   size_t
606     length;
607
608   unsigned char
609     *blob;
610
611   /*
612     Clone pixel cache (both caches on disk).
613   */
614   if (cache_info->debug != MagickFalse)
615     (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
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       if (cache_info->debug != MagickFalse)
681         (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
682       (void) memcpy(clone_info->pixels,cache_info->pixels,(size_t)
683         cache_info->length);
684       return(MagickTrue);
685     }
686   if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
687     {
688       /*
689         Clone pixel cache (one cache on disk, one in memory).
690       */
691       if (cache_info->debug != MagickFalse)
692         (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
693       if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
694         {
695           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
696             cache_info->cache_filename);
697           return(MagickFalse);
698         }
699       count=ReadPixelCacheRegion(cache_info,cache_info->offset,
700         cache_info->length,(unsigned char *) clone_info->pixels);
701       (void) ClosePixelCacheOnDisk(cache_info);
702       if ((MagickSizeType) count != cache_info->length)
703         {
704           ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
705             cache_info->cache_filename);
706           return(MagickFalse);
707         }
708       return(MagickTrue);
709     }
710   if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
711     {
712       /*
713         Clone pixel cache (one cache on disk, one in memory).
714       */
715       if (clone_info->debug != MagickFalse)
716         (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
717       if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
718         {
719           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
720             clone_info->cache_filename);
721           return(MagickFalse);
722         }
723       count=WritePixelCacheRegion(clone_info,clone_info->offset,
724         clone_info->length,(unsigned char *) cache_info->pixels);
725       (void) ClosePixelCacheOnDisk(clone_info);
726       if ((MagickSizeType) count != clone_info->length)
727         {
728           ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
729             clone_info->cache_filename);
730           return(MagickFalse);
731         }
732       return(MagickTrue);
733     }
734   /*
735     Clone pixel cache (both caches on disk).
736   */
737   return(DiskToDiskPixelCacheClone(clone_info,cache_info,exception));
738 }
739
740 static MagickBooleanType PixelCacheCloneUnoptimized(CacheInfo *clone_info,
741   CacheInfo *cache_info,ExceptionInfo *exception)
742 {
743   MagickBooleanType
744     status;
745
746   MagickOffsetType
747     cache_offset,
748     clone_offset,
749     count;
750
751   register ssize_t
752     x;
753
754   register unsigned char
755     *p;
756
757   size_t
758     length;
759
760   ssize_t
761     y;
762
763   unsigned char
764     *blob;
765
766   /*
767     Clone pixel cache (unoptimized).
768   */
769   if (cache_info->debug != MagickFalse)
770     {
771       if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
772         (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
773       else
774        if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
775          (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
776        else
777          if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
778            (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
779          else
780            (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
781     }
782   length=(size_t) MagickMax(MagickMax(cache_info->number_channels,
783     clone_info->number_channels)*sizeof(Quantum),MagickMax(
784     cache_info->metacontent_extent,clone_info->metacontent_extent));
785   blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blob));
786   if (blob == (unsigned char *) NULL)
787     {
788       (void) ThrowMagickException(exception,GetMagickModule(),
789         ResourceLimitError,"MemoryAllocationFailed","`%s'",
790         cache_info->filename);
791       return(MagickFalse);
792     }
793   (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
794   cache_offset=0;
795   clone_offset=0;
796   if (cache_info->type == DiskCache)
797     {
798       if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
799         {
800           blob=(unsigned char *) RelinquishMagickMemory(blob);
801           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
802             cache_info->cache_filename);
803           return(MagickFalse);
804         }
805       cache_offset=cache_info->offset;
806     }
807   if (clone_info->type == DiskCache)
808     {
809       if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
810         {
811           blob=(unsigned char *) RelinquishMagickMemory(blob);
812           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
813             clone_info->cache_filename);
814           return(MagickFalse);
815         }
816       clone_offset=clone_info->offset;
817     }
818   /*
819     Clone pixel channels.
820   */
821   status=MagickTrue;
822   p=blob;
823   for (y=0; y < (ssize_t) cache_info->rows; y++)
824   {
825     for (x=0; x < (ssize_t) cache_info->columns; x++)
826     {
827       register ssize_t
828         i;
829
830       /*
831         Read a set of pixel channels.
832       */
833       length=cache_info->number_channels*sizeof(Quantum);
834       if (cache_info->type != DiskCache)
835         p=(unsigned char *) cache_info->pixels+cache_offset;
836       else
837         {
838           count=ReadPixelCacheRegion(cache_info,cache_offset,length,p);
839           if ((MagickSizeType) count != length)
840             {
841               status=MagickFalse;
842               break;
843             }
844         }
845       cache_offset+=length;
846       if ((y < (ssize_t) clone_info->rows) &&
847           (x < (ssize_t) clone_info->columns))
848         for (i=0; i < (ssize_t) clone_info->number_channels; i++)
849         {
850           PixelChannel
851             channel;
852
853           PixelTrait
854             traits;
855
856           ssize_t
857             offset;
858
859           /*
860             Write a set of pixel channels.
861           */
862           channel=clone_info->channel_map[i].channel;
863           traits=cache_info->channel_map[channel].traits;
864           if (traits == UndefinedPixelTrait)
865             {
866               clone_offset+=sizeof(Quantum);
867               continue;
868             }
869           offset=cache_info->channel_map[channel].offset;
870           if (clone_info->type != DiskCache)
871             (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,p+
872               offset*sizeof(Quantum),sizeof(Quantum));
873           else
874             {
875               count=WritePixelCacheRegion(clone_info,clone_offset,
876                 sizeof(Quantum),p+offset*sizeof(Quantum));
877               if ((MagickSizeType) count != sizeof(Quantum))
878                 {
879                   status=MagickFalse;
880                   break;
881                 }
882             }
883           clone_offset+=sizeof(Quantum);
884         }
885     }
886     if (y < (ssize_t) clone_info->rows)
887       {
888         /*
889           Set remaining columns as undefined.
890         */
891         length=clone_info->number_channels*sizeof(Quantum);
892         (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
893         for ( ; x < (ssize_t) clone_info->columns; x++)
894         {
895           if (clone_info->type != DiskCache)
896             (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
897               blob,length);
898           else
899             {
900               count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
901               if ((MagickSizeType) count != length)
902                 {
903                   status=MagickFalse;
904                   break;
905               }
906             }
907           clone_offset+=length;
908         }
909       }
910   }
911   length=clone_info->number_channels*sizeof(Quantum);
912   (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
913   for ( ; y < (ssize_t) clone_info->rows; y++)
914   {
915     /*
916       Set remaining rows as undefined.
917     */
918     for (x=0; x < (ssize_t) clone_info->columns; x++)
919     {
920       if (clone_info->type != DiskCache)
921         (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
922           length);
923       else
924         {
925           count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
926           if ((MagickSizeType) count != length)
927             {
928               status=MagickFalse;
929               break;
930             }
931         }
932       clone_offset+=length;
933     }
934   }
935   if ((cache_info->metacontent_extent != 0) ||
936       (clone_info->metacontent_extent != 0))
937     {
938       /*
939         Clone metacontent.
940       */
941       for (y=0; y < (ssize_t) cache_info->rows; y++)
942       {
943         for (x=0; x < (ssize_t) cache_info->columns; x++)
944         {
945           /*
946             Read a set of metacontent.
947           */
948           length=cache_info->metacontent_extent;
949           if (cache_info->type != DiskCache)
950             p=(unsigned char *) cache_info->pixels+cache_offset;
951           else
952             {
953               count=ReadPixelCacheRegion(cache_info,cache_offset,length,p);
954               if ((MagickSizeType) count != length)
955                 {
956                   status=MagickFalse;
957                   break;
958                 }
959             }
960           cache_offset+=length;
961           if ((y < (ssize_t) clone_info->rows) &&
962               (x < (ssize_t) clone_info->columns))
963             {
964               /*
965                 Write a set of metacontent.
966               */
967               length=clone_info->metacontent_extent;
968               if (clone_info->type != DiskCache)
969                 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
970                   p,length);
971               else
972                 {
973                   count=WritePixelCacheRegion(clone_info,clone_offset,length,p);
974                   if ((MagickSizeType) count != length)
975                     {
976                       status=MagickFalse;
977                       break;
978                     }
979                 }
980               clone_offset+=length;
981             }
982         }
983         length=clone_info->metacontent_extent;
984         (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
985         for ( ; x < (ssize_t) clone_info->columns; x++)
986         {
987           /*
988             Set remaining columns as undefined.
989           */
990           if (clone_info->type != DiskCache)
991             (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
992               blob,length);
993           else
994             {
995               count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
996               if ((MagickSizeType) count != length)
997                 {
998                   status=MagickFalse;
999                   break;
1000                 }
1001             }
1002           clone_offset+=length;
1003         }
1004       }
1005       if (y < (ssize_t) clone_info->rows)
1006         {
1007           /*
1008             Set remaining rows as undefined.
1009           */
1010           length=clone_info->metacontent_extent;
1011           (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1012           for ( ; y < (ssize_t) clone_info->rows; y++)
1013           {
1014             for (x=0; x < (ssize_t) clone_info->columns; x++)
1015             {
1016               if (clone_info->type != DiskCache)
1017                 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1018                   blob,length);
1019               else
1020                 {
1021                   count=WritePixelCacheRegion(clone_info,clone_offset,length,
1022                     blob);
1023                   if ((MagickSizeType) count != length)
1024                     {
1025                       status=MagickFalse;
1026                       break;
1027                     }
1028                 }
1029               clone_offset+=length;
1030             }
1031           }
1032         }
1033     }
1034   if (clone_info->type == DiskCache)
1035     (void) ClosePixelCacheOnDisk(clone_info);
1036   if (cache_info->type == DiskCache)
1037     (void) ClosePixelCacheOnDisk(cache_info);
1038   blob=(unsigned char *) RelinquishMagickMemory(blob);
1039   return(status);
1040 }
1041
1042 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1043   CacheInfo *cache_info,ExceptionInfo *exception)
1044 {
1045   PixelChannelMap
1046     *p,
1047     *q;
1048
1049   if (cache_info->type == PingCache)
1050     return(MagickTrue);
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       abort();
1240       break;
1241     }
1242     default:
1243       break;
1244   }
1245   cache_info->type=UndefinedCache;
1246   cache_info->mapped=MagickFalse;
1247   cache_info->metacontent=(void *) NULL;
1248 }
1249
1250 MagickPrivate Cache DestroyPixelCache(Cache cache)
1251 {
1252   CacheInfo
1253     *cache_info;
1254
1255   assert(cache != (Cache) NULL);
1256   cache_info=(CacheInfo *) cache;
1257   assert(cache_info->signature == MagickSignature);
1258   if (cache_info->debug != MagickFalse)
1259     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1260       cache_info->filename);
1261   LockSemaphoreInfo(cache_info->semaphore);
1262   cache_info->reference_count--;
1263   if (cache_info->reference_count != 0)
1264     {
1265       UnlockSemaphoreInfo(cache_info->semaphore);
1266       return((Cache) NULL);
1267     }
1268   UnlockSemaphoreInfo(cache_info->semaphore);
1269   if (cache_info->debug != MagickFalse)
1270     {
1271       char
1272         message[MaxTextExtent];
1273
1274       (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
1275         cache_info->filename);
1276       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1277     }
1278   RelinquishPixelCachePixels(cache_info);
1279   if (cache_info->distribute_cache_info != (DistributeCacheInfo *) NULL)
1280     cache_info->distribute_cache_info=
1281       DestroyDistributeCacheInfo(cache_info->distribute_cache_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   MagickBooleanType
3738     status;
3739
3740   MagickSizeType
3741     length,
3742     number_pixels;
3743
3744   size_t
3745     columns,
3746     packet_size;
3747
3748   assert(image != (const Image *) NULL);
3749   assert(image->signature == MagickSignature);
3750   assert(image->cache != (Cache) NULL);
3751   if (image->debug != MagickFalse)
3752     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3753   if ((image->columns == 0) || (image->rows == 0))
3754     ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3755   cache_info=(CacheInfo *) image->cache;
3756   assert(cache_info->signature == MagickSignature);
3757   source_info=(*cache_info);
3758   source_info.file=(-1);
3759   (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
3760     image->filename,(double) GetImageIndexInList(image));
3761   cache_info->storage_class=image->storage_class;
3762   cache_info->colorspace=image->colorspace;
3763   cache_info->alpha_trait=image->alpha_trait;
3764   cache_info->mask=image->mask;
3765   cache_info->rows=image->rows;
3766   cache_info->columns=image->columns;
3767   InitializePixelChannelMap(image);
3768   cache_info->number_channels=GetPixelChannels(image);
3769   (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3770     sizeof(*image->channel_map));
3771   cache_info->metacontent_extent=image->metacontent_extent;
3772   cache_info->mode=mode;
3773   if (image->ping != MagickFalse)
3774     {
3775       cache_info->type=PingCache;
3776       cache_info->pixels=(Quantum *) NULL;
3777       cache_info->metacontent=(void *) NULL;
3778       cache_info->length=0;
3779       return(MagickTrue);
3780     }
3781   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3782   packet_size=cache_info->number_channels*sizeof(Quantum);
3783   if (image->metacontent_extent != 0)
3784     packet_size+=cache_info->metacontent_extent;
3785   length=number_pixels*packet_size;
3786   columns=(size_t) (length/cache_info->rows/packet_size);
3787   if (cache_info->columns != columns)
3788     ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
3789       image->filename);
3790   cache_info->length=length;
3791   status=AcquireMagickResource(AreaResource,cache_info->length);
3792   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3793     cache_info->metacontent_extent);
3794   if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
3795     {
3796       status=AcquireMagickResource(MemoryResource,cache_info->length);
3797       if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
3798           (cache_info->type == MemoryCache))
3799         {
3800           AllocatePixelCachePixels(cache_info);
3801           if (cache_info->pixels == (Quantum *) NULL)
3802             cache_info->pixels=source_info.pixels;
3803           else
3804             {
3805               /*
3806                 Create memory pixel cache.
3807               */
3808               status=MagickTrue;
3809               cache_info->type=MemoryCache;
3810               cache_info->metacontent=(void *) NULL;
3811               if (cache_info->metacontent_extent != 0)
3812                 cache_info->metacontent=(void *) (cache_info->pixels+
3813                   number_pixels*cache_info->number_channels);
3814               if ((source_info.storage_class != UndefinedClass) &&
3815                   (mode != ReadMode))
3816                 {
3817                   status=ClonePixelCachePixels(cache_info,&source_info,
3818                     exception);
3819                   RelinquishPixelCachePixels(&source_info);
3820                 }
3821               if (image->debug != MagickFalse)
3822                 {
3823                   (void) FormatMagickSize(cache_info->length,MagickTrue,format);
3824                   (void) FormatLocaleString(message,MaxTextExtent,
3825                     "open %s (%s memory, %.20gx%.20gx%.20g %s)",
3826                     cache_info->filename,cache_info->mapped != MagickFalse ?
3827                     "anonymous" : "heap",(double) cache_info->columns,(double)
3828                     cache_info->rows,(double) cache_info->number_channels,
3829                     format);
3830                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3831                     message);
3832                 }
3833               return(status);
3834             }
3835         }
3836       RelinquishMagickResource(MemoryResource,cache_info->length);
3837     }
3838   /*
3839     Create pixel cache on disk.
3840   */
3841   status=AcquireMagickResource(DiskResource,cache_info->length);
3842   if (status == MagickFalse)
3843     {
3844       cache_info->distribute_cache_info=AcquireDistributeCacheInfo();
3845       if (cache_info->distribute_cache_info != (DistributeCacheInfo *) NULL)
3846         return(MagickTrue);
3847       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3848         "CacheResourcesExhausted","`%s'",image->filename);
3849       return(MagickFalse);
3850     }
3851   if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3852     {
3853       (void) ClosePixelCacheOnDisk(cache_info);
3854       *cache_info->cache_filename='\0';
3855     }
3856   if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3857     {
3858       RelinquishMagickResource(DiskResource,cache_info->length);
3859       ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3860         image->filename);
3861       return(MagickFalse);
3862     }
3863   status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3864     cache_info->length);
3865   if (status == MagickFalse)
3866     {
3867       ThrowFileException(exception,CacheError,"UnableToExtendCache",
3868         image->filename);
3869       return(MagickFalse);
3870     }
3871   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3872     cache_info->metacontent_extent);
3873   if (length != (MagickSizeType) ((size_t) length))
3874     cache_info->type=DiskCache;
3875   else
3876     {
3877       status=AcquireMagickResource(MapResource,cache_info->length);
3878       if ((status == MagickFalse) && (cache_info->type != MapCache) &&
3879           (cache_info->type != MemoryCache))
3880         cache_info->type=DiskCache;
3881       else
3882         {
3883           cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3884             cache_info->offset,(size_t) cache_info->length);
3885           if (cache_info->pixels == (Quantum *) NULL)
3886             {
3887               cache_info->type=DiskCache;
3888               cache_info->pixels=source_info.pixels;
3889             }
3890           else
3891             {
3892               /*
3893                 Create file-backed memory-mapped pixel cache.
3894               */
3895               status=MagickTrue;
3896               (void) ClosePixelCacheOnDisk(cache_info);
3897               cache_info->type=MapCache;
3898               cache_info->mapped=MagickTrue;
3899               cache_info->metacontent=(void *) NULL;
3900               if (cache_info->metacontent_extent != 0)
3901                 cache_info->metacontent=(void *) (cache_info->pixels+
3902                   number_pixels*cache_info->number_channels);
3903               if ((source_info.storage_class != UndefinedClass) &&
3904                   (mode != ReadMode))
3905                 {
3906                   status=ClonePixelCachePixels(cache_info,&source_info,
3907                     exception);
3908                   RelinquishPixelCachePixels(&source_info);
3909                 }
3910               if (image->debug != MagickFalse)
3911                 {
3912                   (void) FormatMagickSize(cache_info->length,MagickTrue,format);
3913                   (void) FormatLocaleString(message,MaxTextExtent,
3914                     "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
3915                     cache_info->filename,cache_info->cache_filename,
3916                     cache_info->file,(double) cache_info->columns,(double)
3917                     cache_info->rows,(double) cache_info->number_channels,
3918                     format);
3919                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3920                     message);
3921                 }
3922               return(status);
3923             }
3924         }
3925       RelinquishMagickResource(MapResource,cache_info->length);
3926     }
3927   status=MagickTrue;
3928   if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3929     {
3930       status=ClonePixelCachePixels(cache_info,&source_info,exception);
3931       RelinquishPixelCachePixels(&source_info);
3932     }
3933   if (image->debug != MagickFalse)
3934     {
3935       (void) FormatMagickSize(cache_info->length,MagickFalse,format);
3936       (void) FormatLocaleString(message,MaxTextExtent,
3937         "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
3938         cache_info->cache_filename,cache_info->file,(double)
3939         cache_info->columns,(double) cache_info->rows,(double)
3940         cache_info->number_channels,format);
3941       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3942     }
3943   return(status);
3944 }
3945 \f
3946 /*
3947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3948 %                                                                             %
3949 %                                                                             %
3950 %                                                                             %
3951 +   P e r s i s t P i x e l C a c h e                                         %
3952 %                                                                             %
3953 %                                                                             %
3954 %                                                                             %
3955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3956 %
3957 %  PersistPixelCache() attaches to or initializes a persistent pixel cache.  A
3958 %  persistent pixel cache is one that resides on disk and is not destroyed
3959 %  when the program exits.
3960 %
3961 %  The format of the PersistPixelCache() method is:
3962 %
3963 %      MagickBooleanType PersistPixelCache(Image *image,const char *filename,
3964 %        const MagickBooleanType attach,MagickOffsetType *offset,
3965 %        ExceptionInfo *exception)
3966 %
3967 %  A description of each parameter follows:
3968 %
3969 %    o image: the image.
3970 %
3971 %    o filename: the persistent pixel cache filename.
3972 %
3973 %    o attach: A value other than zero initializes the persistent pixel cache.
3974 %
3975 %    o initialize: A value other than zero initializes the persistent pixel
3976 %      cache.
3977 %
3978 %    o offset: the offset in the persistent cache to store pixels.
3979 %
3980 %    o exception: return any errors or warnings in this structure.
3981 %
3982 */
3983 MagickExport MagickBooleanType PersistPixelCache(Image *image,
3984   const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
3985   ExceptionInfo *exception)
3986 {
3987   CacheInfo
3988     *cache_info,
3989     *clone_info;
3990
3991   Image
3992     clone_image;
3993
3994   MagickBooleanType
3995     status;
3996
3997   ssize_t
3998     page_size;
3999
4000   assert(image != (Image *) NULL);
4001   assert(image->signature == MagickSignature);
4002   if (image->debug != MagickFalse)
4003     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4004   assert(image->cache != (void *) NULL);
4005   assert(filename != (const char *) NULL);
4006   assert(offset != (MagickOffsetType *) NULL);
4007   page_size=GetMagickPageSize();
4008   cache_info=(CacheInfo *) image->cache;
4009   assert(cache_info->signature == MagickSignature);
4010   if (attach != MagickFalse)
4011     {
4012       /*
4013         Attach existing persistent pixel cache.
4014       */
4015       if (image->debug != MagickFalse)
4016         (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4017           "attach persistent cache");
4018       (void) CopyMagickString(cache_info->cache_filename,filename,
4019         MaxTextExtent);
4020       cache_info->type=DiskCache;
4021       cache_info->offset=(*offset);
4022       if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4023         return(MagickFalse);
4024       *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4025       return(MagickTrue);
4026     }
4027   if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4028       (cache_info->reference_count == 1))
4029     {
4030       LockSemaphoreInfo(cache_info->semaphore);
4031       if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4032           (cache_info->reference_count == 1))
4033         {
4034           int
4035             status;
4036
4037           /*
4038             Usurp existing persistent pixel cache.
4039           */
4040           status=rename_utf8(cache_info->cache_filename,filename);
4041           if (status == 0)
4042             {
4043               (void) CopyMagickString(cache_info->cache_filename,filename,
4044                 MaxTextExtent);
4045               *offset+=cache_info->length+page_size-(cache_info->length %
4046                 page_size);
4047               UnlockSemaphoreInfo(cache_info->semaphore);
4048               cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4049               if (image->debug != MagickFalse)
4050                 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4051                   "Usurp resident persistent cache");
4052               return(MagickTrue);
4053             }
4054         }
4055       UnlockSemaphoreInfo(cache_info->semaphore);
4056     }
4057   /*
4058     Clone persistent pixel cache.
4059   */
4060   clone_image=(*image);
4061   clone_info=(CacheInfo *) clone_image.cache;
4062   image->cache=ClonePixelCache(cache_info);
4063   cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4064   (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4065   cache_info->type=DiskCache;
4066   cache_info->offset=(*offset);
4067   cache_info=(CacheInfo *) image->cache;
4068   status=OpenPixelCache(image,IOMode,exception);
4069   if (status != MagickFalse)
4070     status=ClonePixelCachePixels(cache_info,clone_info,exception);
4071   *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4072   clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4073   return(status);
4074 }
4075 \f
4076 /*
4077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4078 %                                                                             %
4079 %                                                                             %
4080 %                                                                             %
4081 +   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                 %
4082 %                                                                             %
4083 %                                                                             %
4084 %                                                                             %
4085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4086 %
4087 %  QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
4088 %  defined by the region rectangle and returns a pointer to the region.  This
4089 %  region is subsequently transferred from the pixel cache with
4090 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
4091 %  pixels are transferred, otherwise a NULL is returned.
4092 %
4093 %  The format of the QueueAuthenticPixelCacheNexus() method is:
4094 %
4095 %      Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
4096 %        const ssize_t y,const size_t columns,const size_t rows,
4097 %        const MagickBooleanType clone,NexusInfo *nexus_info,
4098 %        ExceptionInfo *exception)
4099 %
4100 %  A description of each parameter follows:
4101 %
4102 %    o image: the image.
4103 %
4104 %    o x,y,columns,rows:  These values define the perimeter of a region of
4105 %      pixels.
4106 %
4107 %    o nexus_info: the cache nexus to set.
4108 %
4109 %    o clone: clone the pixel cache.
4110 %
4111 %    o exception: return any errors or warnings in this structure.
4112 %
4113 */
4114 MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4115   const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
4116   const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4117 {
4118   CacheInfo
4119     *cache_info;
4120
4121   MagickOffsetType
4122     offset;
4123
4124   MagickSizeType
4125     number_pixels;
4126
4127   RectangleInfo
4128     region;
4129
4130   /*
4131     Validate pixel cache geometry.
4132   */
4133   assert(image != (const Image *) NULL);
4134   assert(image->signature == MagickSignature);
4135   assert(image->cache != (Cache) NULL);
4136   cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4137   if (cache_info == (Cache) NULL)
4138     return((Quantum *) NULL);
4139   assert(cache_info->signature == MagickSignature);
4140   if ((cache_info->columns == 0) && (cache_info->rows == 0))
4141     {
4142       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4143         "NoPixelsDefinedInCache","`%s'",image->filename);
4144       return((Quantum *) NULL);
4145     }
4146   if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4147       (y >= (ssize_t) cache_info->rows))
4148     {
4149       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4150         "PixelsAreNotAuthentic","`%s'",image->filename);
4151       return((Quantum *) NULL);
4152     }
4153   offset=(MagickOffsetType) y*cache_info->columns+x;
4154   if (offset < 0)
4155     return((Quantum *) NULL);
4156   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4157   offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4158   if ((MagickSizeType) offset >= number_pixels)
4159     return((Quantum *) NULL);
4160   /*
4161     Return pixel cache.
4162   */
4163   region.x=x;
4164   region.y=y;
4165   region.width=columns;
4166   region.height=rows;
4167   return(SetPixelCacheNexusPixels(image,WriteMode,&region,nexus_info,exception));
4168 }
4169 \f
4170 /*
4171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4172 %                                                                             %
4173 %                                                                             %
4174 %                                                                             %
4175 +   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                         %
4176 %                                                                             %
4177 %                                                                             %
4178 %                                                                             %
4179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4180 %
4181 %  QueueAuthenticPixelsCache() allocates an region to store image pixels as
4182 %  defined by the region rectangle and returns a pointer to the region.  This
4183 %  region is subsequently transferred from the pixel cache with
4184 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
4185 %  pixels are transferred, otherwise a NULL is returned.
4186 %
4187 %  The format of the QueueAuthenticPixelsCache() method is:
4188 %
4189 %      Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4190 %        const ssize_t y,const size_t columns,const size_t rows,
4191 %        ExceptionInfo *exception)
4192 %
4193 %  A description of each parameter follows:
4194 %
4195 %    o image: the image.
4196 %
4197 %    o x,y,columns,rows:  These values define the perimeter of a region of
4198 %      pixels.
4199 %
4200 %    o exception: return any errors or warnings in this structure.
4201 %
4202 */
4203 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4204   const ssize_t y,const size_t columns,const size_t rows,
4205   ExceptionInfo *exception)
4206 {
4207   CacheInfo
4208     *cache_info;
4209
4210   const int
4211     id = GetOpenMPThreadId();
4212
4213   Quantum
4214     *q;
4215
4216   assert(image != (const Image *) NULL);
4217   assert(image->signature == MagickSignature);
4218   assert(image->cache != (Cache) NULL);
4219   cache_info=(CacheInfo *) image->cache;
4220   assert(cache_info->signature == MagickSignature);
4221   assert(id < (int) cache_info->number_threads);
4222   q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4223     cache_info->nexus_info[id],exception);
4224   return(q);
4225 }
4226 \f
4227 /*
4228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4229 %                                                                             %
4230 %                                                                             %
4231 %                                                                             %
4232 %   Q u e u e A u t h e n t i c P i x e l s                                   %
4233 %                                                                             %
4234 %                                                                             %
4235 %                                                                             %
4236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4237 %
4238 %  QueueAuthenticPixels() queues a mutable pixel region.  If the region is
4239 %  successfully initialized a pointer to a Quantum array representing the
4240 %  region is returned, otherwise NULL is returned.  The returned pointer may
4241 %  point to a temporary working buffer for the pixels or it may point to the
4242 %  final location of the pixels in memory.
4243 %
4244 %  Write-only access means that any existing pixel values corresponding to
4245 %  the region are ignored.  This is useful if the initial image is being
4246 %  created from scratch, or if the existing pixel values are to be
4247 %  completely replaced without need to refer to their pre-existing values.
4248 %  The application is free to read and write the pixel buffer returned by
4249 %  QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4250 %  initialize the pixel array values. Initializing pixel array values is the
4251 %  application's responsibility.
4252 %
4253 %  Performance is maximized if the selected region is part of one row, or
4254 %  one or more full rows, since then there is opportunity to access the
4255 %  pixels in-place (without a copy) if the image is in memory, or in a
4256 %  memory-mapped file. The returned pointer must *never* be deallocated
4257 %  by the user.
4258 %
4259 %  Pixels accessed via the returned pointer represent a simple array of type
4260 %  Quantum. If the image type is CMYK or the storage class is PseudoClass,
4261 %  call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4262 %  obtain the meta-content (of type void) corresponding to the region.
4263 %  Once the Quantum (and/or Quantum) array has been updated, the
4264 %  changes must be saved back to the underlying image using
4265 %  SyncAuthenticPixels() or they may be lost.
4266 %
4267 %  The format of the QueueAuthenticPixels() method is:
4268 %
4269 %      Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4270 %        const ssize_t y,const size_t columns,const size_t rows,
4271 %        ExceptionInfo *exception)
4272 %
4273 %  A description of each parameter follows:
4274 %
4275 %    o image: the image.
4276 %
4277 %    o x,y,columns,rows:  These values define the perimeter of a region of
4278 %      pixels.
4279 %
4280 %    o exception: return any errors or warnings in this structure.
4281 %
4282 */
4283 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4284   const ssize_t y,const size_t columns,const size_t rows,
4285   ExceptionInfo *exception)
4286 {
4287   CacheInfo
4288     *cache_info;
4289
4290   const int
4291     id = GetOpenMPThreadId();
4292
4293   Quantum
4294     *q;
4295
4296   assert(image != (Image *) NULL);
4297   assert(image->signature == MagickSignature);
4298   assert(image->cache != (Cache) NULL);
4299   cache_info=(CacheInfo *) image->cache;
4300   assert(cache_info->signature == MagickSignature);
4301   if (cache_info->methods.queue_authentic_pixels_handler !=
4302       (QueueAuthenticPixelsHandler) NULL)
4303     {
4304       q=cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4305         rows,exception);
4306       return(q);
4307     }
4308   assert(id < (int) cache_info->number_threads);
4309   q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4310     cache_info->nexus_info[id],exception);
4311   return(q);
4312 }
4313 \f
4314 /*
4315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4316 %                                                                             %
4317 %                                                                             %
4318 %                                                                             %
4319 +   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                         %
4320 %                                                                             %
4321 %                                                                             %
4322 %                                                                             %
4323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4324 %
4325 %  ReadPixelCacheMetacontent() reads metacontent from the specified region of
4326 %  the pixel cache.
4327 %
4328 %  The format of the ReadPixelCacheMetacontent() method is:
4329 %
4330 %      MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4331 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4332 %
4333 %  A description of each parameter follows:
4334 %
4335 %    o cache_info: the pixel cache.
4336 %
4337 %    o nexus_info: the cache nexus to read the metacontent.
4338 %
4339 %    o exception: return any errors or warnings in this structure.
4340 %
4341 */
4342 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4343   NexusInfo *nexus_info,ExceptionInfo *exception)
4344 {
4345   MagickOffsetType
4346     count,
4347     offset;
4348
4349   MagickSizeType
4350     extent,
4351     length;
4352
4353   register ssize_t
4354     y;
4355
4356   register unsigned char
4357     *restrict q;
4358
4359   size_t
4360     rows;
4361
4362   if (cache_info->metacontent_extent == 0)
4363     return(MagickFalse);
4364   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4365     return(MagickTrue);
4366   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4367     nexus_info->region.x;
4368   length=(MagickSizeType) nexus_info->region.width*
4369     cache_info->metacontent_extent;
4370   rows=nexus_info->region.height;
4371   extent=length*rows;
4372   q=(unsigned char *) nexus_info->metacontent;
4373   switch (cache_info->type)
4374   {
4375     case MemoryCache:
4376     case MapCache:
4377     {
4378       register unsigned char
4379         *restrict p;
4380
4381       /*
4382         Read meta-content from memory.
4383       */
4384       if ((cache_info->columns == nexus_info->region.width) &&
4385           (extent == (MagickSizeType) ((size_t) extent)))
4386         {
4387           length=extent;
4388           rows=1UL;
4389         }
4390       p=(unsigned char *) cache_info->metacontent+offset*
4391         cache_info->metacontent_extent;
4392       for (y=0; y < (ssize_t) rows; y++)
4393       {
4394         (void) memcpy(q,p,(size_t) length);
4395         p+=cache_info->metacontent_extent*cache_info->columns;
4396         q+=cache_info->metacontent_extent*nexus_info->region.width;
4397       }
4398       break;
4399     }
4400     case DiskCache:
4401     {
4402       /*
4403         Read meta content from disk.
4404       */
4405       LockSemaphoreInfo(cache_info->file_semaphore);
4406       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4407         {
4408           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4409             cache_info->cache_filename);
4410           UnlockSemaphoreInfo(cache_info->file_semaphore);
4411           return(MagickFalse);
4412         }
4413       if ((cache_info->columns == nexus_info->region.width) &&
4414           (extent <= MagickMaxBufferExtent))
4415         {
4416           length=extent;
4417           rows=1UL;
4418         }
4419       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4420       for (y=0; y < (ssize_t) rows; y++)
4421       {
4422         count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4423           cache_info->number_channels*sizeof(Quantum)+offset*
4424           cache_info->metacontent_extent,length,(unsigned char *) q);
4425         if ((MagickSizeType) count != length)
4426           break;
4427         offset+=cache_info->columns;
4428         q+=cache_info->metacontent_extent*nexus_info->region.width;
4429       }
4430       if (IsFileDescriptorLimitExceeded() != MagickFalse)
4431         (void) ClosePixelCacheOnDisk(cache_info);
4432       UnlockSemaphoreInfo(cache_info->file_semaphore);
4433       if (y < (ssize_t) rows)
4434         {
4435           ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4436             cache_info->cache_filename);
4437           return(MagickFalse);
4438         }
4439       break;
4440     }
4441     case DistributedCache:
4442     {
4443       abort();
4444       break;
4445     }
4446     default:
4447       break;
4448   }
4449   if ((cache_info->debug != MagickFalse) &&
4450       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4451     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4452       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4453       nexus_info->region.width,(double) nexus_info->region.height,(double)
4454       nexus_info->region.x,(double) nexus_info->region.y);
4455   return(MagickTrue);
4456 }
4457 \f
4458 /*
4459 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4460 %                                                                             %
4461 %                                                                             %
4462 %                                                                             %
4463 +   R e a d P i x e l C a c h e P i x e l s                                   %
4464 %                                                                             %
4465 %                                                                             %
4466 %                                                                             %
4467 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4468 %
4469 %  ReadPixelCachePixels() reads pixels from the specified region of the pixel
4470 %  cache.
4471 %
4472 %  The format of the ReadPixelCachePixels() method is:
4473 %
4474 %      MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4475 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4476 %
4477 %  A description of each parameter follows:
4478 %
4479 %    o cache_info: the pixel cache.
4480 %
4481 %    o nexus_info: the cache nexus to read the pixels.
4482 %
4483 %    o exception: return any errors or warnings in this structure.
4484 %
4485 */
4486 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4487   NexusInfo *nexus_info,ExceptionInfo *exception)
4488 {
4489   MagickOffsetType
4490     count,
4491     offset;
4492
4493   MagickSizeType
4494     extent,
4495     length;
4496
4497   register Quantum
4498     *restrict q;
4499
4500   register ssize_t
4501     y;
4502
4503   size_t
4504     rows;
4505
4506   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4507     return(MagickTrue);
4508   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4509     nexus_info->region.x;
4510   length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4511     sizeof(Quantum);
4512   rows=nexus_info->region.height;
4513   extent=length*rows;
4514   q=nexus_info->pixels;
4515   switch (cache_info->type)
4516   {
4517     case MemoryCache:
4518     case MapCache:
4519     {
4520       register Quantum
4521         *restrict p;
4522
4523       /*
4524         Read pixels from memory.
4525       */
4526       if ((cache_info->columns == nexus_info->region.width) &&
4527           (extent == (MagickSizeType) ((size_t) extent)))
4528         {
4529           length=extent;
4530           rows=1UL;
4531         }
4532       p=cache_info->pixels+offset*cache_info->number_channels;
4533       for (y=0; y < (ssize_t) rows; y++)
4534       {
4535         (void) memcpy(q,p,(size_t) length);
4536         p+=cache_info->number_channels*cache_info->columns;
4537         q+=cache_info->number_channels*nexus_info->region.width;
4538       }
4539       break;
4540     }
4541     case DiskCache:
4542     {
4543       /*
4544         Read pixels from disk.
4545       */
4546       LockSemaphoreInfo(cache_info->file_semaphore);
4547       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4548         {
4549           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4550             cache_info->cache_filename);
4551           UnlockSemaphoreInfo(cache_info->file_semaphore);
4552           return(MagickFalse);
4553         }
4554       if ((cache_info->columns == nexus_info->region.width) &&
4555           (extent <= MagickMaxBufferExtent))
4556         {
4557           length=extent;
4558           rows=1UL;
4559         }
4560       for (y=0; y < (ssize_t) rows; y++)
4561       {
4562         count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4563           cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4564         if ((MagickSizeType) count != length)
4565           break;
4566         offset+=cache_info->columns;
4567         q+=cache_info->number_channels*nexus_info->region.width;
4568       }
4569       if (IsFileDescriptorLimitExceeded() != MagickFalse)
4570         (void) ClosePixelCacheOnDisk(cache_info);
4571       UnlockSemaphoreInfo(cache_info->file_semaphore);
4572       if (y < (ssize_t) rows)
4573         {
4574           ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4575             cache_info->cache_filename);
4576           return(MagickFalse);
4577         }
4578       break;
4579     }
4580     case DistributedCache:
4581     {
4582       abort();
4583       break;
4584     }
4585     default:
4586       break;
4587   }
4588   if ((cache_info->debug != MagickFalse) &&
4589       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4590     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4591       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4592       nexus_info->region.width,(double) nexus_info->region.height,(double)
4593       nexus_info->region.x,(double) nexus_info->region.y);
4594   return(MagickTrue);
4595 }
4596 \f
4597 /*
4598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4599 %                                                                             %
4600 %                                                                             %
4601 %                                                                             %
4602 +   R e f e r e n c e P i x e l C a c h e                                     %
4603 %                                                                             %
4604 %                                                                             %
4605 %                                                                             %
4606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4607 %
4608 %  ReferencePixelCache() increments the reference count associated with the
4609 %  pixel cache returning a pointer to the cache.
4610 %
4611 %  The format of the ReferencePixelCache method is:
4612 %
4613 %      Cache ReferencePixelCache(Cache cache_info)
4614 %
4615 %  A description of each parameter follows:
4616 %
4617 %    o cache_info: the pixel cache.
4618 %
4619 */
4620 MagickPrivate Cache ReferencePixelCache(Cache cache)
4621 {
4622   CacheInfo
4623     *cache_info;
4624
4625   assert(cache != (Cache *) NULL);
4626   cache_info=(CacheInfo *) cache;
4627   assert(cache_info->signature == MagickSignature);
4628   LockSemaphoreInfo(cache_info->semaphore);
4629   cache_info->reference_count++;
4630   UnlockSemaphoreInfo(cache_info->semaphore);
4631   return(cache_info);
4632 }
4633 \f
4634 /*
4635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4636 %                                                                             %
4637 %                                                                             %
4638 %                                                                             %
4639 +   S e t P i x e l C a c h e M e t h o d s                                   %
4640 %                                                                             %
4641 %                                                                             %
4642 %                                                                             %
4643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4644 %
4645 %  SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4646 %
4647 %  The format of the SetPixelCacheMethods() method is:
4648 %
4649 %      SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4650 %
4651 %  A description of each parameter follows:
4652 %
4653 %    o cache: the pixel cache.
4654 %
4655 %    o cache_methods: Specifies a pointer to a CacheMethods structure.
4656 %
4657 */
4658 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4659 {
4660   CacheInfo
4661     *cache_info;
4662
4663   GetOneAuthenticPixelFromHandler
4664     get_one_authentic_pixel_from_handler;
4665
4666   GetOneVirtualPixelFromHandler
4667     get_one_virtual_pixel_from_handler;
4668
4669   /*
4670     Set cache pixel methods.
4671   */
4672   assert(cache != (Cache) NULL);
4673   assert(cache_methods != (CacheMethods *) NULL);
4674   cache_info=(CacheInfo *) cache;
4675   assert(cache_info->signature == MagickSignature);
4676   if (cache_info->debug != MagickFalse)
4677     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4678       cache_info->filename);
4679   if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4680     cache_info->methods.get_virtual_pixel_handler=
4681       cache_methods->get_virtual_pixel_handler;
4682   if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4683     cache_info->methods.destroy_pixel_handler=
4684       cache_methods->destroy_pixel_handler;
4685   if (cache_methods->get_virtual_metacontent_from_handler !=
4686       (GetVirtualMetacontentFromHandler) NULL)
4687     cache_info->methods.get_virtual_metacontent_from_handler=
4688       cache_methods->get_virtual_metacontent_from_handler;
4689   if (cache_methods->get_authentic_pixels_handler !=
4690       (GetAuthenticPixelsHandler) NULL)
4691     cache_info->methods.get_authentic_pixels_handler=
4692       cache_methods->get_authentic_pixels_handler;
4693   if (cache_methods->queue_authentic_pixels_handler !=
4694       (QueueAuthenticPixelsHandler) NULL)
4695     cache_info->methods.queue_authentic_pixels_handler=
4696       cache_methods->queue_authentic_pixels_handler;
4697   if (cache_methods->sync_authentic_pixels_handler !=
4698       (SyncAuthenticPixelsHandler) NULL)
4699     cache_info->methods.sync_authentic_pixels_handler=
4700       cache_methods->sync_authentic_pixels_handler;
4701   if (cache_methods->get_authentic_pixels_from_handler !=
4702       (GetAuthenticPixelsFromHandler) NULL)
4703     cache_info->methods.get_authentic_pixels_from_handler=
4704       cache_methods->get_authentic_pixels_from_handler;
4705   if (cache_methods->get_authentic_metacontent_from_handler !=
4706       (GetAuthenticMetacontentFromHandler) NULL)
4707     cache_info->methods.get_authentic_metacontent_from_handler=
4708       cache_methods->get_authentic_metacontent_from_handler;
4709   get_one_virtual_pixel_from_handler=
4710     cache_info->methods.get_one_virtual_pixel_from_handler;
4711   if (get_one_virtual_pixel_from_handler !=
4712       (GetOneVirtualPixelFromHandler) NULL)
4713     cache_info->methods.get_one_virtual_pixel_from_handler=
4714       cache_methods->get_one_virtual_pixel_from_handler;
4715   get_one_authentic_pixel_from_handler=
4716     cache_methods->get_one_authentic_pixel_from_handler;
4717   if (get_one_authentic_pixel_from_handler !=
4718       (GetOneAuthenticPixelFromHandler) NULL)
4719     cache_info->methods.get_one_authentic_pixel_from_handler=
4720       cache_methods->get_one_authentic_pixel_from_handler;
4721 }
4722 \f
4723 /*
4724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4725 %                                                                             %
4726 %                                                                             %
4727 %                                                                             %
4728 +   S e t P i x e l C a c h e N e x u s P i x e l s                           %
4729 %                                                                             %
4730 %                                                                             %
4731 %                                                                             %
4732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4733 %
4734 %  SetPixelCacheNexusPixels() defines the region of the cache for the
4735 %  specified cache nexus.
4736 %
4737 %  The format of the SetPixelCacheNexusPixels() method is:
4738 %
4739 %      Quantum SetPixelCacheNexusPixels(const Image *image,const MapMode mode,
4740 %        const RectangleInfo *region,NexusInfo *nexus_info,
4741 %        ExceptionInfo *exception)
4742 %
4743 %  A description of each parameter follows:
4744 %
4745 %    o image: the image.
4746 %
4747 %    o mode: ReadMode, WriteMode, or IOMode.
4748 %
4749 %    o region: A pointer to the RectangleInfo structure that defines the
4750 %      region of this particular cache nexus.
4751 %
4752 %    o nexus_info: the cache nexus to set.
4753 %
4754 %    o exception: return any errors or warnings in this structure.
4755 %
4756 */
4757
4758 static inline MagickBooleanType AcquireCacheNexusPixels(
4759   const CacheInfo *restrict cache_info,NexusInfo *nexus_info,
4760   ExceptionInfo *exception)
4761 {
4762   if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4763     return(MagickFalse);
4764   nexus_info->mapped=MagickFalse;
4765   nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
4766     (size_t) nexus_info->length));
4767   if (nexus_info->cache == (Quantum *) NULL)
4768     {
4769       nexus_info->mapped=MagickTrue;
4770       nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4771         nexus_info->length);
4772     }
4773   if (nexus_info->cache == (Quantum *) NULL)
4774     {
4775       (void) ThrowMagickException(exception,GetMagickModule(),
4776         ResourceLimitError,"MemoryAllocationFailed","`%s'",
4777         cache_info->filename);
4778       return(MagickFalse);
4779     }
4780   return(MagickTrue);
4781 }
4782
4783 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
4784   const MapMode mode)
4785 {
4786   if (mode == ReadMode)
4787     {
4788       MagickCachePrefetch((unsigned char *) nexus_info->pixels,0,1);
4789       return;
4790     }
4791   MagickCachePrefetch((unsigned char *) nexus_info->pixels,1,1);
4792 }
4793
4794 static Quantum *SetPixelCacheNexusPixels(const Image *image,const MapMode mode,
4795   const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
4796 {
4797   CacheInfo
4798     *cache_info;
4799
4800   MagickBooleanType
4801     status;
4802
4803   MagickSizeType
4804     length,
4805     number_pixels;
4806
4807   cache_info=(CacheInfo *) image->cache;
4808   assert(cache_info->signature == MagickSignature);
4809   if (cache_info->type == UndefinedCache)
4810     return((Quantum *) NULL);
4811   nexus_info->region=(*region);
4812   if ((cache_info->type != DiskCache) && (cache_info->type != PingCache))
4813     {
4814       ssize_t
4815         x,
4816         y;
4817
4818       x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
4819       y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
4820       if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
4821            (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
4822           ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
4823            ((nexus_info->region.width == cache_info->columns) ||
4824             ((nexus_info->region.width % cache_info->columns) == 0)))))
4825         {
4826           MagickOffsetType
4827             offset;
4828
4829           /*
4830             Pixels are accessed directly from memory.
4831           */
4832           offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4833             nexus_info->region.x;
4834           nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
4835             offset;
4836           nexus_info->metacontent=(void *) NULL;
4837           if (cache_info->metacontent_extent != 0)
4838             nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
4839               offset*cache_info->metacontent_extent;
4840           PrefetchPixelCacheNexusPixels(nexus_info,mode);
4841           return(nexus_info->pixels);
4842         }
4843     }
4844   /*
4845     Pixels are stored in a cache region until they are synced to the cache.
4846   */
4847   number_pixels=(MagickSizeType) nexus_info->region.width*
4848     nexus_info->region.height;
4849   length=number_pixels*cache_info->number_channels*sizeof(Quantum);
4850   if (cache_info->metacontent_extent != 0)
4851     length+=number_pixels*cache_info->metacontent_extent;
4852   if (nexus_info->cache == (Quantum *) NULL)
4853     {
4854       nexus_info->length=length;
4855       status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4856       if (status == MagickFalse)
4857         {
4858           nexus_info->length=0;
4859           return((Quantum *) NULL);
4860         }
4861     }
4862   else
4863     if (nexus_info->length != length)
4864       {
4865         RelinquishCacheNexusPixels(nexus_info);
4866         nexus_info->length=length;
4867         status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4868         if (status == MagickFalse)
4869           {
4870             nexus_info->length=0;
4871             return((Quantum *) NULL);
4872           }
4873       }
4874   nexus_info->pixels=nexus_info->cache;
4875   nexus_info->metacontent=(void *) NULL;
4876   if (cache_info->metacontent_extent != 0)
4877     nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
4878       cache_info->number_channels);
4879   PrefetchPixelCacheNexusPixels(nexus_info,mode);
4880   return(nexus_info->pixels);
4881 }
4882 \f
4883 /*
4884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4885 %                                                                             %
4886 %                                                                             %
4887 %                                                                             %
4888 %   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                       %
4889 %                                                                             %
4890 %                                                                             %
4891 %                                                                             %
4892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4893 %
4894 %  SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
4895 %  pixel cache and returns the previous setting.  A virtual pixel is any pixel
4896 %  access that is outside the boundaries of the image cache.
4897 %
4898 %  The format of the SetPixelCacheVirtualMethod() method is:
4899 %
4900 %      VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4901 %        const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4902 %
4903 %  A description of each parameter follows:
4904 %
4905 %    o image: the image.
4906 %
4907 %    o virtual_pixel_method: choose the type of virtual pixel.
4908 %
4909 %    o exception: return any errors or warnings in this structure.
4910 %
4911 */
4912
4913 static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
4914   ExceptionInfo *exception)
4915 {
4916   CacheInfo
4917     *cache_info;
4918
4919   CacheView
4920     *image_view;
4921
4922   MagickBooleanType
4923     status;
4924
4925   ssize_t
4926     y;
4927
4928   assert(image != (Image *) NULL);
4929   assert(image->signature == MagickSignature);
4930   if (image->debug != MagickFalse)
4931     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4932   assert(image->cache != (Cache) NULL);
4933   cache_info=(CacheInfo *) image->cache;
4934   assert(cache_info->signature == MagickSignature);
4935   image->alpha_trait=BlendPixelTrait;
4936   status=MagickTrue;
4937   image_view=AcquireVirtualCacheView(image,exception);  /* must be virtual */
4938 #if defined(MAGICKCORE_OPENMP_SUPPORT)
4939   #pragma omp parallel for schedule(static,4) shared(status) \
4940     magick_threads(image,image,1,1)
4941 #endif
4942   for (y=0; y < (ssize_t) image->rows; y++)
4943   {
4944     register Quantum
4945       *restrict q;
4946
4947     register ssize_t
4948       x;
4949
4950     if (status == MagickFalse)
4951       continue;
4952     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
4953     if (q == (Quantum *) NULL)
4954       {
4955         status=MagickFalse;
4956         continue;
4957       }
4958     for (x=0; x < (ssize_t) image->columns; x++)
4959     {
4960       SetPixelAlpha(image,alpha,q);
4961       q+=GetPixelChannels(image);
4962     }
4963     status=SyncCacheViewAuthenticPixels(image_view,exception);
4964   }
4965   image_view=DestroyCacheView(image_view);
4966   return(status);
4967 }
4968
4969 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4970   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4971 {
4972   CacheInfo
4973     *cache_info;
4974
4975   VirtualPixelMethod
4976     method;
4977
4978   assert(image != (Image *) NULL);
4979   assert(image->signature == MagickSignature);
4980   if (image->debug != MagickFalse)
4981     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4982   assert(image->cache != (Cache) NULL);
4983   cache_info=(CacheInfo *) image->cache;
4984   assert(cache_info->signature == MagickSignature);
4985   method=cache_info->virtual_pixel_method;
4986   cache_info->virtual_pixel_method=virtual_pixel_method;
4987   if ((image->columns != 0) && (image->rows != 0))
4988     switch (virtual_pixel_method)
4989     {
4990       case BackgroundVirtualPixelMethod:
4991       {
4992         if ((image->background_color.alpha_trait == BlendPixelTrait) &&
4993             (image->alpha_trait != BlendPixelTrait))
4994           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
4995         if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
4996             (IsGrayColorspace(image->colorspace) != MagickFalse))
4997           (void) TransformImageColorspace(image,RGBColorspace,exception);
4998         break;
4999       }
5000       case TransparentVirtualPixelMethod:
5001       {
5002         if (image->alpha_trait != BlendPixelTrait)
5003           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5004         break;
5005       }
5006       default:
5007         break;
5008     }
5009   return(method);
5010 }
5011 \f
5012 /*
5013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5014 %                                                                             %
5015 %                                                                             %
5016 %                                                                             %
5017 +   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                   %
5018 %                                                                             %
5019 %                                                                             %
5020 %                                                                             %
5021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5022 %
5023 %  SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5024 %  in-memory or disk cache.  The method returns MagickTrue if the pixel region
5025 %  is synced, otherwise MagickFalse.
5026 %
5027 %  The format of the SyncAuthenticPixelCacheNexus() method is:
5028 %
5029 %      MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5030 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5031 %
5032 %  A description of each parameter follows:
5033 %
5034 %    o image: the image.
5035 %
5036 %    o nexus_info: the cache nexus to sync.
5037 %
5038 %    o exception: return any errors or warnings in this structure.
5039 %
5040 */
5041 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5042   NexusInfo *nexus_info,ExceptionInfo *exception)
5043 {
5044   CacheInfo
5045     *cache_info;
5046
5047   MagickBooleanType
5048     status;
5049
5050   /*
5051     Transfer pixels to the cache.
5052   */
5053   assert(image != (Image *) NULL);
5054   assert(image->signature == MagickSignature);
5055   if (image->cache == (Cache) NULL)
5056     ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5057   cache_info=(CacheInfo *) image->cache;
5058   assert(cache_info->signature == MagickSignature);
5059   if (cache_info->type == UndefinedCache)
5060     return(MagickFalse);
5061   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5062     return(MagickTrue);
5063   assert(cache_info->signature == MagickSignature);
5064   status=WritePixelCachePixels(cache_info,nexus_info,exception);
5065   if ((cache_info->metacontent_extent != 0) &&
5066       (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5067     return(MagickFalse);
5068   return(status);
5069 }
5070 \f
5071 /*
5072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5073 %                                                                             %
5074 %                                                                             %
5075 %                                                                             %
5076 +   S y n c A u t h e n t i c P i x e l C a c h e                             %
5077 %                                                                             %
5078 %                                                                             %
5079 %                                                                             %
5080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5081 %
5082 %  SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5083 %  or disk cache.  The method returns MagickTrue if the pixel region is synced,
5084 %  otherwise MagickFalse.
5085 %
5086 %  The format of the SyncAuthenticPixelsCache() method is:
5087 %
5088 %      MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5089 %        ExceptionInfo *exception)
5090 %
5091 %  A description of each parameter follows:
5092 %
5093 %    o image: the image.
5094 %
5095 %    o exception: return any errors or warnings in this structure.
5096 %
5097 */
5098 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5099   ExceptionInfo *exception)
5100 {
5101   CacheInfo
5102     *cache_info;
5103
5104   const int
5105     id = GetOpenMPThreadId();
5106
5107   MagickBooleanType
5108     status;
5109
5110   assert(image != (Image *) NULL);
5111   assert(image->signature == MagickSignature);
5112   assert(image->cache != (Cache) NULL);
5113   cache_info=(CacheInfo *) image->cache;
5114   assert(cache_info->signature == MagickSignature);
5115   assert(id < (int) cache_info->number_threads);
5116   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5117     exception);
5118   return(status);
5119 }
5120 \f
5121 /*
5122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5123 %                                                                             %
5124 %                                                                             %
5125 %                                                                             %
5126 %   S y n c A u t h e n t i c P i x e l s                                     %
5127 %                                                                             %
5128 %                                                                             %
5129 %                                                                             %
5130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5131 %
5132 %  SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5133 %  The method returns MagickTrue if the pixel region is flushed, otherwise
5134 %  MagickFalse.
5135 %
5136 %  The format of the SyncAuthenticPixels() method is:
5137 %
5138 %      MagickBooleanType SyncAuthenticPixels(Image *image,
5139 %        ExceptionInfo *exception)
5140 %
5141 %  A description of each parameter follows:
5142 %
5143 %    o image: the image.
5144 %
5145 %    o exception: return any errors or warnings in this structure.
5146 %
5147 */
5148 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5149   ExceptionInfo *exception)
5150 {
5151   CacheInfo
5152     *cache_info;
5153
5154   const int
5155     id = GetOpenMPThreadId();
5156
5157   MagickBooleanType
5158     status;
5159
5160   assert(image != (Image *) NULL);
5161   assert(image->signature == MagickSignature);
5162   assert(image->cache != (Cache) NULL);
5163   cache_info=(CacheInfo *) image->cache;
5164   assert(cache_info->signature == MagickSignature);
5165   if (cache_info->methods.sync_authentic_pixels_handler !=
5166        (SyncAuthenticPixelsHandler) NULL)
5167     {
5168       status=cache_info->methods.sync_authentic_pixels_handler(image,
5169         exception);
5170       return(status);
5171     }
5172   assert(id < (int) cache_info->number_threads);
5173   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5174     exception);
5175   return(status);
5176 }
5177 \f
5178 /*
5179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5180 %                                                                             %
5181 %                                                                             %
5182 %                                                                             %
5183 +   S y n c I m a g e P i x e l C a c h e                                     %
5184 %                                                                             %
5185 %                                                                             %
5186 %                                                                             %
5187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5188 %
5189 %  SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5190 %  The method returns MagickTrue if the pixel region is flushed, otherwise
5191 %  MagickFalse.
5192 %
5193 %  The format of the SyncImagePixelCache() method is:
5194 %
5195 %      MagickBooleanType SyncImagePixelCache(Image *image,
5196 %        ExceptionInfo *exception)
5197 %
5198 %  A description of each parameter follows:
5199 %
5200 %    o image: the image.
5201 %
5202 %    o exception: return any errors or warnings in this structure.
5203 %
5204 */
5205 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5206   ExceptionInfo *exception)
5207 {
5208   CacheInfo
5209     *cache_info;
5210
5211   assert(image != (Image *) NULL);
5212   assert(exception != (ExceptionInfo *) NULL);
5213   cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5214   return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5215 }
5216 \f
5217 /*
5218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5219 %                                                                             %
5220 %                                                                             %
5221 %                                                                             %
5222 +   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                       %
5223 %                                                                             %
5224 %                                                                             %
5225 %                                                                             %
5226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5227 %
5228 %  WritePixelCacheMetacontent() writes the meta-content to the specified region
5229 %  of the pixel cache.
5230 %
5231 %  The format of the WritePixelCacheMetacontent() method is:
5232 %
5233 %      MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5234 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5235 %
5236 %  A description of each parameter follows:
5237 %
5238 %    o cache_info: the pixel cache.
5239 %
5240 %    o nexus_info: the cache nexus to write the meta-content.
5241 %
5242 %    o exception: return any errors or warnings in this structure.
5243 %
5244 */
5245 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5246   NexusInfo *nexus_info,ExceptionInfo *exception)
5247 {
5248   MagickOffsetType
5249     count,
5250     offset;
5251
5252   MagickSizeType
5253     extent,
5254     length;
5255
5256   register const unsigned char
5257     *restrict p;
5258
5259   register ssize_t
5260     y;
5261
5262   size_t
5263     rows;
5264
5265   if (cache_info->metacontent_extent == 0)
5266     return(MagickFalse);
5267   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5268     return(MagickTrue);
5269   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5270     nexus_info->region.x;
5271   length=(MagickSizeType) nexus_info->region.width*
5272     cache_info->metacontent_extent;
5273   rows=nexus_info->region.height;
5274   extent=(MagickSizeType) length*rows;
5275   p=(unsigned char *) nexus_info->metacontent;
5276   switch (cache_info->type)
5277   {
5278     case MemoryCache:
5279     case MapCache:
5280     {
5281       register unsigned char
5282         *restrict q;
5283
5284       /*
5285         Write associated pixels to memory.
5286       */
5287       if ((cache_info->columns == nexus_info->region.width) &&
5288           (extent == (MagickSizeType) ((size_t) extent)))
5289         {
5290           length=extent;
5291           rows=1UL;
5292         }
5293       q=(unsigned char *) cache_info->metacontent+offset*
5294         cache_info->metacontent_extent;
5295       for (y=0; y < (ssize_t) rows; y++)
5296       {
5297         (void) memcpy(q,p,(size_t) length);
5298         p+=nexus_info->region.width*cache_info->metacontent_extent;
5299         q+=cache_info->columns*cache_info->metacontent_extent;
5300       }
5301       break;
5302     }
5303     case DiskCache:
5304     {
5305       /*
5306         Write associated pixels to disk.
5307       */
5308       LockSemaphoreInfo(cache_info->file_semaphore);
5309       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5310         {
5311           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5312             cache_info->cache_filename);
5313           UnlockSemaphoreInfo(cache_info->file_semaphore);
5314           return(MagickFalse);
5315         }
5316       if ((cache_info->columns == nexus_info->region.width) &&
5317           (extent <= MagickMaxBufferExtent))
5318         {
5319           length=extent;
5320           rows=1UL;
5321         }
5322       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5323       for (y=0; y < (ssize_t) rows; y++)
5324       {
5325         count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5326           cache_info->number_channels*sizeof(Quantum)+offset*
5327           cache_info->metacontent_extent,length,(const unsigned char *) p);
5328         if ((MagickSizeType) count != length)
5329           break;
5330         p+=nexus_info->region.width*cache_info->metacontent_extent;
5331         offset+=cache_info->columns;
5332       }
5333       if (IsFileDescriptorLimitExceeded() != MagickFalse)
5334         (void) ClosePixelCacheOnDisk(cache_info);
5335       UnlockSemaphoreInfo(cache_info->file_semaphore);
5336       if (y < (ssize_t) rows)
5337         {
5338           ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5339             cache_info->cache_filename);
5340           return(MagickFalse);
5341         }
5342       break;
5343     }
5344     case DistributedCache:
5345     {
5346       abort();
5347       break;
5348     }
5349     default:
5350       break;
5351   }
5352   if ((cache_info->debug != MagickFalse) &&
5353       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5354     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5355       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5356       nexus_info->region.width,(double) nexus_info->region.height,(double)
5357       nexus_info->region.x,(double) nexus_info->region.y);
5358   return(MagickTrue);
5359 }
5360 \f
5361 /*
5362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5363 %                                                                             %
5364 %                                                                             %
5365 %                                                                             %
5366 +   W r i t e C a c h e P i x e l s                                           %
5367 %                                                                             %
5368 %                                                                             %
5369 %                                                                             %
5370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5371 %
5372 %  WritePixelCachePixels() writes image pixels to the specified region of the
5373 %  pixel cache.
5374 %
5375 %  The format of the WritePixelCachePixels() method is:
5376 %
5377 %      MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5378 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5379 %
5380 %  A description of each parameter follows:
5381 %
5382 %    o cache_info: the pixel cache.
5383 %
5384 %    o nexus_info: the cache nexus to write the pixels.
5385 %
5386 %    o exception: return any errors or warnings in this structure.
5387 %
5388 */
5389 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5390   NexusInfo *nexus_info,ExceptionInfo *exception)
5391 {
5392   MagickOffsetType
5393     count,
5394     offset;
5395
5396   MagickSizeType
5397     extent,
5398     length;
5399
5400   register const Quantum
5401     *restrict p;
5402
5403   register ssize_t
5404     y;
5405
5406   size_t
5407     rows;
5408
5409   if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5410     return(MagickTrue);
5411   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5412     nexus_info->region.x;
5413   length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5414     sizeof(Quantum);
5415   rows=nexus_info->region.height;
5416   extent=length*rows;
5417   p=nexus_info->pixels;
5418   switch (cache_info->type)
5419   {
5420     case MemoryCache:
5421     case MapCache:
5422     {
5423       register Quantum
5424         *restrict q;
5425
5426       /*
5427         Write pixels to memory.
5428       */
5429       if ((cache_info->columns == nexus_info->region.width) &&
5430           (extent == (MagickSizeType) ((size_t) extent)))
5431         {
5432           length=extent;
5433           rows=1UL;
5434         }
5435       q=cache_info->pixels+offset*cache_info->number_channels;
5436       for (y=0; y < (ssize_t) rows; y++)
5437       {
5438         (void) memcpy(q,p,(size_t) length);
5439         p+=nexus_info->region.width*cache_info->number_channels;
5440         q+=cache_info->columns*cache_info->number_channels;
5441       }
5442       break;
5443     }
5444     case DiskCache:
5445     {
5446       /*
5447         Write pixels to disk.
5448       */
5449       LockSemaphoreInfo(cache_info->file_semaphore);
5450       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5451         {
5452           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5453             cache_info->cache_filename);
5454           UnlockSemaphoreInfo(cache_info->file_semaphore);
5455           return(MagickFalse);
5456         }
5457       if ((cache_info->columns == nexus_info->region.width) &&
5458           (extent <= MagickMaxBufferExtent))
5459         {
5460           length=extent;
5461           rows=1UL;
5462         }
5463       for (y=0; y < (ssize_t) rows; y++)
5464       {
5465         count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5466           cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5467           p);
5468         if ((MagickSizeType) count != length)
5469           break;
5470         p+=nexus_info->region.width*cache_info->number_channels;
5471         offset+=cache_info->columns;
5472       }
5473       if (IsFileDescriptorLimitExceeded() != MagickFalse)
5474         (void) ClosePixelCacheOnDisk(cache_info);
5475       UnlockSemaphoreInfo(cache_info->file_semaphore);
5476       if (y < (ssize_t) rows)
5477         {
5478           ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5479             cache_info->cache_filename);
5480           return(MagickFalse);
5481         }
5482       break;
5483     }
5484     case DistributedCache:
5485     {
5486       abort();
5487       break;
5488     }
5489     default:
5490       break;
5491   }
5492   if ((cache_info->debug != MagickFalse) &&
5493       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5494     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5495       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5496       nexus_info->region.width,(double) nexus_info->region.height,(double)
5497       nexus_info->region.x,(double) nexus_info->region.y);
5498   return(MagickTrue);
5499 }