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