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