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