]> granicus.if.org Git - imagemagick/blob - MagickCore/cache.c
(no commit message)
[imagemagick] / MagickCore / cache.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                      CCCC   AAA    CCCC  H   H  EEEEE                       %
7 %                     C      A   A  C      H   H  E                           %
8 %                     C      AAAAA  C      HHHHH  EEE                         %
9 %                     C      A   A  C      H   H  E                           %
10 %                      CCCC  A   A   CCCC  H   H  EEEEE                       %
11 %                                                                             %
12 %                                                                             %
13 %                       MagickCore Pixel Cache Methods                        %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1999                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-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=MagickSignature;
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=MagickSignature;
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 == MagickSignature);
298   assert(exception != (ExceptionInfo *) NULL);
299   assert(exception->signature == MagickSignature);
300   assert(image->cache != (Cache) NULL);
301   cache_info=(CacheInfo *) image->cache;
302   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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   ssize_t
484     count;
485
486   unsigned char
487     buffer[MagickMaxBufferExtent];
488
489   /*
490     Clone pixel cache on disk with identifcal morphology.
491   */
492   if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
493       (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
494     return(MagickFalse);
495 #if defined(MAGICKCORE_HAVE_SENDFILE)
496   if (cache_info->length == (MagickSizeType) ((ssize_t) cache_info->length))
497     {
498       off_t
499         offset;
500
501       offset=0;
502       count=sendfile(clone_info->file,cache_info->file,&offset,(size_t)
503         cache_info->length);
504       if (count == (ssize_t) cache_info->length)
505         return(MagickTrue);
506     }
507 #endif
508   extent=0;
509   while ((count=read(cache_info->file,buffer,sizeof(buffer))) > 0)
510   { 
511     ssize_t
512       number_bytes;
513     
514     number_bytes=write(clone_info->file,buffer,(size_t) count);
515     if (number_bytes != count)
516       break;
517     extent+=number_bytes;
518   }
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) && (cache_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 == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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=(~MagickSignature);
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=(~MagickSignature);
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 == MagickSignature);
1046   assert(image->cache != (Cache) NULL);
1047   cache_info=(CacheInfo *) image->cache;
1048   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
1097   assert(image->cache != (Cache) NULL);
1098   cache_info=(CacheInfo *) image->cache;
1099   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
1203   assert(image->cache != (Cache) NULL);
1204   cache_info=(CacheInfo *) image->cache;
1205   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
1244   assert(image->cache != (Cache) NULL);
1245   cache_info=(CacheInfo *) image->cache;
1246   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
1313   assert(image->cache != (Cache) NULL);
1314   cache_info=(CacheInfo *) image->cache;
1315   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
1621   assert(image->cache != (Cache) NULL);
1622   cache_info=(CacheInfo *) image->cache;
1623   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
1692   assert(image->cache != (Cache) NULL);
1693   cache_info=(CacheInfo *) image->cache;
1694   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
1749   assert(image->cache != (Cache) NULL);
1750   cache_info=(CacheInfo *) image->cache;
1751   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
1804   assert(image->cache != (Cache) NULL);
1805   cache_info=(CacheInfo *) image->cache;
1806   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
1867   assert(image->cache != (Cache) NULL);
1868   cache_info=(CacheInfo *) image->cache;
1869   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
1926   assert(image->cache != (Cache) NULL);
1927   cache_info=(CacheInfo *) image->cache;
1928   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
2095   assert(image->cache != (Cache) NULL);
2096   assert(length != (MagickSizeType *) NULL);
2097   assert(exception != (ExceptionInfo *) NULL);
2098   assert(exception->signature == MagickSignature);
2099   cache_info=(CacheInfo *) image->cache;
2100   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
2181   if (image->debug != MagickFalse)
2182     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2183   cache_info=(CacheInfo *) image->cache;
2184   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
2222   assert(image->cache != (Cache) NULL);
2223   cache_info=(CacheInfo *) image->cache;
2224   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
2264   assert(image->cache != (Cache) NULL);
2265   cache_info=(CacheInfo *) image->cache;
2266   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
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 == MagickSignature);
2350   assert(image->cache != (Cache) NULL);
2351   cache_info=(CacheInfo *) image->cache;
2352   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
2538   assert(image->cache != (Cache) NULL);
2539   cache_info=(CacheInfo *) image->cache;
2540   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
2929   assert(image->cache != (Cache) NULL);
2930   cache_info=(CacheInfo *) image->cache;
2931   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
2971   assert(image->cache != (Cache) NULL);
2972   cache_info=(CacheInfo *) image->cache;
2973   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
3044   assert(image->cache != (Cache) NULL);
3045   cache_info=(CacheInfo *) image->cache;
3046   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
3090   assert(image->cache != (Cache) NULL);
3091   cache_info=(CacheInfo *) image->cache;
3092   assert(cache_info->signature == MagickSignature);
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 == MagickSignature);
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   register MagickOffsetType
3250     i;
3251
3252   ssize_t
3253     count;
3254
3255 #if !defined(MAGICKCORE_HAVE_PWRITE)
3256   if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3257     return((MagickOffsetType) -1);
3258 #endif
3259   count=0;
3260   for (i=0; i < (MagickOffsetType) length; i+=count)
3261   {
3262 #if !defined(MAGICKCORE_HAVE_PWRITE)
3263     count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
3264       (MagickSizeType) SSIZE_MAX));
3265 #else
3266     count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
3267       (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
3268 #endif
3269     if (count <= 0)
3270       {
3271         count=0;
3272         if (errno != EINTR)
3273           break;
3274       }
3275   }
3276   return(i);
3277 }
3278
3279 static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3280 {
3281   CacheInfo
3282     *restrict cache_info;
3283
3284   MagickOffsetType
3285     count,
3286     extent,
3287     offset;
3288
3289   cache_info=(CacheInfo *) image->cache;
3290   if (image->debug != MagickFalse)
3291     {
3292       char
3293         format[MagickPathExtent],
3294         message[MagickPathExtent];
3295
3296       (void) FormatMagickSize(length,MagickFalse,"B",MagickPathExtent,format);
3297       (void) FormatLocaleString(message,MagickPathExtent,
3298         "extend %s (%s[%d], disk, %s)",cache_info->filename,
3299         cache_info->cache_filename,cache_info->file,format);
3300       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3301     }
3302   if (length != (MagickSizeType) ((MagickOffsetType) length))
3303     return(MagickFalse);
3304   offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3305   if (offset < 0)
3306     return(MagickFalse);
3307   if ((MagickSizeType) offset >= length)
3308     return(MagickTrue);
3309   extent=(MagickOffsetType) length-1;
3310   count=WritePixelCacheRegion(cache_info,extent,1,(const unsigned char *) "");
3311 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3312   if (cache_info->synchronize != MagickFalse)
3313     (void) posix_fallocate(cache_info->file,offset+1,extent-offset);
3314 #endif
3315 #if defined(SIGBUS)
3316   (void) signal(SIGBUS,CacheSignalHandler);
3317 #endif
3318   return(count != (MagickOffsetType) 1 ? MagickFalse : MagickTrue);
3319 }
3320
3321 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3322   ExceptionInfo *exception)
3323 {
3324   CacheInfo
3325     *restrict cache_info,
3326     source_info;
3327
3328   char
3329     format[MagickPathExtent],
3330     message[MagickPathExtent];
3331
3332   const char
3333     *type;
3334
3335   MagickBooleanType
3336     status;
3337
3338   MagickSizeType
3339     length,
3340     number_pixels;
3341
3342   size_t
3343     columns,
3344     packet_size;
3345
3346   assert(image != (const Image *) NULL);
3347   assert(image->signature == MagickSignature);
3348   assert(image->cache != (Cache) NULL);
3349   if (image->debug != MagickFalse)
3350     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3351   if ((image->columns == 0) || (image->rows == 0))
3352     ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3353   cache_info=(CacheInfo *) image->cache;
3354   assert(cache_info->signature == MagickSignature);
3355   if ((AcquireMagickResource(WidthResource,image->columns) == MagickFalse) ||
3356       (AcquireMagickResource(HeightResource,image->rows) == MagickFalse))
3357     ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
3358       image->filename);
3359   source_info=(*cache_info);
3360   source_info.file=(-1);
3361   (void) FormatLocaleString(cache_info->filename,MagickPathExtent,"%s[%.20g]",
3362     image->filename,(double) GetImageIndexInList(image));
3363   cache_info->storage_class=image->storage_class;
3364   cache_info->colorspace=image->colorspace;
3365   cache_info->alpha_trait=image->alpha_trait;
3366   cache_info->read_mask=image->read_mask;
3367   cache_info->write_mask=image->write_mask;
3368   cache_info->rows=image->rows;
3369   cache_info->columns=image->columns;
3370   InitializePixelChannelMap(image);
3371   cache_info->number_channels=GetPixelChannels(image);
3372   (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3373     sizeof(*image->channel_map));
3374   cache_info->metacontent_extent=image->metacontent_extent;
3375   cache_info->mode=mode;
3376   if (image->ping != MagickFalse)
3377     {
3378       cache_info->storage_class=image->storage_class;
3379       cache_info->colorspace=image->colorspace;
3380       cache_info->type=PingCache;
3381       return(MagickTrue);
3382     }
3383   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3384   packet_size=cache_info->number_channels*sizeof(Quantum);
3385   if (image->metacontent_extent != 0)
3386     packet_size+=cache_info->metacontent_extent;
3387   length=number_pixels*packet_size;
3388   columns=(size_t) (length/cache_info->rows/packet_size);
3389   if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3390       ((ssize_t) cache_info->rows < 0))
3391     ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
3392       image->filename);
3393   cache_info->length=length;
3394   status=AcquireMagickResource(AreaResource,cache_info->length);
3395   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3396     cache_info->metacontent_extent);
3397   if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
3398     {
3399       status=AcquireMagickResource(MemoryResource,cache_info->length);
3400       if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
3401           (cache_info->type == MemoryCache))
3402         {
3403           AllocatePixelCachePixels(cache_info);
3404           if (cache_info->pixels == (Quantum *) NULL)
3405             cache_info->pixels=source_info.pixels;
3406           else
3407             {
3408               /*
3409                 Create memory pixel cache.
3410               */
3411               status=MagickTrue;
3412               cache_info->type=MemoryCache;
3413               cache_info->metacontent=(void *) NULL;
3414               if (cache_info->metacontent_extent != 0)
3415                 cache_info->metacontent=(void *) (cache_info->pixels+
3416                   number_pixels*cache_info->number_channels);
3417               if ((source_info.storage_class != UndefinedClass) &&
3418                   (mode != ReadMode))
3419                 {
3420                   status=ClonePixelCacheRepository(cache_info,&source_info,
3421                     exception);
3422                   RelinquishPixelCachePixels(&source_info);
3423                 }
3424               if (image->debug != MagickFalse)
3425                 {
3426                   (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
3427                     MagickPathExtent,format);
3428                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3429                     cache_info->type);
3430                   (void) FormatLocaleString(message,MagickPathExtent,
3431                     "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3432                     cache_info->filename,cache_info->mapped != MagickFalse ?
3433                     "Anonymous" : "Heap",type,(double) cache_info->columns,
3434                     (double) cache_info->rows,(double)
3435                     cache_info->number_channels,format);
3436                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3437                     message);
3438                 }
3439               return(status);
3440             }
3441         }
3442       RelinquishMagickResource(MemoryResource,cache_info->length);
3443     }
3444   /*
3445     Create pixel cache on disk.
3446   */
3447   status=AcquireMagickResource(DiskResource,cache_info->length);
3448   if ((status == MagickFalse) || (cache_info->type == DistributedCache))
3449     {
3450       DistributeCacheInfo
3451         *server_info;
3452
3453       if (cache_info->type == DistributedCache)
3454         RelinquishMagickResource(DiskResource,cache_info->length);
3455       server_info=AcquireDistributeCacheInfo(exception);
3456       if (server_info != (DistributeCacheInfo *) NULL)
3457         {
3458           status=OpenDistributePixelCache(server_info,image);
3459           if (status == MagickFalse)
3460             {
3461               ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3462                 GetDistributeCacheHostname(server_info));
3463               server_info=DestroyDistributeCacheInfo(server_info);
3464             }
3465           else
3466             {
3467               /*
3468                 Create a distributed pixel cache.
3469               */
3470               cache_info->type=DistributedCache;
3471               cache_info->server_info=server_info;
3472               (void) FormatLocaleString(cache_info->cache_filename,
3473                 MagickPathExtent,"%s:%d",GetDistributeCacheHostname(
3474                 (DistributeCacheInfo *) cache_info->server_info),
3475                 GetDistributeCachePort((DistributeCacheInfo *)
3476                 cache_info->server_info));
3477               if ((source_info.storage_class != UndefinedClass) &&
3478                   (mode != ReadMode))
3479                 {
3480                   status=ClonePixelCacheRepository(cache_info,&source_info,
3481                     exception);
3482                   RelinquishPixelCachePixels(&source_info);
3483                 }
3484               if (image->debug != MagickFalse)
3485                 {
3486                   (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
3487                     MagickPathExtent,format);
3488                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3489                     cache_info->type);
3490                   (void) FormatLocaleString(message,MagickPathExtent,
3491                     "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3492                     cache_info->filename,cache_info->cache_filename,
3493                     GetDistributeCacheFile((DistributeCacheInfo *)
3494                     cache_info->server_info),type,(double) cache_info->columns,
3495                     (double) cache_info->rows,(double)
3496                     cache_info->number_channels,format);
3497                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3498                     message);
3499                 }
3500               return(MagickTrue);
3501             }
3502         }
3503       RelinquishMagickResource(DiskResource,cache_info->length);
3504       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3505         "CacheResourcesExhausted","`%s'",image->filename);
3506       return(MagickFalse);
3507     }
3508   if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3509     {
3510       (void) ClosePixelCacheOnDisk(cache_info);
3511       *cache_info->cache_filename='\0';
3512     }
3513   if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3514     {
3515       RelinquishMagickResource(DiskResource,cache_info->length);
3516       ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3517         image->filename);
3518       return(MagickFalse);
3519     }
3520   status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3521     cache_info->length);
3522   if (status == MagickFalse)
3523     {
3524       ThrowFileException(exception,CacheError,"UnableToExtendCache",
3525         image->filename);
3526       return(MagickFalse);
3527     }
3528   length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3529     cache_info->metacontent_extent);
3530   if (length != (MagickSizeType) ((size_t) length))
3531     cache_info->type=DiskCache;
3532   else
3533     {
3534       status=AcquireMagickResource(MapResource,cache_info->length);
3535       if ((status == MagickFalse) && (cache_info->type != MapCache) &&
3536           (cache_info->type != MemoryCache))
3537         cache_info->type=DiskCache;
3538       else
3539         {
3540           cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3541             cache_info->offset,(size_t) cache_info->length);
3542           if (cache_info->pixels == (Quantum *) NULL)
3543             {
3544               cache_info->type=DiskCache;
3545               cache_info->pixels=source_info.pixels;
3546             }
3547           else
3548             {
3549               /*
3550                 Create file-backed memory-mapped pixel cache.
3551               */
3552               status=MagickTrue;
3553               (void) ClosePixelCacheOnDisk(cache_info);
3554               cache_info->type=MapCache;
3555               cache_info->mapped=MagickTrue;
3556               cache_info->metacontent=(void *) NULL;
3557               if (cache_info->metacontent_extent != 0)
3558                 cache_info->metacontent=(void *) (cache_info->pixels+
3559                   number_pixels*cache_info->number_channels);
3560               if ((source_info.storage_class != UndefinedClass) &&
3561                   (mode != ReadMode))
3562                 {
3563                   status=ClonePixelCacheRepository(cache_info,&source_info,
3564                     exception);
3565                   RelinquishPixelCachePixels(&source_info);
3566                 }
3567               if (image->debug != MagickFalse)
3568                 {
3569                   (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
3570                     MagickPathExtent,format);
3571                   type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3572                     cache_info->type);
3573                   (void) FormatLocaleString(message,MagickPathExtent,
3574                     "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3575                     cache_info->filename,cache_info->cache_filename,
3576                     cache_info->file,type,(double) cache_info->columns,(double)
3577                     cache_info->rows,(double) cache_info->number_channels,
3578                     format);
3579                   (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3580                     message);
3581                 }
3582               return(status);
3583             }
3584         }
3585       RelinquishMagickResource(MapResource,cache_info->length);
3586     }
3587   status=MagickTrue;
3588   if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3589     {
3590       status=ClonePixelCacheRepository(cache_info,&source_info,exception);
3591       RelinquishPixelCachePixels(&source_info);
3592     }
3593   if (image->debug != MagickFalse)
3594     {
3595       (void) FormatMagickSize(cache_info->length,MagickFalse,"B",MagickPathExtent,
3596         format);
3597       type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3598         cache_info->type);
3599       (void) FormatLocaleString(message,MagickPathExtent,
3600         "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
3601         cache_info->cache_filename,cache_info->file,type,(double)
3602         cache_info->columns,(double) cache_info->rows,(double)
3603         cache_info->number_channels,format);
3604       (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3605     }
3606   return(status);
3607 }
3608 \f
3609 /*
3610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3611 %                                                                             %
3612 %                                                                             %
3613 %                                                                             %
3614 +   P e r s i s t P i x e l C a c h e                                         %
3615 %                                                                             %
3616 %                                                                             %
3617 %                                                                             %
3618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3619 %
3620 %  PersistPixelCache() attaches to or initializes a persistent pixel cache.  A
3621 %  persistent pixel cache is one that resides on disk and is not destroyed
3622 %  when the program exits.
3623 %
3624 %  The format of the PersistPixelCache() method is:
3625 %
3626 %      MagickBooleanType PersistPixelCache(Image *image,const char *filename,
3627 %        const MagickBooleanType attach,MagickOffsetType *offset,
3628 %        ExceptionInfo *exception)
3629 %
3630 %  A description of each parameter follows:
3631 %
3632 %    o image: the image.
3633 %
3634 %    o filename: the persistent pixel cache filename.
3635 %
3636 %    o attach: A value other than zero initializes the persistent pixel cache.
3637 %
3638 %    o initialize: A value other than zero initializes the persistent pixel
3639 %      cache.
3640 %
3641 %    o offset: the offset in the persistent cache to store pixels.
3642 %
3643 %    o exception: return any errors or warnings in this structure.
3644 %
3645 */
3646 MagickExport MagickBooleanType PersistPixelCache(Image *image,
3647   const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
3648   ExceptionInfo *exception)
3649 {
3650   CacheInfo
3651     *restrict cache_info,
3652     *restrict clone_info;
3653
3654   Image
3655     clone_image;
3656
3657   MagickBooleanType
3658     status;
3659
3660   ssize_t
3661     page_size;
3662
3663   assert(image != (Image *) NULL);
3664   assert(image->signature == MagickSignature);
3665   if (image->debug != MagickFalse)
3666     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3667   assert(image->cache != (void *) NULL);
3668   assert(filename != (const char *) NULL);
3669   assert(offset != (MagickOffsetType *) NULL);
3670   page_size=GetMagickPageSize();
3671   cache_info=(CacheInfo *) image->cache;
3672   assert(cache_info->signature == MagickSignature);
3673   if (attach != MagickFalse)
3674     {
3675       /*
3676         Attach existing persistent pixel cache.
3677       */
3678       if (image->debug != MagickFalse)
3679         (void) LogMagickEvent(CacheEvent,GetMagickModule(),
3680           "attach persistent cache");
3681       (void) CopyMagickString(cache_info->cache_filename,filename,
3682         MagickPathExtent);
3683       cache_info->type=DiskCache;
3684       cache_info->offset=(*offset);
3685       if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
3686         return(MagickFalse);
3687       *offset+=cache_info->length+page_size-(cache_info->length % page_size);
3688       return(MagickTrue);
3689     }
3690   if ((cache_info->mode != ReadMode) &&
3691       ((cache_info->type == DiskCache) || (cache_info->type == MapCache)) &&
3692       (cache_info->reference_count == 1))
3693     {
3694       LockSemaphoreInfo(cache_info->semaphore);
3695       if ((cache_info->mode != ReadMode) &&
3696           ((cache_info->type == DiskCache) || (cache_info->type == MapCache)) &&
3697           (cache_info->reference_count == 1))
3698         {
3699           int
3700             status;
3701
3702           /*
3703             Usurp existing persistent pixel cache.
3704           */
3705           status=rename_utf8(cache_info->cache_filename,filename);
3706           if (status == 0)
3707             {
3708               (void) CopyMagickString(cache_info->cache_filename,filename,
3709                 MagickPathExtent);
3710               *offset+=cache_info->length+page_size-(cache_info->length %
3711                 page_size);
3712               UnlockSemaphoreInfo(cache_info->semaphore);
3713               cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
3714               if (image->debug != MagickFalse)
3715                 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
3716                   "Usurp resident persistent cache");
3717               return(MagickTrue);
3718             }
3719         }
3720       UnlockSemaphoreInfo(cache_info->semaphore);
3721     }
3722   /*
3723     Clone persistent pixel cache.
3724   */
3725   clone_image=(*image);
3726   clone_info=(CacheInfo *) clone_image.cache;
3727   image->cache=ClonePixelCache(cache_info);
3728   cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
3729   (void) CopyMagickString(cache_info->cache_filename,filename,MagickPathExtent);
3730   cache_info->type=DiskCache;
3731   cache_info->offset=(*offset);
3732   cache_info=(CacheInfo *) image->cache;
3733   status=OpenPixelCache(image,IOMode,exception);
3734   if (status != MagickFalse)
3735     status=ClonePixelCacheRepository(cache_info,clone_info,exception);
3736   *offset+=cache_info->length+page_size-(cache_info->length % page_size);
3737   clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
3738   return(status);
3739 }
3740 \f
3741 /*
3742 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3743 %                                                                             %
3744 %                                                                             %
3745 %                                                                             %
3746 +   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                 %
3747 %                                                                             %
3748 %                                                                             %
3749 %                                                                             %
3750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3751 %
3752 %  QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
3753 %  defined by the region rectangle and returns a pointer to the region.  This
3754 %  region is subsequently transferred from the pixel cache with
3755 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
3756 %  pixels are transferred, otherwise a NULL is returned.
3757 %
3758 %  The format of the QueueAuthenticPixelCacheNexus() method is:
3759 %
3760 %      Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
3761 %        const ssize_t y,const size_t columns,const size_t rows,
3762 %        const MagickBooleanType clone,NexusInfo *nexus_info,
3763 %        ExceptionInfo *exception)
3764 %
3765 %  A description of each parameter follows:
3766 %
3767 %    o image: the image.
3768 %
3769 %    o x,y,columns,rows:  These values define the perimeter of a region of
3770 %      pixels.
3771 %
3772 %    o nexus_info: the cache nexus to set.
3773 %
3774 %    o clone: clone the pixel cache.
3775 %
3776 %    o exception: return any errors or warnings in this structure.
3777 %
3778 */
3779 MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
3780   const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3781   const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
3782 {
3783   CacheInfo
3784     *restrict cache_info;
3785
3786   MagickOffsetType
3787     offset;
3788
3789   MagickSizeType
3790     number_pixels;
3791
3792   Quantum
3793     *restrict pixels;
3794
3795   RectangleInfo
3796     region;
3797
3798   /*
3799     Validate pixel cache geometry.
3800   */
3801   assert(image != (const Image *) NULL);
3802   assert(image->signature == MagickSignature);
3803   assert(image->cache != (Cache) NULL);
3804   cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
3805   if (cache_info == (Cache) NULL)
3806     return((Quantum *) NULL);
3807   assert(cache_info->signature == MagickSignature);
3808   if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
3809       (y < 0) || (x >= (ssize_t) cache_info->columns) ||
3810       (y >= (ssize_t) cache_info->rows))
3811     {
3812       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3813         "PixelsAreNotAuthentic","`%s'",image->filename);
3814       return((Quantum *) NULL);
3815     }
3816   offset=(MagickOffsetType) y*cache_info->columns+x;
3817   if (offset < 0)
3818     return((Quantum *) NULL);
3819   number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3820   offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
3821   if ((MagickSizeType) offset >= number_pixels)
3822     return((Quantum *) NULL);
3823   /*
3824     Return pixel cache.
3825   */
3826   region.x=x;
3827   region.y=y;
3828   region.width=columns;
3829   region.height=rows;
3830   pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,&region,nexus_info,
3831     exception);
3832   return(pixels);
3833 }
3834 \f
3835 /*
3836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3837 %                                                                             %
3838 %                                                                             %
3839 %                                                                             %
3840 +   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                         %
3841 %                                                                             %
3842 %                                                                             %
3843 %                                                                             %
3844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3845 %
3846 %  QueueAuthenticPixelsCache() allocates an region to store image pixels as
3847 %  defined by the region rectangle and returns a pointer to the region.  This
3848 %  region is subsequently transferred from the pixel cache with
3849 %  SyncAuthenticPixelsCache().  A pointer to the pixels is returned if the
3850 %  pixels are transferred, otherwise a NULL is returned.
3851 %
3852 %  The format of the QueueAuthenticPixelsCache() method is:
3853 %
3854 %      Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
3855 %        const ssize_t y,const size_t columns,const size_t rows,
3856 %        ExceptionInfo *exception)
3857 %
3858 %  A description of each parameter follows:
3859 %
3860 %    o image: the image.
3861 %
3862 %    o x,y,columns,rows:  These values define the perimeter of a region of
3863 %      pixels.
3864 %
3865 %    o exception: return any errors or warnings in this structure.
3866 %
3867 */
3868 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
3869   const ssize_t y,const size_t columns,const size_t rows,
3870   ExceptionInfo *exception)
3871 {
3872   CacheInfo
3873     *restrict cache_info;
3874
3875   const int
3876     id = GetOpenMPThreadId();
3877
3878   Quantum
3879     *restrict pixels;
3880
3881   assert(image != (const Image *) NULL);
3882   assert(image->signature == MagickSignature);
3883   assert(image->cache != (Cache) NULL);
3884   cache_info=(CacheInfo *) image->cache;
3885   assert(cache_info->signature == MagickSignature);
3886   assert(id < (int) cache_info->number_threads);
3887   pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
3888     cache_info->nexus_info[id],exception);
3889   return(pixels);
3890 }
3891 \f
3892 /*
3893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3894 %                                                                             %
3895 %                                                                             %
3896 %                                                                             %
3897 %   Q u e u e A u t h e n t i c P i x e l s                                   %
3898 %                                                                             %
3899 %                                                                             %
3900 %                                                                             %
3901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3902 %
3903 %  QueueAuthenticPixels() queues a mutable pixel region.  If the region is
3904 %  successfully initialized a pointer to a Quantum array representing the
3905 %  region is returned, otherwise NULL is returned.  The returned pointer may
3906 %  point to a temporary working buffer for the pixels or it may point to the
3907 %  final location of the pixels in memory.
3908 %
3909 %  Write-only access means that any existing pixel values corresponding to
3910 %  the region are ignored.  This is useful if the initial image is being
3911 %  created from scratch, or if the existing pixel values are to be
3912 %  completely replaced without need to refer to their pre-existing values.
3913 %  The application is free to read and write the pixel buffer returned by
3914 %  QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
3915 %  initialize the pixel array values. Initializing pixel array values is the
3916 %  application's responsibility.
3917 %
3918 %  Performance is maximized if the selected region is part of one row, or
3919 %  one or more full rows, since then there is opportunity to access the
3920 %  pixels in-place (without a copy) if the image is in memory, or in a
3921 %  memory-mapped file. The returned pointer must *never* be deallocated
3922 %  by the user.
3923 %
3924 %  Pixels accessed via the returned pointer represent a simple array of type
3925 %  Quantum. If the image type is CMYK or the storage class is PseudoClass,
3926 %  call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3927 %  obtain the meta-content (of type void) corresponding to the region.
3928 %  Once the Quantum (and/or Quantum) array has been updated, the
3929 %  changes must be saved back to the underlying image using
3930 %  SyncAuthenticPixels() or they may be lost.
3931 %
3932 %  The format of the QueueAuthenticPixels() method is:
3933 %
3934 %      Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
3935 %        const ssize_t y,const size_t columns,const size_t rows,
3936 %        ExceptionInfo *exception)
3937 %
3938 %  A description of each parameter follows:
3939 %
3940 %    o image: the image.
3941 %
3942 %    o x,y,columns,rows:  These values define the perimeter of a region of
3943 %      pixels.
3944 %
3945 %    o exception: return any errors or warnings in this structure.
3946 %
3947 */
3948 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
3949   const ssize_t y,const size_t columns,const size_t rows,
3950   ExceptionInfo *exception)
3951 {
3952   CacheInfo
3953     *restrict cache_info;
3954
3955   const int
3956     id = GetOpenMPThreadId();
3957
3958   Quantum
3959     *restrict pixels;
3960
3961   assert(image != (Image *) NULL);
3962   assert(image->signature == MagickSignature);
3963   assert(image->cache != (Cache) NULL);
3964   cache_info=(CacheInfo *) image->cache;
3965   assert(cache_info->signature == MagickSignature);
3966   if (cache_info->methods.queue_authentic_pixels_handler !=
3967       (QueueAuthenticPixelsHandler) NULL)
3968     {
3969       pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
3970         columns,rows,exception);
3971       return(pixels);
3972     }
3973   assert(id < (int) cache_info->number_threads);
3974   pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
3975     cache_info->nexus_info[id],exception);
3976   return(pixels);
3977 }
3978 \f
3979 /*
3980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3981 %                                                                             %
3982 %                                                                             %
3983 %                                                                             %
3984 +   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                         %
3985 %                                                                             %
3986 %                                                                             %
3987 %                                                                             %
3988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3989 %
3990 %  ReadPixelCacheMetacontent() reads metacontent from the specified region of
3991 %  the pixel cache.
3992 %
3993 %  The format of the ReadPixelCacheMetacontent() method is:
3994 %
3995 %      MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
3996 %        NexusInfo *nexus_info,ExceptionInfo *exception)
3997 %
3998 %  A description of each parameter follows:
3999 %
4000 %    o cache_info: the pixel cache.
4001 %
4002 %    o nexus_info: the cache nexus to read the metacontent.
4003 %
4004 %    o exception: return any errors or warnings in this structure.
4005 %
4006 */
4007
4008 static inline MagickOffsetType ReadPixelCacheRegion(
4009   const CacheInfo *restrict cache_info,const MagickOffsetType offset,
4010   const MagickSizeType length,unsigned char *restrict buffer)
4011 {
4012   register MagickOffsetType
4013     i;
4014
4015   ssize_t
4016     count;
4017
4018 #if !defined(MAGICKCORE_HAVE_PREAD)
4019   if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4020     return((MagickOffsetType) -1);
4021 #endif
4022   count=0;
4023   for (i=0; i < (MagickOffsetType) length; i+=count)
4024   {
4025 #if !defined(MAGICKCORE_HAVE_PREAD)
4026     count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
4027       (MagickSizeType) SSIZE_MAX));
4028 #else
4029     count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
4030       (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
4031 #endif
4032     if (count <= 0)
4033       {
4034         count=0;
4035         if (errno != EINTR)
4036           break;
4037       }
4038   }
4039   return(i);
4040 }
4041
4042 static MagickBooleanType ReadPixelCacheMetacontent(
4043   CacheInfo *restrict cache_info,NexusInfo *restrict nexus_info,
4044   ExceptionInfo *exception)
4045 {
4046   MagickOffsetType
4047     count,
4048     offset;
4049
4050   MagickSizeType
4051     extent,
4052     length;
4053
4054   register ssize_t
4055     y;
4056
4057   register unsigned char
4058     *restrict q;
4059
4060   size_t
4061     rows;
4062
4063   if (cache_info->metacontent_extent == 0)
4064     return(MagickFalse);
4065   if (nexus_info->authentic_pixel_cache != MagickFalse)
4066     return(MagickTrue);
4067   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4068     nexus_info->region.x;
4069   length=(MagickSizeType) nexus_info->region.width*
4070     cache_info->metacontent_extent;
4071   extent=length*nexus_info->region.height;
4072   rows=nexus_info->region.height;
4073   y=0;
4074   q=(unsigned char *) nexus_info->metacontent;
4075   switch (cache_info->type)
4076   {
4077     case MemoryCache:
4078     case MapCache:
4079     {
4080       register unsigned char
4081         *restrict p;
4082
4083       /*
4084         Read meta-content from memory.
4085       */
4086       if ((cache_info->columns == nexus_info->region.width) &&
4087           (extent == (MagickSizeType) ((size_t) extent)))
4088         {
4089           length=extent;
4090           rows=1UL;
4091         }
4092       p=(unsigned char *) cache_info->metacontent+offset*
4093         cache_info->metacontent_extent;
4094       for (y=0; y < (ssize_t) rows; y++)
4095       {
4096         (void) memcpy(q,p,(size_t) length);
4097         p+=cache_info->metacontent_extent*cache_info->columns;
4098         q+=cache_info->metacontent_extent*nexus_info->region.width;
4099       }
4100       break;
4101     }
4102     case DiskCache:
4103     {
4104       /*
4105         Read meta content from disk.
4106       */
4107       LockSemaphoreInfo(cache_info->file_semaphore);
4108       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4109         {
4110           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4111             cache_info->cache_filename);
4112           UnlockSemaphoreInfo(cache_info->file_semaphore);
4113           return(MagickFalse);
4114         }
4115       if ((cache_info->columns == nexus_info->region.width) &&
4116           (extent <= MagickMaxBufferExtent))
4117         {
4118           length=extent;
4119           rows=1UL;
4120         }
4121       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4122       for (y=0; y < (ssize_t) rows; y++)
4123       {
4124         count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4125           cache_info->number_channels*sizeof(Quantum)+offset*
4126           cache_info->metacontent_extent,length,(unsigned char *) q);
4127         if (count != (MagickOffsetType) length)
4128           break;
4129         offset+=cache_info->columns;
4130         q+=cache_info->metacontent_extent*nexus_info->region.width;
4131       }
4132       if (IsFileDescriptorLimitExceeded() != MagickFalse)
4133         (void) ClosePixelCacheOnDisk(cache_info);
4134       UnlockSemaphoreInfo(cache_info->file_semaphore);
4135       break;
4136     }
4137     case DistributedCache:
4138     {
4139       RectangleInfo
4140         region;
4141
4142       /*
4143         Read metacontent from distributed cache.
4144       */
4145       LockSemaphoreInfo(cache_info->file_semaphore);
4146       region=nexus_info->region;
4147       if ((cache_info->columns != nexus_info->region.width) ||
4148           (extent > MagickMaxBufferExtent))
4149         region.height=1UL;
4150       else
4151         {
4152           length=extent;
4153           rows=1UL;
4154         }
4155       for (y=0; y < (ssize_t) rows; y++)
4156       {
4157         count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
4158           cache_info->server_info,&region,length,(unsigned char *) q);
4159         if (count != (MagickOffsetType) length)
4160           break;
4161         q+=cache_info->metacontent_extent*nexus_info->region.width;
4162         region.y++;
4163       }
4164       UnlockSemaphoreInfo(cache_info->file_semaphore);
4165       break;
4166     }
4167     default:
4168       break;
4169   }
4170   if (y < (ssize_t) rows)
4171     {
4172       ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4173         cache_info->cache_filename);
4174       return(MagickFalse);
4175     }
4176   if ((cache_info->debug != MagickFalse) &&
4177       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4178     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4179       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4180       nexus_info->region.width,(double) nexus_info->region.height,(double)
4181       nexus_info->region.x,(double) nexus_info->region.y);
4182   return(MagickTrue);
4183 }
4184 \f
4185 /*
4186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4187 %                                                                             %
4188 %                                                                             %
4189 %                                                                             %
4190 +   R e a d P i x e l C a c h e P i x e l s                                   %
4191 %                                                                             %
4192 %                                                                             %
4193 %                                                                             %
4194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4195 %
4196 %  ReadPixelCachePixels() reads pixels from the specified region of the pixel
4197 %  cache.
4198 %
4199 %  The format of the ReadPixelCachePixels() method is:
4200 %
4201 %      MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4202 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4203 %
4204 %  A description of each parameter follows:
4205 %
4206 %    o cache_info: the pixel cache.
4207 %
4208 %    o nexus_info: the cache nexus to read the pixels.
4209 %
4210 %    o exception: return any errors or warnings in this structure.
4211 %
4212 */
4213 static MagickBooleanType ReadPixelCachePixels(CacheInfo *restrict cache_info,
4214   NexusInfo *restrict nexus_info,ExceptionInfo *exception)
4215 {
4216   MagickOffsetType
4217     count,
4218     offset;
4219
4220   MagickSizeType
4221     extent,
4222     length;
4223
4224   register Quantum
4225     *restrict q;
4226
4227   register ssize_t
4228     y;
4229
4230   size_t
4231     rows;
4232
4233   if (nexus_info->authentic_pixel_cache != MagickFalse)
4234     return(MagickTrue);
4235   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4236     nexus_info->region.x;
4237   length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
4238     sizeof(Quantum);
4239   extent=length*nexus_info->region.height;
4240   rows=nexus_info->region.height;
4241   y=0;
4242   q=nexus_info->pixels;
4243   switch (cache_info->type)
4244   {
4245     case MemoryCache:
4246     case MapCache:
4247     {
4248       register Quantum
4249         *restrict p;
4250
4251       /*
4252         Read pixels from memory.
4253       */
4254       if ((cache_info->columns == nexus_info->region.width) &&
4255           (extent == (MagickSizeType) ((size_t) extent)))
4256         {
4257           length=extent;
4258           rows=1UL;
4259         }
4260       p=cache_info->pixels+offset*cache_info->number_channels;
4261       for (y=0; y < (ssize_t) rows; y++)
4262       {
4263         (void) memcpy(q,p,(size_t) length);
4264         p+=cache_info->number_channels*cache_info->columns;
4265         q+=cache_info->number_channels*nexus_info->region.width;
4266       }
4267       break;
4268     }
4269     case DiskCache:
4270     {
4271       /*
4272         Read pixels from disk.
4273       */
4274       LockSemaphoreInfo(cache_info->file_semaphore);
4275       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4276         {
4277           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4278             cache_info->cache_filename);
4279           UnlockSemaphoreInfo(cache_info->file_semaphore);
4280           return(MagickFalse);
4281         }
4282       if ((cache_info->columns == nexus_info->region.width) &&
4283           (extent <= MagickMaxBufferExtent))
4284         {
4285           length=extent;
4286           rows=1UL;
4287         }
4288       for (y=0; y < (ssize_t) rows; y++)
4289       {
4290         count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4291           cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4292         if (count != (MagickOffsetType) length)
4293           break;
4294         offset+=cache_info->columns;
4295         q+=cache_info->number_channels*nexus_info->region.width;
4296       }
4297       if (IsFileDescriptorLimitExceeded() != MagickFalse)
4298         (void) ClosePixelCacheOnDisk(cache_info);
4299       UnlockSemaphoreInfo(cache_info->file_semaphore);
4300       break;
4301     }
4302     case DistributedCache:
4303     {
4304       RectangleInfo
4305         region;
4306
4307       /*
4308         Read pixels from distributed cache.
4309       */
4310       LockSemaphoreInfo(cache_info->file_semaphore);
4311       region=nexus_info->region;
4312       if ((cache_info->columns != nexus_info->region.width) ||
4313           (extent > MagickMaxBufferExtent))
4314         region.height=1UL;
4315       else
4316         {
4317           length=extent;
4318           rows=1UL;
4319         }
4320       for (y=0; y < (ssize_t) rows; y++)
4321       {
4322         count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4323           cache_info->server_info,&region,length,(unsigned char *) q);
4324         if (count != (MagickOffsetType) length)
4325           break;
4326         q+=cache_info->number_channels*nexus_info->region.width;
4327         region.y++;
4328       }
4329       UnlockSemaphoreInfo(cache_info->file_semaphore);
4330       break;
4331     }
4332     default:
4333       break;
4334   }
4335   if (y < (ssize_t) rows)
4336     {
4337       ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4338         cache_info->cache_filename);
4339       return(MagickFalse);
4340     }
4341   if ((cache_info->debug != MagickFalse) &&
4342       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4343     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4344       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4345       nexus_info->region.width,(double) nexus_info->region.height,(double)
4346       nexus_info->region.x,(double) nexus_info->region.y);
4347   return(MagickTrue);
4348 }
4349 \f
4350 /*
4351 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4352 %                                                                             %
4353 %                                                                             %
4354 %                                                                             %
4355 +   R e f e r e n c e P i x e l C a c h e                                     %
4356 %                                                                             %
4357 %                                                                             %
4358 %                                                                             %
4359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4360 %
4361 %  ReferencePixelCache() increments the reference count associated with the
4362 %  pixel cache returning a pointer to the cache.
4363 %
4364 %  The format of the ReferencePixelCache method is:
4365 %
4366 %      Cache ReferencePixelCache(Cache cache_info)
4367 %
4368 %  A description of each parameter follows:
4369 %
4370 %    o cache_info: the pixel cache.
4371 %
4372 */
4373 MagickPrivate Cache ReferencePixelCache(Cache cache)
4374 {
4375   CacheInfo
4376     *restrict cache_info;
4377
4378   assert(cache != (Cache *) NULL);
4379   cache_info=(CacheInfo *) cache;
4380   assert(cache_info->signature == MagickSignature);
4381   LockSemaphoreInfo(cache_info->semaphore);
4382   cache_info->reference_count++;
4383   UnlockSemaphoreInfo(cache_info->semaphore);
4384   return(cache_info);
4385 }
4386 \f
4387 /*
4388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4389 %                                                                             %
4390 %                                                                             %
4391 %                                                                             %
4392 +   S e t P i x e l C a c h e M e t h o d s                                   %
4393 %                                                                             %
4394 %                                                                             %
4395 %                                                                             %
4396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4397 %
4398 %  SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4399 %
4400 %  The format of the SetPixelCacheMethods() method is:
4401 %
4402 %      SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4403 %
4404 %  A description of each parameter follows:
4405 %
4406 %    o cache: the pixel cache.
4407 %
4408 %    o cache_methods: Specifies a pointer to a CacheMethods structure.
4409 %
4410 */
4411 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4412 {
4413   CacheInfo
4414     *restrict cache_info;
4415
4416   GetOneAuthenticPixelFromHandler
4417     get_one_authentic_pixel_from_handler;
4418
4419   GetOneVirtualPixelFromHandler
4420     get_one_virtual_pixel_from_handler;
4421
4422   /*
4423     Set cache pixel methods.
4424   */
4425   assert(cache != (Cache) NULL);
4426   assert(cache_methods != (CacheMethods *) NULL);
4427   cache_info=(CacheInfo *) cache;
4428   assert(cache_info->signature == MagickSignature);
4429   if (cache_info->debug != MagickFalse)
4430     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4431       cache_info->filename);
4432   if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4433     cache_info->methods.get_virtual_pixel_handler=
4434       cache_methods->get_virtual_pixel_handler;
4435   if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4436     cache_info->methods.destroy_pixel_handler=
4437       cache_methods->destroy_pixel_handler;
4438   if (cache_methods->get_virtual_metacontent_from_handler !=
4439       (GetVirtualMetacontentFromHandler) NULL)
4440     cache_info->methods.get_virtual_metacontent_from_handler=
4441       cache_methods->get_virtual_metacontent_from_handler;
4442   if (cache_methods->get_authentic_pixels_handler !=
4443       (GetAuthenticPixelsHandler) NULL)
4444     cache_info->methods.get_authentic_pixels_handler=
4445       cache_methods->get_authentic_pixels_handler;
4446   if (cache_methods->queue_authentic_pixels_handler !=
4447       (QueueAuthenticPixelsHandler) NULL)
4448     cache_info->methods.queue_authentic_pixels_handler=
4449       cache_methods->queue_authentic_pixels_handler;
4450   if (cache_methods->sync_authentic_pixels_handler !=
4451       (SyncAuthenticPixelsHandler) NULL)
4452     cache_info->methods.sync_authentic_pixels_handler=
4453       cache_methods->sync_authentic_pixels_handler;
4454   if (cache_methods->get_authentic_pixels_from_handler !=
4455       (GetAuthenticPixelsFromHandler) NULL)
4456     cache_info->methods.get_authentic_pixels_from_handler=
4457       cache_methods->get_authentic_pixels_from_handler;
4458   if (cache_methods->get_authentic_metacontent_from_handler !=
4459       (GetAuthenticMetacontentFromHandler) NULL)
4460     cache_info->methods.get_authentic_metacontent_from_handler=
4461       cache_methods->get_authentic_metacontent_from_handler;
4462   get_one_virtual_pixel_from_handler=
4463     cache_info->methods.get_one_virtual_pixel_from_handler;
4464   if (get_one_virtual_pixel_from_handler !=
4465       (GetOneVirtualPixelFromHandler) NULL)
4466     cache_info->methods.get_one_virtual_pixel_from_handler=
4467       cache_methods->get_one_virtual_pixel_from_handler;
4468   get_one_authentic_pixel_from_handler=
4469     cache_methods->get_one_authentic_pixel_from_handler;
4470   if (get_one_authentic_pixel_from_handler !=
4471       (GetOneAuthenticPixelFromHandler) NULL)
4472     cache_info->methods.get_one_authentic_pixel_from_handler=
4473       cache_methods->get_one_authentic_pixel_from_handler;
4474 }
4475 \f
4476 /*
4477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4478 %                                                                             %
4479 %                                                                             %
4480 %                                                                             %
4481 +   S e t P i x e l C a c h e N e x u s P i x e l s                           %
4482 %                                                                             %
4483 %                                                                             %
4484 %                                                                             %
4485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4486 %
4487 %  SetPixelCacheNexusPixels() defines the region of the cache for the
4488 %  specified cache nexus.
4489 %
4490 %  The format of the SetPixelCacheNexusPixels() method is:
4491 %
4492 %      Quantum SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4493 %        const MapMode mode,const RectangleInfo *region,NexusInfo *nexus_info,
4494 %        ExceptionInfo *exception)
4495 %
4496 %  A description of each parameter follows:
4497 %
4498 %    o cache_info: the pixel cache.
4499 %
4500 %    o mode: ReadMode, WriteMode, or IOMode.
4501 %
4502 %    o region: A pointer to the RectangleInfo structure that defines the
4503 %      region of this particular cache nexus.
4504 %
4505 %    o nexus_info: the cache nexus to set.
4506 %
4507 %    o exception: return any errors or warnings in this structure.
4508 %
4509 */
4510
4511 static inline MagickBooleanType AcquireCacheNexusPixels(
4512   const CacheInfo *restrict cache_info,NexusInfo *nexus_info,
4513   ExceptionInfo *exception)
4514 {
4515   if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4516     return(MagickFalse);
4517   nexus_info->mapped=MagickFalse;
4518   nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
4519     (size_t) nexus_info->length));
4520   if (nexus_info->cache == (Quantum *) NULL)
4521     {
4522       nexus_info->mapped=MagickTrue;
4523       nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4524         nexus_info->length);
4525     }
4526   if (nexus_info->cache == (Quantum *) NULL)
4527     {
4528       (void) ThrowMagickException(exception,GetMagickModule(),
4529         ResourceLimitError,"MemoryAllocationFailed","`%s'",
4530         cache_info->filename);
4531       return(MagickFalse);
4532     }
4533   return(MagickTrue);
4534 }
4535
4536 static inline MagickBooleanType IsPixelCacheAuthentic(
4537   const CacheInfo *restrict cache_info,const NexusInfo *restrict nexus_info)
4538 {
4539   MagickBooleanType
4540     status;
4541
4542   MagickOffsetType
4543     offset;
4544
4545   /*
4546     Does nexus pixels point directly to in-core cache pixels or is it buffered?
4547   */
4548   if (cache_info->type == PingCache)
4549     return(MagickTrue);
4550   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4551     nexus_info->region.x;
4552   status=nexus_info->pixels == (cache_info->pixels+offset*
4553     cache_info->number_channels) ? MagickTrue : MagickFalse;
4554   return(status);
4555 }
4556
4557 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
4558   const MapMode mode)
4559 {
4560   if (mode == ReadMode)
4561     {
4562       MagickCachePrefetch((unsigned char *) nexus_info->pixels,0,1);
4563       return;
4564     }
4565   MagickCachePrefetch((unsigned char *) nexus_info->pixels,1,1);
4566 }
4567
4568 static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4569   const MapMode mode,const RectangleInfo *region,NexusInfo *nexus_info,
4570   ExceptionInfo *exception)
4571 {
4572   MagickBooleanType
4573     status;
4574
4575   MagickSizeType
4576     length,
4577     number_pixels;
4578
4579   assert(cache_info != (const CacheInfo *) NULL);
4580   assert(cache_info->signature == MagickSignature);
4581   if (cache_info->type == UndefinedCache)
4582     return((Quantum *) NULL);
4583   nexus_info->region=(*region);
4584   if ((cache_info->type == MemoryCache) || (cache_info->type == MapCache))
4585     {
4586       ssize_t
4587         x,
4588         y;
4589
4590       x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
4591       y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
4592       if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
4593            (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
4594           ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
4595            ((nexus_info->region.width == cache_info->columns) ||
4596             ((nexus_info->region.width % cache_info->columns) == 0)))))
4597         {
4598           MagickOffsetType
4599             offset;
4600
4601           /*
4602             Pixels are accessed directly from memory.
4603           */
4604           offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4605             nexus_info->region.x;
4606           nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
4607             offset;
4608           nexus_info->metacontent=(void *) NULL;
4609           if (cache_info->metacontent_extent != 0)
4610             nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
4611               offset*cache_info->metacontent_extent;
4612           PrefetchPixelCacheNexusPixels(nexus_info,mode);
4613           nexus_info->authentic_pixel_cache=IsPixelCacheAuthentic(cache_info,
4614             nexus_info);
4615           return(nexus_info->pixels);
4616         }
4617     }
4618   /*
4619     Pixels are stored in a staging region until they are synced to the cache.
4620   */
4621   number_pixels=(MagickSizeType) nexus_info->region.width*
4622     nexus_info->region.height;
4623   length=number_pixels*cache_info->number_channels*sizeof(Quantum);
4624   if (cache_info->metacontent_extent != 0)
4625     length+=number_pixels*cache_info->metacontent_extent;
4626   if (nexus_info->cache == (Quantum *) NULL)
4627     {
4628       nexus_info->length=length;
4629       status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4630       if (status == MagickFalse)
4631         {
4632           nexus_info->length=0;
4633           return((Quantum *) NULL);
4634         }
4635     }
4636   else
4637     if (nexus_info->length < length)
4638       {
4639         RelinquishCacheNexusPixels(nexus_info);
4640         nexus_info->length=length;
4641         status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4642         if (status == MagickFalse)
4643           {
4644             nexus_info->length=0;
4645             return((Quantum *) NULL);
4646           }
4647       }
4648   nexus_info->pixels=nexus_info->cache;
4649   nexus_info->metacontent=(void *) NULL;
4650   if (cache_info->metacontent_extent != 0)
4651     nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
4652       cache_info->number_channels);
4653   PrefetchPixelCacheNexusPixels(nexus_info,mode);
4654   nexus_info->authentic_pixel_cache=IsPixelCacheAuthentic(cache_info,
4655     nexus_info);
4656   return(nexus_info->pixels);
4657 }
4658 \f
4659 /*
4660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4661 %                                                                             %
4662 %                                                                             %
4663 %                                                                             %
4664 %   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                       %
4665 %                                                                             %
4666 %                                                                             %
4667 %                                                                             %
4668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4669 %
4670 %  SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
4671 %  pixel cache and returns the previous setting.  A virtual pixel is any pixel
4672 %  access that is outside the boundaries of the image cache.
4673 %
4674 %  The format of the SetPixelCacheVirtualMethod() method is:
4675 %
4676 %      VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4677 %        const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4678 %
4679 %  A description of each parameter follows:
4680 %
4681 %    o image: the image.
4682 %
4683 %    o virtual_pixel_method: choose the type of virtual pixel.
4684 %
4685 %    o exception: return any errors or warnings in this structure.
4686 %
4687 */
4688
4689 static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
4690   ExceptionInfo *exception)
4691 {
4692   CacheInfo
4693     *restrict cache_info;
4694
4695   CacheView
4696     *restrict image_view;
4697
4698   MagickBooleanType
4699     status;
4700
4701   ssize_t
4702     y;
4703
4704   assert(image != (Image *) NULL);
4705   assert(image->signature == MagickSignature);
4706   if (image->debug != MagickFalse)
4707     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4708   assert(image->cache != (Cache) NULL);
4709   cache_info=(CacheInfo *) image->cache;
4710   assert(cache_info->signature == MagickSignature);
4711   image->alpha_trait=BlendPixelTrait;
4712   status=MagickTrue;
4713   image_view=AcquireVirtualCacheView(image,exception);  /* must be virtual */
4714 #if defined(MAGICKCORE_OPENMP_SUPPORT)
4715   #pragma omp parallel for schedule(static,4) shared(status) \
4716     magick_threads(image,image,1,1)
4717 #endif
4718   for (y=0; y < (ssize_t) image->rows; y++)
4719   {
4720     register Quantum
4721       *restrict q;
4722
4723     register ssize_t
4724       x;
4725
4726     if (status == MagickFalse)
4727       continue;
4728     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
4729     if (q == (Quantum *) NULL)
4730       {
4731         status=MagickFalse;
4732         continue;
4733       }
4734     for (x=0; x < (ssize_t) image->columns; x++)
4735     {
4736       SetPixelAlpha(image,alpha,q);
4737       q+=GetPixelChannels(image);
4738     }
4739     status=SyncCacheViewAuthenticPixels(image_view,exception);
4740   }
4741   image_view=DestroyCacheView(image_view);
4742   return(status);
4743 }
4744
4745 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4746   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4747 {
4748   CacheInfo
4749     *restrict cache_info;
4750
4751   VirtualPixelMethod
4752     method;
4753
4754   assert(image != (Image *) NULL);
4755   assert(image->signature == MagickSignature);
4756   if (image->debug != MagickFalse)
4757     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4758   assert(image->cache != (Cache) NULL);
4759   cache_info=(CacheInfo *) image->cache;
4760   assert(cache_info->signature == MagickSignature);
4761   method=cache_info->virtual_pixel_method;
4762   cache_info->virtual_pixel_method=virtual_pixel_method;
4763   if ((image->columns != 0) && (image->rows != 0))
4764     switch (virtual_pixel_method)
4765     {
4766       case BackgroundVirtualPixelMethod:
4767       {
4768         if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
4769             (image->alpha_trait == UndefinedPixelTrait))
4770           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
4771         if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
4772             (IsGrayColorspace(image->colorspace) != MagickFalse))
4773           (void) SetImageColorspace(image,sRGBColorspace,exception);
4774         break;
4775       }
4776       case TransparentVirtualPixelMethod:
4777       {
4778         if (image->alpha_trait == UndefinedPixelTrait)
4779           (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
4780         break;
4781       }
4782       default:
4783         break;
4784     }
4785   return(method);
4786 }
4787 \f
4788 /*
4789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4790 %                                                                             %
4791 %                                                                             %
4792 %                                                                             %
4793 +   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                   %
4794 %                                                                             %
4795 %                                                                             %
4796 %                                                                             %
4797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4798 %
4799 %  SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
4800 %  in-memory or disk cache.  The method returns MagickTrue if the pixel region
4801 %  is synced, otherwise MagickFalse.
4802 %
4803 %  The format of the SyncAuthenticPixelCacheNexus() method is:
4804 %
4805 %      MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
4806 %        NexusInfo *nexus_info,ExceptionInfo *exception)
4807 %
4808 %  A description of each parameter follows:
4809 %
4810 %    o image: the image.
4811 %
4812 %    o nexus_info: the cache nexus to sync.
4813 %
4814 %    o exception: return any errors or warnings in this structure.
4815 %
4816 */
4817 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
4818   NexusInfo *restrict nexus_info,ExceptionInfo *exception)
4819 {
4820   CacheInfo
4821     *restrict cache_info;
4822
4823   MagickBooleanType
4824     status;
4825
4826   /*
4827     Transfer pixels to the cache.
4828   */
4829   assert(image != (Image *) NULL);
4830   assert(image->signature == MagickSignature);
4831   if (image->cache == (Cache) NULL)
4832     ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
4833   cache_info=(CacheInfo *) image->cache;
4834   assert(cache_info->signature == MagickSignature);
4835   if (cache_info->type == UndefinedCache)
4836     return(MagickFalse);
4837   if (nexus_info->authentic_pixel_cache != MagickFalse)
4838     {
4839       image->taint=MagickTrue;
4840       return(MagickTrue);
4841     }
4842   assert(cache_info->signature == MagickSignature);
4843   status=WritePixelCachePixels(cache_info,nexus_info,exception);
4844   if ((cache_info->metacontent_extent != 0) &&
4845       (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
4846     return(MagickFalse);
4847   if (status != MagickFalse)
4848     image->taint=MagickTrue;
4849   return(status);
4850 }
4851 \f
4852 /*
4853 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4854 %                                                                             %
4855 %                                                                             %
4856 %                                                                             %
4857 +   S y n c A u t h e n t i c P i x e l C a c h e                             %
4858 %                                                                             %
4859 %                                                                             %
4860 %                                                                             %
4861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4862 %
4863 %  SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
4864 %  or disk cache.  The method returns MagickTrue if the pixel region is synced,
4865 %  otherwise MagickFalse.
4866 %
4867 %  The format of the SyncAuthenticPixelsCache() method is:
4868 %
4869 %      MagickBooleanType SyncAuthenticPixelsCache(Image *image,
4870 %        ExceptionInfo *exception)
4871 %
4872 %  A description of each parameter follows:
4873 %
4874 %    o image: the image.
4875 %
4876 %    o exception: return any errors or warnings in this structure.
4877 %
4878 */
4879 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
4880   ExceptionInfo *exception)
4881 {
4882   CacheInfo
4883     *restrict cache_info;
4884
4885   const int
4886     id = GetOpenMPThreadId();
4887
4888   MagickBooleanType
4889     status;
4890
4891   assert(image != (Image *) NULL);
4892   assert(image->signature == MagickSignature);
4893   assert(image->cache != (Cache) NULL);
4894   cache_info=(CacheInfo *) image->cache;
4895   assert(cache_info->signature == MagickSignature);
4896   assert(id < (int) cache_info->number_threads);
4897   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
4898     exception);
4899   return(status);
4900 }
4901 \f
4902 /*
4903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4904 %                                                                             %
4905 %                                                                             %
4906 %                                                                             %
4907 %   S y n c A u t h e n t i c P i x e l s                                     %
4908 %                                                                             %
4909 %                                                                             %
4910 %                                                                             %
4911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4912 %
4913 %  SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
4914 %  The method returns MagickTrue if the pixel region is flushed, otherwise
4915 %  MagickFalse.
4916 %
4917 %  The format of the SyncAuthenticPixels() method is:
4918 %
4919 %      MagickBooleanType SyncAuthenticPixels(Image *image,
4920 %        ExceptionInfo *exception)
4921 %
4922 %  A description of each parameter follows:
4923 %
4924 %    o image: the image.
4925 %
4926 %    o exception: return any errors or warnings in this structure.
4927 %
4928 */
4929 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
4930   ExceptionInfo *exception)
4931 {
4932   CacheInfo
4933     *restrict cache_info;
4934
4935   const int
4936     id = GetOpenMPThreadId();
4937
4938   MagickBooleanType
4939     status;
4940
4941   assert(image != (Image *) NULL);
4942   assert(image->signature == MagickSignature);
4943   assert(image->cache != (Cache) NULL);
4944   cache_info=(CacheInfo *) image->cache;
4945   assert(cache_info->signature == MagickSignature);
4946   if (cache_info->methods.sync_authentic_pixels_handler !=
4947        (SyncAuthenticPixelsHandler) NULL)
4948     {
4949       status=cache_info->methods.sync_authentic_pixels_handler(image,
4950         exception);
4951       return(status);
4952     }
4953   assert(id < (int) cache_info->number_threads);
4954   status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
4955     exception);
4956   return(status);
4957 }
4958 \f
4959 /*
4960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4961 %                                                                             %
4962 %                                                                             %
4963 %                                                                             %
4964 +   S y n c I m a g e P i x e l C a c h e                                     %
4965 %                                                                             %
4966 %                                                                             %
4967 %                                                                             %
4968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4969 %
4970 %  SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
4971 %  The method returns MagickTrue if the pixel region is flushed, otherwise
4972 %  MagickFalse.
4973 %
4974 %  The format of the SyncImagePixelCache() method is:
4975 %
4976 %      MagickBooleanType SyncImagePixelCache(Image *image,
4977 %        ExceptionInfo *exception)
4978 %
4979 %  A description of each parameter follows:
4980 %
4981 %    o image: the image.
4982 %
4983 %    o exception: return any errors or warnings in this structure.
4984 %
4985 */
4986 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
4987   ExceptionInfo *exception)
4988 {
4989   CacheInfo
4990     *restrict cache_info;
4991
4992   assert(image != (Image *) NULL);
4993   assert(exception != (ExceptionInfo *) NULL);
4994   cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
4995   return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
4996 }
4997 \f
4998 /*
4999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5000 %                                                                             %
5001 %                                                                             %
5002 %                                                                             %
5003 +   W r i t e P i x e l C a c h e M e t a c o n t e n t                       %
5004 %                                                                             %
5005 %                                                                             %
5006 %                                                                             %
5007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5008 %
5009 %  WritePixelCacheMetacontent() writes the meta-content to the specified region
5010 %  of the pixel cache.
5011 %
5012 %  The format of the WritePixelCacheMetacontent() method is:
5013 %
5014 %      MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5015 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5016 %
5017 %  A description of each parameter follows:
5018 %
5019 %    o cache_info: the pixel cache.
5020 %
5021 %    o nexus_info: the cache nexus to write the meta-content.
5022 %
5023 %    o exception: return any errors or warnings in this structure.
5024 %
5025 */
5026 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5027   NexusInfo *restrict nexus_info,ExceptionInfo *exception)
5028 {
5029   MagickOffsetType
5030     count,
5031     offset;
5032
5033   MagickSizeType
5034     extent,
5035     length;
5036
5037   register const unsigned char
5038     *restrict p;
5039
5040   register ssize_t
5041     y;
5042
5043   size_t
5044     rows;
5045
5046   if (cache_info->metacontent_extent == 0)
5047     return(MagickFalse);
5048   if (nexus_info->authentic_pixel_cache != MagickFalse)
5049     return(MagickTrue);
5050   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5051     nexus_info->region.x;
5052   length=(MagickSizeType) nexus_info->region.width*
5053     cache_info->metacontent_extent;
5054   extent=(MagickSizeType) length*nexus_info->region.height;
5055   rows=nexus_info->region.height;
5056   y=0;
5057   p=(unsigned char *) nexus_info->metacontent;
5058   switch (cache_info->type)
5059   {
5060     case MemoryCache:
5061     case MapCache:
5062     {
5063       register unsigned char
5064         *restrict q;
5065
5066       /*
5067         Write associated pixels to memory.
5068       */
5069       if ((cache_info->columns == nexus_info->region.width) &&
5070           (extent == (MagickSizeType) ((size_t) extent)))
5071         {
5072           length=extent;
5073           rows=1UL;
5074         }
5075       q=(unsigned char *) cache_info->metacontent+offset*
5076         cache_info->metacontent_extent;
5077       for (y=0; y < (ssize_t) rows; y++)
5078       {
5079         (void) memcpy(q,p,(size_t) length);
5080         p+=nexus_info->region.width*cache_info->metacontent_extent;
5081         q+=cache_info->columns*cache_info->metacontent_extent;
5082       }
5083       break;
5084     }
5085     case DiskCache:
5086     {
5087       /*
5088         Write associated pixels to disk.
5089       */
5090       LockSemaphoreInfo(cache_info->file_semaphore);
5091       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5092         {
5093           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5094             cache_info->cache_filename);
5095           UnlockSemaphoreInfo(cache_info->file_semaphore);
5096           return(MagickFalse);
5097         }
5098       if ((cache_info->columns == nexus_info->region.width) &&
5099           (extent <= MagickMaxBufferExtent))
5100         {
5101           length=extent;
5102           rows=1UL;
5103         }
5104       extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5105       for (y=0; y < (ssize_t) rows; y++)
5106       {
5107         count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5108           cache_info->number_channels*sizeof(Quantum)+offset*
5109           cache_info->metacontent_extent,length,(const unsigned char *) p);
5110         if (count != (MagickOffsetType) length)
5111           break;
5112         p+=cache_info->metacontent_extent*nexus_info->region.width;
5113         offset+=cache_info->columns;
5114       }
5115       if (IsFileDescriptorLimitExceeded() != MagickFalse)
5116         (void) ClosePixelCacheOnDisk(cache_info);
5117       UnlockSemaphoreInfo(cache_info->file_semaphore);
5118       break;
5119     }
5120     case DistributedCache:
5121     {
5122       RectangleInfo
5123         region;
5124
5125       /*
5126         Write metacontent to distributed cache.
5127       */
5128       LockSemaphoreInfo(cache_info->file_semaphore);
5129       region=nexus_info->region;
5130       if ((cache_info->columns != nexus_info->region.width) ||
5131           (extent > MagickMaxBufferExtent))
5132         region.height=1UL;
5133       else
5134         {
5135           length=extent;
5136           rows=1UL;
5137         }
5138       for (y=0; y < (ssize_t) rows; y++)
5139       {
5140         count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
5141           cache_info->server_info,&region,length,(const unsigned char *) p);
5142         if (count != (MagickOffsetType) length)
5143           break;
5144         p+=cache_info->metacontent_extent*nexus_info->region.width;
5145         region.y++;
5146       }
5147       UnlockSemaphoreInfo(cache_info->file_semaphore);
5148       break;
5149     }
5150     default:
5151       break;
5152   }
5153   if (y < (ssize_t) rows)
5154     {
5155       ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5156         cache_info->cache_filename);
5157       return(MagickFalse);
5158     }
5159   if ((cache_info->debug != MagickFalse) &&
5160       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5161     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5162       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5163       nexus_info->region.width,(double) nexus_info->region.height,(double)
5164       nexus_info->region.x,(double) nexus_info->region.y);
5165   return(MagickTrue);
5166 }
5167 \f
5168 /*
5169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5170 %                                                                             %
5171 %                                                                             %
5172 %                                                                             %
5173 +   W r i t e C a c h e P i x e l s                                           %
5174 %                                                                             %
5175 %                                                                             %
5176 %                                                                             %
5177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5178 %
5179 %  WritePixelCachePixels() writes image pixels to the specified region of the
5180 %  pixel cache.
5181 %
5182 %  The format of the WritePixelCachePixels() method is:
5183 %
5184 %      MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5185 %        NexusInfo *nexus_info,ExceptionInfo *exception)
5186 %
5187 %  A description of each parameter follows:
5188 %
5189 %    o cache_info: the pixel cache.
5190 %
5191 %    o nexus_info: the cache nexus to write the pixels.
5192 %
5193 %    o exception: return any errors or warnings in this structure.
5194 %
5195 */
5196 static MagickBooleanType WritePixelCachePixels(CacheInfo *restrict cache_info,
5197   NexusInfo *restrict nexus_info,ExceptionInfo *exception)
5198 {
5199   MagickOffsetType
5200     count,
5201     offset;
5202
5203   MagickSizeType
5204     extent,
5205     length;
5206
5207   register const Quantum
5208     *restrict p;
5209
5210   register ssize_t
5211     y;
5212
5213   size_t
5214     rows;
5215
5216   if (nexus_info->authentic_pixel_cache != MagickFalse)
5217     return(MagickTrue);
5218   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5219     nexus_info->region.x;
5220   length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5221     sizeof(Quantum);
5222   extent=length*nexus_info->region.height;
5223   rows=nexus_info->region.height;
5224   y=0;
5225   p=nexus_info->pixels;
5226   switch (cache_info->type)
5227   {
5228     case MemoryCache:
5229     case MapCache:
5230     {
5231       register Quantum
5232         *restrict q;
5233
5234       /*
5235         Write pixels to memory.
5236       */
5237       if ((cache_info->columns == nexus_info->region.width) &&
5238           (extent == (MagickSizeType) ((size_t) extent)))
5239         {
5240           length=extent;
5241           rows=1UL;
5242         }
5243       q=cache_info->pixels+offset*cache_info->number_channels;
5244       for (y=0; y < (ssize_t) rows; y++)
5245       {
5246         (void) memcpy(q,p,(size_t) length);
5247         p+=cache_info->number_channels*nexus_info->region.width;
5248         q+=cache_info->columns*cache_info->number_channels;
5249       }
5250       break;
5251     }
5252     case DiskCache:
5253     {
5254       /*
5255         Write pixels to disk.
5256       */
5257       LockSemaphoreInfo(cache_info->file_semaphore);
5258       if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5259         {
5260           ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5261             cache_info->cache_filename);
5262           UnlockSemaphoreInfo(cache_info->file_semaphore);
5263           return(MagickFalse);
5264         }
5265       if ((cache_info->columns == nexus_info->region.width) &&
5266           (extent <= MagickMaxBufferExtent))
5267         {
5268           length=extent;
5269           rows=1UL;
5270         }
5271       for (y=0; y < (ssize_t) rows; y++)
5272       {
5273         count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5274           cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5275           p);
5276         if (count != (MagickOffsetType) length)
5277           break;
5278         p+=cache_info->number_channels*nexus_info->region.width;
5279         offset+=cache_info->columns;
5280       }
5281       if (IsFileDescriptorLimitExceeded() != MagickFalse)
5282         (void) ClosePixelCacheOnDisk(cache_info);
5283       UnlockSemaphoreInfo(cache_info->file_semaphore);
5284       break;
5285     }
5286     case DistributedCache:
5287     {
5288       RectangleInfo
5289         region;
5290
5291       /*
5292         Write pixels to distributed cache.
5293       */
5294       LockSemaphoreInfo(cache_info->file_semaphore);
5295       region=nexus_info->region;
5296       if ((cache_info->columns != nexus_info->region.width) ||
5297           (extent > MagickMaxBufferExtent))
5298         region.height=1UL;
5299       else
5300         {
5301           length=extent;
5302           rows=1UL;
5303         }
5304       for (y=0; y < (ssize_t) rows; y++)
5305       {
5306         count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
5307           cache_info->server_info,&region,length,(const unsigned char *) p);
5308         if (count != (MagickOffsetType) length)
5309           break;
5310         p+=cache_info->number_channels*nexus_info->region.width;
5311         region.y++;
5312       }
5313       UnlockSemaphoreInfo(cache_info->file_semaphore);
5314       break;
5315     }
5316     default:
5317       break;
5318   }
5319   if (y < (ssize_t) rows)
5320     {
5321       ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5322         cache_info->cache_filename);
5323       return(MagickFalse);
5324     }
5325   if ((cache_info->debug != MagickFalse) &&
5326       (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5327     (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5328       "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5329       nexus_info->region.width,(double) nexus_info->region.height,(double)
5330       nexus_info->region.x,(double) nexus_info->region.y);
5331   return(MagickTrue);
5332 }