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