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