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