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