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