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