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