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