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