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