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