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