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