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