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