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