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