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