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