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