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