root/ImageMagick/trunk/magick/cache.c

Revision 469, 192.9 KB (checked in by cristy, 4 weeks ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                      CCCC   AAA    CCCC  H   H  EEEEE                       %
7%                     C      A   A  C      H   H  E                           %
8%                     C      AAAAA  C      HHHHH  EEE                         %
9%                     C      A   A  C      H   H  E                           %
10%                      CCCC  A   A   CCCC  H   H  EEEEE                       %
11%                                                                             %
12%                                                                             %
13%                       MagickCore Pixel Cache Methods                        %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 1999                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2009 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
40/*
41  Include declarations.
42*/
43#include "magick/studio.h"
44#include "magick/blob.h"
45#include "magick/blob-private.h"
46#include "magick/cache.h"
47#include "magick/cache-private.h"
48#include "magick/color-private.h"
49#include "magick/composite-private.h"
50#include "magick/exception.h"
51#include "magick/exception-private.h"
52#include "magick/list.h"
53#include "magick/log.h"
54#include "magick/magick.h"
55#include "magick/memory_.h"
56#include "magick/pixel-private.h"
57#include "magick/quantum.h"
58#include "magick/random_.h"
59#include "magick/resource_.h"
60#include "magick/semaphore.h"
61#include "magick/splay-tree.h"
62#include "magick/string_.h"
63#include "magick/thread-private.h"
64#include "magick/utility.h"
65#if defined(MAGICKCORE_ZLIB_DELEGATE)
66#include "zlib.h"
67#endif
68
69/*
70  Typedef declarations.
71*/
72typedef struct _MagickModulo
73{
74  long
75    quotient,
76    remainder;
77} MagickModulo;
78
79struct _NexusInfo
80{
81  MagickBooleanType
82    mapped;
83
84  RectangleInfo
85    region;
86
87  MagickSizeType
88    length;
89
90  PixelPacket
91    *cache,
92    *pixels;
93
94  IndexPacket
95    *indexes;
96
97  unsigned long
98    signature;
99};
100
101/*
102  Forward declarations.
103*/
104#if defined(__cplusplus) || defined(c_plusplus)
105extern "C" {
106#endif
107
108static const IndexPacket
109  *GetVirtualIndexesFromCache(const Image *);
110
111static const PixelPacket
112  *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const long,
113    const long,const unsigned long,const unsigned long,ExceptionInfo *),
114  *GetVirtualPixelsCache(const Image *);
115
116static MagickBooleanType
117  GetOneAuthenticPixelFromCache(Image *,const long,const long,PixelPacket *,
118    ExceptionInfo *),
119  GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
120    const long,const long,PixelPacket *,ExceptionInfo *),
121  OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
122  ReadPixelCacheIndexes(CacheInfo *,NexusInfo *,ExceptionInfo *),
123  ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
124  SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
125  WritePixelCacheIndexes(CacheInfo *,NexusInfo *,ExceptionInfo *),
126  WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
127
128static PixelPacket
129  *GetAuthenticPixelsCache(Image *,const long,const long,const unsigned long,
130    const unsigned long,ExceptionInfo *),
131  *QueueAuthenticPixelsCache(Image *,const long,const long,const unsigned long,
132    const unsigned long,ExceptionInfo *),
133  *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *,
134     ExceptionInfo *);
135
136#if defined(__cplusplus) || defined(c_plusplus)
137}
138#endif
139
140/*
141  Global declarations.
142*/
143static volatile MagickBooleanType
144  instantiate_cache = MagickFalse;
145
146static SemaphoreInfo
147  *cache_semaphore = (SemaphoreInfo *) NULL;
148
149static SplayTreeInfo
150  *cache_resources = (SplayTreeInfo *) NULL;
151
152static time_t
153  cache_timer = 0;
154
155/*
156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157%                                                                             %
158%                                                                             %
159%                                                                             %
160+   A c q u i r e P i x e l C a c h e                                         %
161%                                                                             %
162%                                                                             %
163%                                                                             %
164%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165%
166%  AcquirePixelCache() acquires a pixel cache.
167%
168%  The format of the AcquirePixelCache() method is:
169%
170%      Cache AcquirePixelCache(const unsigned long number_threads)
171%
172%  A description of each parameter follows:
173%
174%    o number_threads: the number of nexus threads.
175%
176*/
177MagickExport Cache AcquirePixelCache(const unsigned long number_threads)
178{
179  CacheInfo
180    *cache_info;
181
182  cache_info=(CacheInfo *) AcquireAlignedMemory(1,sizeof(*cache_info));
183  if (cache_info == (CacheInfo *) NULL)
184    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
185  (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
186  cache_info->type=UndefinedCache;
187  cache_info->mode=IOMode;
188  cache_info->colorspace=RGBColorspace;
189  cache_info->file=(-1);
190  cache_info->id=GetMagickThreadId();
191  cache_info->number_threads=number_threads;
192  if (number_threads == 0)
193    cache_info->number_threads=GetOpenMPMaximumThreads();
194  cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
195  if (cache_info->nexus_info == (NexusInfo **) NULL)
196    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
197  GetPixelCacheMethods(&cache_info->methods);
198  cache_info->reference_count=1;
199  cache_info->semaphore=AllocateSemaphoreInfo();
200  cache_info->disk_semaphore=AllocateSemaphoreInfo();
201  cache_info->debug=IsEventLogging();
202  cache_info->signature=MagickSignature;
203  if ((cache_resources == (SplayTreeInfo *) NULL) &&
204      (instantiate_cache == MagickFalse))
205    {
206      if (cache_semaphore == (SemaphoreInfo *) NULL)
207        AcquireSemaphoreInfo(&cache_semaphore);
208      (void) LockSemaphoreInfo(cache_semaphore);
209      if ((cache_resources == (SplayTreeInfo *) NULL) &&
210          (instantiate_cache == MagickFalse))
211        {
212          cache_resources=NewSplayTree((int (*)(const void *,const void *))
213            NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
214          instantiate_cache=MagickTrue;
215        }
216      (void) UnlockSemaphoreInfo(cache_semaphore);
217    }
218  (void) AddValueToSplayTree(cache_resources,cache_info,cache_info);
219  return((Cache ) cache_info);
220}
221
222/*
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224%                                                                             %
225%                                                                             %
226%                                                                             %
227%   A c q u i r e P i x e l C a c h e N e x u s                               %
228%                                                                             %
229%                                                                             %
230%                                                                             %
231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232%
233%  AcquirePixelCacheNexus() allocates the NexusInfo structure.
234%
235%  The format of the AcquirePixelCacheNexus method is:
236%
237%      NexusInfo **AcquirePixelCacheNexus(const unsigned long number_threads)
238%
239%  A description of each parameter follows:
240%
241%    o number_threads: the number of nexus threads.
242%
243*/
244MagickExport NexusInfo **AcquirePixelCacheNexus(
245  const unsigned long number_threads)
246{
247  register long
248    i;
249
250  NexusInfo
251    **nexus_info;
252
253  nexus_info=(NexusInfo **) AcquireAlignedMemory(number_threads,
254    sizeof(*nexus_info));
255  if (nexus_info == (NexusInfo **) NULL)
256    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
257  for (i=0; i < (long) number_threads; i++)
258  {
259    nexus_info[i]=(NexusInfo *) AcquireAlignedMemory(1,sizeof(**nexus_info));
260    if (nexus_info[i] == (NexusInfo *) NULL)
261      ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
262    (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
263    nexus_info[i]->signature=MagickSignature;
264  }
265  return(nexus_info);
266}
267
268/*
269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270%                                                                             %
271%                                                                             %
272%                                                                             %
273+   C a c h e C o m p o n e n t G e n e s i s                                 %
274%                                                                             %
275%                                                                             %
276%                                                                             %
277%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278%
279%  CacheComponentGenesis() instantiates the cache component.
280%
281%  The format of the CacheComponentGenesis method is:
282%
283%      MagickBooleanType CacheComponentGenesis(void)
284%
285*/
286MagickExport MagickBooleanType CacheComponentGenesis(void)
287{
288  AcquireSemaphoreInfo(&cache_semaphore);
289  return(MagickTrue);
290}
291
292/*
293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294%                                                                             %
295%                                                                             %
296%                                                                             %
297+   C a c h e C o m p o n e n t T e r m i n u s                               %
298%                                                                             %
299%                                                                             %
300%                                                                             %
301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302%
303%  CacheComponentTerminus() destroys the cache component.
304%
305%  The format of the CacheComponentTerminus() method is:
306%
307%      CacheComponentTerminus(void)
308%
309*/
310MagickExport void CacheComponentTerminus(void)
311{
312  if (cache_semaphore == (SemaphoreInfo *) NULL)
313    AcquireSemaphoreInfo(&cache_semaphore);
314  (void) LockSemaphoreInfo(cache_semaphore);
315  if (cache_resources != (SplayTreeInfo *) NULL)
316    cache_resources=DestroySplayTree(cache_resources);
317  instantiate_cache=MagickFalse;
318  (void) UnlockSemaphoreInfo(cache_semaphore);
319  DestroySemaphoreInfo(&cache_semaphore);
320}
321
322/*
323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324%                                                                             %
325%                                                                             %
326%                                                                             %
327+   C l i p P i x e l C a c h e N e x u s                                     %
328%                                                                             %
329%                                                                             %
330%                                                                             %
331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332%
333%  ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
334%  mask.  The method returns MagickTrue if the pixel region is clipped,
335%  otherwise MagickFalse.
336%
337%  The format of the ClipPixelCacheNexus() method is:
338%
339%      MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
340%        ExceptionInfo *exception)
341%
342%  A description of each parameter follows:
343%
344%    o image: the image.
345%
346%    o nexus_info: the cache nexus to clip.
347%
348%    o exception: return any errors or warnings in this structure.
349%
350*/
351static MagickBooleanType ClipPixelCacheNexus(Image *image,
352  NexusInfo *nexus_info,ExceptionInfo *exception)
353{
354  CacheInfo
355    *cache_info;
356
357  MagickSizeType
358    number_pixels;
359
360  NexusInfo
361    **clip_nexus,
362    **image_nexus;
363
364  register const PixelPacket
365    *__restrict r;
366
367  register IndexPacket
368    *__restrict nexus_indexes,
369    *__restrict indexes;
370
371  register long
372    i;
373
374  register PixelPacket
375    *__restrict p,
376    *__restrict q;
377
378  /*
379    Apply clip mask.
380  */
381  if (image->debug != MagickFalse)
382    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
383  if (image->clip_mask == (Image *) NULL)
384    return(MagickFalse);
385  cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
386  if (cache_info == (Cache) NULL)
387    return(MagickFalse);
388  image_nexus=AcquirePixelCacheNexus(1);
389  clip_nexus=AcquirePixelCacheNexus(1);
390  if ((image_nexus == (NexusInfo **) NULL) ||
391      (clip_nexus == (NexusInfo **) NULL))
392    ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
393  p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
394    nexus_info->region.width,nexus_info->region.height,image_nexus[0],
395    exception);
396  indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
397  q=nexus_info->pixels;
398  nexus_indexes=nexus_info->indexes;
399  r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
400    nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
401    nexus_info->region.height,clip_nexus[0],exception);
402  number_pixels=(MagickSizeType) nexus_info->region.width*
403    nexus_info->region.height;
404  for (i=0; i < (long) number_pixels; i++)
405  {
406    if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
407      break;
408    if (PixelIntensityToQuantum(r) > ((Quantum) QuantumRange/2))
409      {
410        q->red=p->red;
411        q->green=p->green;
412        q->blue=p->blue;
413        q->opacity=p->opacity;
414        if (cache_info->active_index_channel != MagickFalse)
415          nexus_indexes[i]=indexes[i];
416      }
417    p++;
418    q++;
419    r++;
420  }
421  clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
422  image_nexus=DestroyPixelCacheNexus(image_nexus,1);
423  if (i < (long) number_pixels)
424    return(MagickFalse);
425  return(MagickTrue);
426}
427
428/*
429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430%                                                                             %
431%                                                                             %
432%                                                                             %
433+   C l o n e P i x e l C a c h e                                             %
434%                                                                             %
435%                                                                             %
436%                                                                             %
437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438%
439%  ClonePixelCache() clones a pixel cache.
440%
441%  The format of the ClonePixelCache() method is:
442%
443%      Cache ClonePixelCache(const Cache cache)
444%
445%  A description of each parameter follows:
446%
447%    o cache: the pixel cache.
448%
449*/
450MagickExport Cache ClonePixelCache(const Cache cache)
451{
452  CacheInfo
453    *clone_info;
454
455  const CacheInfo
456    *cache_info;
457
458  assert(cache != (const Cache) NULL);
459  cache_info=(const CacheInfo *) cache;
460  assert(cache_info->signature == MagickSignature);
461  if (cache_info->debug != MagickFalse)
462    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
463      cache_info->filename);
464  clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
465  if (clone_info == (Cache) NULL)
466    return((Cache) NULL);
467  clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
468  return((Cache ) clone_info);
469}
470
471/*
472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
473%                                                                             %
474%                                                                             %
475%                                                                             %
476+   C l o n e P i x e l C a c h e N e x u s                                   %
477%                                                                             %
478%                                                                             %
479%                                                                             %
480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481%
482%  ClonePixelCacheNexus() clones the source cache nexus to the destination
483%  nexus.
484%
485%  The format of the ClonePixelCacheNexus() method is:
486%
487%      MagickBooleanType ClonePixelCacheNexus(CacheInfo *destination,
488%        CacheInfo *source,ExceptionInfo *exception)
489%
490%  A description of each parameter follows:
491%
492%    o destination: the destination cache nexus.
493%
494%    o source: the source cache nexus.
495%
496%    o exception: return any errors or warnings in this structure.
497%
498*/
499
500static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
501  NexusInfo *nexus_info,ExceptionInfo *exception)
502{
503  if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
504    return(MagickFalse);
505  nexus_info->mapped=MagickFalse;
506  nexus_info->cache=(PixelPacket *) AcquireMagickMemory((size_t)
507    nexus_info->length);
508  if (nexus_info->cache == (PixelPacket *) NULL)
509    {
510      nexus_info->mapped=MagickTrue;
511      nexus_info->cache=(PixelPacket *) MapBlob(-1,IOMode,0,(size_t)
512        nexus_info->length);
513    }
514  if (nexus_info->cache == (PixelPacket *) NULL)
515    {
516      (void) ThrowMagickException(exception,GetMagickModule(),
517        ResourceLimitError,"MemoryAllocationFailed","`%s'",
518        cache_info->filename);
519      return(MagickFalse);
520    }
521  return(MagickTrue);
522}
523
524static MagickBooleanType ClonePixelCacheNexus(CacheInfo *destination,
525  CacheInfo *source,ExceptionInfo *exception)
526{
527  MagickBooleanType
528    status;
529
530  MagickSizeType
531    number_pixels;
532
533  register long
534    i;
535
536  register const NexusInfo
537    *p;
538
539  register NexusInfo
540    *q;
541
542  status=MagickTrue;
543  for (i=0; i < (long) source->number_threads; i++)
544  {
545    p=source->nexus_info[i];
546    q=destination->nexus_info[i];
547    q->mapped=p->mapped;
548    q->region=p->region;
549    q->length=p->length;
550    q->cache=p->cache;
551    q->pixels=p->pixels;
552    q->indexes=p->indexes;
553    if (p->cache != (PixelPacket *) NULL)
554      {
555        status=AcquireCacheNexusPixels(source,q,exception);
556        if (status != MagickFalse)
557          {
558            (void) CopyMagickMemory(q->cache,p->cache,(size_t) p->length);
559            q->pixels=q->cache;
560            q->indexes=(IndexPacket *) NULL;
561            number_pixels=(MagickSizeType) q->region.width*q->region.height;
562            if (p->indexes != (IndexPacket *) NULL)
563              q->indexes=(IndexPacket *) (q->pixels+number_pixels);
564          }
565      }
566  }
567  return(status);
568}
569
570/*
571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572%                                                                             %
573%                                                                             %
574%                                                                             %
575+   C l o n e P i x e l C a c h e P i x e l s                                 %
576%                                                                             %
577%                                                                             %
578%                                                                             %
579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
580%  ClonePixelCachePixels() clones the source pixel cache to the destination
581%  cache.
582%
583%  The format of the ClonePixelCachePixels() method is:
584%
585%      MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
586%        CacheInfo *source_info,ExceptionInfo *exception)
587%
588%  A description of each parameter follows:
589%
590%    o cache_info: the pixel cache.
591%
592%    o source_info: the source pixel cache.
593%
594%    o exception: return any errors or warnings in this structure.
595%
596*/
597
598static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
599{
600  int
601    status;
602
603  (void) LockSemaphoreInfo(cache_info->disk_semaphore);
604  status=close(cache_info->file);
605  cache_info->file=(-1);
606  RelinquishMagickResource(FileResource,1);
607  (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
608  return(status == -1 ? MagickFalse : MagickTrue);
609}
610
611static void LimitPixelCacheDescriptors(void)
612{
613  register CacheInfo
614    *p,
615    *q;
616
617  /*
618    Limit # of open file descriptors.
619  */
620  if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
621    return;
622  (void) LockSemaphoreInfo(cache_semaphore);
623  if (cache_resources == (SplayTreeInfo *) NULL)
624    {
625      (void) UnlockSemaphoreInfo(cache_semaphore);
626      return;
627    }
628  ResetSplayTreeIterator(cache_resources);
629  p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
630  while (p != (CacheInfo *) NULL)
631  {
632    if ((p->type == DiskCache) && (p->file != -1))
633      {
634        if (IsMagickThreadEqual(p->id) != MagickFalse)
635          break;
636      }
637    p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
638  }
639  for (q=p; p != (CacheInfo *) NULL; )
640  {
641    if ((p->type == DiskCache) && (p->file != -1) &&
642        (p->timestamp < q->timestamp))
643      {
644        if (IsMagickThreadEqual(p->id) != MagickFalse)
645          q=p;
646      }
647    p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
648  }
649  if (q != (CacheInfo *) NULL)
650    (void) ClosePixelCacheOnDisk(q);  /* relinquish least recently used cache */
651  (void) UnlockSemaphoreInfo(cache_semaphore);
652}
653
654static inline MagickSizeType MagickMax(const MagickSizeType x,
655  const MagickSizeType y)
656{
657  if (x > y)
658    return(x);
659  return(y);
660}
661
662static inline MagickSizeType MagickMin(const MagickSizeType x,
663  const MagickSizeType y)
664{
665  if (x < y)
666    return(x);
667  return(y);
668}
669
670static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
671  const MapMode mode)
672{
673  int
674    file;
675
676  /*
677    Open pixel cache on disk.
678  */
679  (void) LockSemaphoreInfo(cache_info->disk_semaphore);
680  if (cache_info->file != -1)
681    {
682      (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
683      return(MagickTrue);  /* cache already open */
684    }
685  LimitPixelCacheDescriptors();
686  if (*cache_info->cache_filename == '\0')
687    file=AcquireUniqueFileResource(cache_info->cache_filename);
688  else
689    switch (mode)
690    {
691      case ReadMode:
692      {
693        file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
694        break;
695      }
696      case WriteMode:
697      {
698        file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
699          O_EXCL,S_MODE);
700        if (file == -1)
701          file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
702        break;
703      }
704      case IOMode:
705      default:
706      {
707        file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
708          O_EXCL,S_MODE);
709        if (file == -1)
710          file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
711        break;
712      }
713    }
714  if (file == -1)
715    {
716      (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
717      return(MagickFalse);
718    }
719  (void) AcquireMagickResource(FileResource,1);
720  cache_info->file=file;
721  cache_info->timestamp=time(0);
722  (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
723  return(MagickTrue);
724}
725
726static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
727  const MagickOffsetType offset,const MagickSizeType length,
728  unsigned char *__restrict buffer)
729{
730  register MagickOffsetType
731    i;
732
733  ssize_t
734    count;
735
736#if !defined(MAGICKCORE_HAVE_PREAD)
737  (void) LockSemaphoreInfo(cache_info->disk_semaphore);
738  cache_info->timestamp=time(0);
739  if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
740    {
741      (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
742      return((MagickOffsetType) -1);
743    }
744#endif
745  count=0;
746  for (i=0; i < (MagickOffsetType) length; i+=count)
747  {
748#if !defined(MAGICKCORE_HAVE_PREAD)
749    count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
750      (MagickSizeType) SSIZE_MAX));
751#else
752    count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
753      (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
754#endif
755    if (count > 0)
756      continue;
757    count=0;
758    if (errno != EINTR)
759      {
760        i=(-1);
761        break;
762      }
763  }
764#if !defined(MAGICKCORE_HAVE_PREAD)
765  (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
766#endif
767  return(i);
768}
769
770static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
771  const MagickOffsetType offset,const MagickSizeType length,
772  const unsigned char *__restrict buffer)
773{
774  register MagickOffsetType
775    i;
776
777  ssize_t
778    count;
779
780#if !defined(MAGICKCORE_HAVE_PWRITE)
781  (void) LockSemaphoreInfo(cache_info->disk_semaphore);
782  cache_info->timestamp=time(0);
783  if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
784    {
785      (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
786      return((MagickOffsetType) -1);
787    }
788#endif
789  count=0;
790  for (i=0; i < (MagickOffsetType) length; i+=count)
791  {
792#if !defined(MAGICKCORE_HAVE_PWRITE)
793    count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
794      (MagickSizeType) SSIZE_MAX));
795#else
796    count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
797      (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
798#endif
799    if (count > 0)
800      continue;
801    count=0;
802    if (errno != EINTR)
803      {
804        i=(-1);
805        break;
806      }
807  }
808#if !defined(MAGICKCORE_HAVE_PWRITE)
809  (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
810#endif
811  return(i);
812}
813
814static MagickBooleanType CloneDiskToDiskPixelCache(CacheInfo *clone_info,
815  CacheInfo *cache_info,ExceptionInfo *exception)
816{
817  MagickOffsetType
818    count,
819    offset,
820    source_offset;
821
822  MagickSizeType
823    length;
824
825  register long
826    y;
827
828  register PixelPacket
829    *__restrict pixels;
830
831  unsigned long
832    columns,
833    rows;
834
835  if (cache_info->debug != MagickFalse)
836    (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
837  if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
838    {
839      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
840        clone_info->cache_filename);
841      return(MagickFalse);
842    }
843  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
844    {
845      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
846        cache_info->cache_filename);
847      return(MagickFalse);
848    }
849  columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
850  rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
851  if ((clone_info->active_index_channel != MagickFalse) &&
852      (cache_info->active_index_channel != MagickFalse))
853    {
854      register IndexPacket
855        *indexes;
856
857      /*
858        Clone cache indexes.
859      */
860      length=MagickMax(clone_info->columns,cache_info->columns)*
861        sizeof(*indexes);
862      indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
863      if (indexes == (IndexPacket *) NULL)
864        {
865          (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
866            "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
867          return(MagickFalse);
868        }
869      (void) ResetMagickMemory(indexes,0,(size_t) length);
870      length=columns*sizeof(*indexes);
871      source_offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
872        sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
873      offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
874        sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
875      for (y=0; y < (long) rows; y++)
876      {
877        source_offset-=cache_info->columns*sizeof(*indexes);
878        count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
879          length,(unsigned char *) indexes);
880        if ((MagickSizeType) count != length)
881          break;
882        offset-=clone_info->columns*sizeof(*indexes);
883        count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
884          (unsigned char *) indexes);
885        if ((MagickSizeType) count != length)
886          break;
887      }
888      if (y < (long) rows)
889        {
890          indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
891          ThrowFileException(exception,CacheError,"UnableToCloneCache",
892            cache_info->cache_filename);
893          return(MagickFalse);
894        }
895      if (clone_info->columns > cache_info->columns)
896        {
897          length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
898          (void) ResetMagickMemory(indexes,0,(size_t) length);
899          offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
900            sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
901          for (y=0; y < (long) rows; y++)
902          {
903            offset-=clone_info->columns*sizeof(*indexes);
904            count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
905              length,(unsigned char *) indexes);
906            if ((MagickSizeType) count != length)
907              break;
908          }
909          if (y < (long) rows)
910            {
911              indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
912              ThrowFileException(exception,CacheError,"UnableToCloneCache",
913                cache_info->cache_filename);
914              return(MagickFalse);
915            }
916        }
917      indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
918    }
919  /*
920    Clone cache pixels.
921  */
922  length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
923  pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
924  if (pixels == (PixelPacket *) NULL)
925    {
926      (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
927        "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
928      return(MagickFalse);
929    }
930  (void) ResetMagickMemory(pixels,0,(size_t) length);
931  length=columns*sizeof(*pixels);
932  source_offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
933  offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
934  for (y=0; y < (long) rows; y++)
935  {
936    source_offset-=cache_info->columns*sizeof(*pixels);
937    count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
938      length,(unsigned char *) pixels);
939    if ((MagickSizeType) count != length)
940      break;
941    offset-=clone_info->columns*sizeof(*pixels);
942    count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
943      (unsigned char *) pixels);
944    if ((MagickSizeType) count != length)
945      break;
946  }
947  if (y < (long) rows)
948    {
949      pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
950      ThrowFileException(exception,CacheError,"UnableToCloneCache",
951        cache_info->cache_filename);
952      return(MagickFalse);
953    }
954  if (clone_info->columns > cache_info->columns)
955    {
956      offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
957        sizeof(*pixels);
958      length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
959      (void) ResetMagickMemory(pixels,0,(size_t) length);
960      for (y=0; y < (long) rows; y++)
961      {
962        offset-=clone_info->columns*sizeof(*pixels);
963        count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
964          (unsigned char *) pixels);
965        if ((MagickSizeType) count != length)
966          break;
967      }
968      if (y < (long) rows)
969        {
970          pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
971          ThrowFileException(exception,CacheError,"UnableToCloneCache",
972            cache_info->cache_filename);
973          return(MagickFalse);
974        }
975    }
976  pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
977  return(MagickTrue);
978}
979
980static MagickBooleanType CloneDiskToMemoryPixelCache(CacheInfo *clone_info,
981  CacheInfo *cache_info,ExceptionInfo *exception)
982{
983  MagickOffsetType
984    count,
985    offset;
986
987  MagickSizeType
988    length;
989
990  register long
991    y;
992
993  register PixelPacket
994    *__restrict pixels,
995    *__restrict q;
996
997  unsigned long
998    columns,
999    rows;
1000
1001  if (cache_info->debug != MagickFalse)
1002    (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
1003  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
1004    {
1005      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1006        cache_info->cache_filename);
1007      return(MagickFalse);
1008    }
1009  columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
1010  rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
1011  if ((clone_info->active_index_channel != MagickFalse) &&
1012      (cache_info->active_index_channel != MagickFalse))
1013    {
1014      register IndexPacket
1015        *indexes,
1016        *q;
1017
1018      /*
1019        Clone cache indexes.
1020      */
1021      length=MagickMax(clone_info->columns,cache_info->columns)*
1022        sizeof(*indexes);
1023      indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
1024      if (indexes == (IndexPacket *) NULL)
1025        {
1026          (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
1027            "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
1028          return(MagickFalse);
1029        }
1030      (void) ResetMagickMemory(indexes,0,(size_t) length);
1031      length=columns*sizeof(IndexPacket);
1032      offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
1033        sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
1034      q=clone_info->indexes+clone_info->columns*rows;
1035      for (y=0; y < (long) rows; y++)
1036      {
1037        offset-=cache_info->columns*sizeof(IndexPacket);
1038        count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset,
1039          length,(unsigned char *) indexes);
1040        if ((MagickSizeType) count != length)
1041          break;
1042        q-=clone_info->columns;
1043        (void) CopyMagickMemory(q,indexes,(size_t) length);
1044        if ((MagickSizeType) count != length)
1045          break;
1046      }
1047      if (y < (long) rows)
1048        {
1049          indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1050          ThrowFileException(exception,CacheError,"UnableToCloneCache",
1051            cache_info->cache_filename);
1052          return(MagickFalse);
1053        }
1054      indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1055    }
1056  /*
1057    Clone cache pixels.
1058  */
1059  length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
1060  pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
1061  if (pixels == (PixelPacket *) NULL)
1062    {
1063      (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
1064        "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
1065      return(MagickFalse);
1066    }
1067  (void) ResetMagickMemory(pixels,0,(size_t) length);
1068  length=columns*sizeof(*pixels);
1069  offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
1070  q=clone_info->pixels+clone_info->columns*rows;
1071  for (y=0; y < (long) rows; y++)
1072  {
1073    offset-=cache_info->columns*sizeof(*pixels);
1074    count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset,length,
1075      (unsigned char *) pixels);
1076    if ((MagickSizeType) count != length)
1077      break;
1078    q-=clone_info->columns;
1079    (void) CopyMagickMemory(q,pixels,(size_t) length);
1080  }
1081  if (y < (long) rows)
1082    {
1083      pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1084      ThrowFileException(exception,CacheError,"UnableToCloneCache",
1085        cache_info->cache_filename);
1086      return(MagickFalse);
1087    }
1088  pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1089  return(MagickTrue);
1090}
1091
1092static MagickBooleanType CloneMemoryToDiskPixelCache(CacheInfo *clone_info,
1093  CacheInfo *cache_info,ExceptionInfo *exception)
1094{
1095  MagickOffsetType
1096    count,
1097    offset;
1098
1099  MagickSizeType
1100    length;
1101
1102  register long
1103    y;
1104
1105  register PixelPacket
1106    *__restrict p,
1107    *__restrict pixels;
1108
1109  unsigned long
1110    columns,
1111    rows;
1112
1113  if (cache_info->debug != MagickFalse)
1114    (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
1115  if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
1116    {
1117      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1118        clone_info->cache_filename);
1119      return(MagickFalse);
1120    }
1121  columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
1122  rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
1123  if ((clone_info->active_index_channel != MagickFalse) &&
1124      (cache_info->active_index_channel != MagickFalse))
1125    {
1126      register IndexPacket
1127        *p,
1128        *indexes;
1129
1130      /*
1131        Clone cache indexes.
1132      */
1133      length=MagickMax(clone_info->columns,cache_info->columns)*
1134        sizeof(*indexes);
1135      indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
1136      if (indexes == (IndexPacket *) NULL)
1137        {
1138          (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
1139            "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
1140          return(MagickFalse);
1141        }
1142      (void) ResetMagickMemory(indexes,0,(size_t) length);
1143      length=columns*sizeof(*indexes);
1144      p=cache_info->indexes+cache_info->columns*rows;
1145      offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
1146        sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
1147      for (y=0; y < (long) rows; y++)
1148      {
1149        p-=cache_info->columns;
1150        (void) CopyMagickMemory(indexes,p,(size_t) length);
1151        offset-=clone_info->columns*sizeof(*indexes);
1152        count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
1153          (unsigned char *) indexes);
1154        if ((MagickSizeType) count != length)
1155          break;
1156      }
1157      if (y < (long) rows)
1158        {
1159          indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1160          ThrowFileException(exception,CacheError,"UnableToCloneCache",
1161            cache_info->cache_filename);
1162          return(MagickFalse);
1163        }
1164      if (clone_info->columns > cache_info->columns)
1165        {
1166          length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
1167          (void) ResetMagickMemory(indexes,0,(size_t) length);
1168          offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
1169            sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
1170          for (y=0; y < (long) rows; y++)
1171          {
1172            offset-=clone_info->columns*sizeof(*indexes);
1173            count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
1174              length,(unsigned char *) indexes);
1175            if ((MagickSizeType) count != length)
1176              break;
1177          }
1178          if (y < (long) rows)
1179            {
1180              indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1181              ThrowFileException(exception,CacheError,"UnableToCloneCache",
1182                cache_info->cache_filename);
1183              return(MagickFalse);
1184            }
1185        }
1186      indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1187    }
1188  /*
1189    Clone cache pixels.
1190  */
1191  length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
1192  pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
1193  if (pixels == (PixelPacket *) NULL)
1194    {
1195      (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
1196        "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
1197      return(MagickFalse);
1198    }
1199  (void) ResetMagickMemory(pixels,0,(size_t) length);
1200  length=columns*sizeof(*pixels);
1201  p=cache_info->pixels+cache_info->columns*rows;
1202  offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
1203  for (y=0; y < (long) rows; y++)
1204  {
1205    p-=cache_info->columns;
1206    (void) CopyMagickMemory(pixels,p,(size_t) length);
1207    offset-=clone_info->columns*sizeof(*pixels);
1208    count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
1209      (unsigned char *) pixels);
1210    if ((MagickSizeType) count != length)
1211      break;
1212  }
1213  if (y < (long) rows)
1214    {
1215      pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1216      ThrowFileException(exception,CacheError,"UnableToCloneCache",
1217        cache_info->cache_filename);
1218      return(MagickFalse);
1219    }
1220  if (clone_info->columns > cache_info->columns)
1221    {
1222      offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
1223        sizeof(*pixels);
1224      length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
1225      (void) ResetMagickMemory(pixels,0,(size_t) length);
1226      for (y=0; y < (long) rows; y++)
1227      {
1228        offset-=clone_info->columns*sizeof(*pixels);
1229        count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
1230          (unsigned char *) pixels);
1231        if ((MagickSizeType) count != length)
1232          break;
1233      }
1234      if (y < (long) rows)
1235        {
1236          pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1237          ThrowFileException(exception,CacheError,"UnableToCloneCache",
1238            cache_info->cache_filename);
1239          return(MagickFalse);
1240        }
1241    }
1242  pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1243  return(MagickTrue);
1244}
1245
1246static MagickBooleanType CloneMemoryToMemoryPixelCache(CacheInfo *clone_info,
1247  CacheInfo *cache_info,ExceptionInfo *magick_unused(exception))
1248{
1249  register long
1250    y;
1251
1252  register PixelPacket
1253    *__restrict pixels,
1254    *__restrict source_pixels;
1255
1256  size_t
1257    length;
1258
1259  unsigned long
1260    columns,
1261    rows;
1262
1263  if (cache_info->debug != MagickFalse)
1264    (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
1265  columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
1266  rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
1267  if ((clone_info->active_index_channel != MagickFalse) &&
1268      (cache_info->active_index_channel != MagickFalse))
1269    {
1270      register IndexPacket
1271        *indexes,
1272        *source_indexes;
1273
1274      /*
1275        Clone cache indexes.
1276      */
1277      length=columns*sizeof(*indexes);
1278      if (clone_info->columns == cache_info->columns)
1279        (void) CopyMagickMemory(clone_info->indexes,cache_info->indexes,
1280          length*rows);
1281      else
1282        {
1283          source_indexes=cache_info->indexes+cache_info->columns*rows;
1284          indexes=clone_info->indexes+clone_info->columns*rows;
1285          for (y=0; y < (long) rows; y++)
1286          {
1287            source_indexes-=cache_info->columns;
1288            indexes-=clone_info->columns;
1289            (void) CopyMagickMemory(indexes,source_indexes,length);
1290          }
1291          if (clone_info->columns > cache_info->columns)
1292            {
1293              length=(clone_info->columns-cache_info->columns)*
1294                sizeof(*indexes);
1295              indexes=clone_info->indexes+clone_info->columns*rows+
1296                cache_info->columns;
1297              for (y=0; y < (long) rows; y++)
1298              {
1299                indexes-=clone_info->columns;
1300                (void) ResetMagickMemory(indexes,0,length);
1301              }
1302            }
1303        }
1304    }
1305  /*
1306    Clone cache pixels.
1307  */
1308  length=columns*sizeof(*pixels);
1309  if (clone_info->columns == cache_info->columns)
1310    (void) CopyMagickMemory(clone_info->pixels,cache_info->pixels,length*rows);
1311  else
1312    {
1313      source_pixels=cache_info->pixels+cache_info->columns*rows;
1314      pixels=clone_info->pixels+clone_info->columns*rows;
1315      for (y=0; y < (long) rows; y++)
1316      {
1317        source_pixels-=cache_info->columns;
1318        pixels-=clone_info->columns;
1319        (void) CopyMagickMemory(pixels,source_pixels,length);
1320      }
1321      if (clone_info->columns > cache_info->columns)
1322        {
1323          length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
1324          pixels=clone_info->pixels+clone_info->columns*rows+
1325            cache_info->columns;
1326          for (y=0; y < (long) rows; y++)
1327          {
1328            pixels-=clone_info->columns;
1329            (void) ResetMagickMemory(pixels,0,length);
1330          }
1331        }
1332    }
1333  return(MagickTrue);
1334}
1335
1336static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1337  CacheInfo *cache_info,ExceptionInfo *exception)
1338{
1339  if ((clone_info->type != DiskCache) && (cache_info->type != DiskCache))
1340    return(CloneMemoryToMemoryPixelCache(clone_info,cache_info,exception));
1341  if ((clone_info->type == DiskCache) && (cache_info->type == DiskCache))
1342    return(CloneDiskToDiskPixelCache(clone_info,cache_info,exception));
1343  if (cache_info->type == DiskCache)
1344    return(CloneDiskToMemoryPixelCache(clone_info,cache_info,exception));
1345  return(CloneMemoryToDiskPixelCache(clone_info,cache_info,exception));
1346}
1347
1348/*
1349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1350%                                                                             %
1351%                                                                             %
1352%                                                                             %
1353+   C l o n e P i x e l C a c h e M e t h o d s                               %
1354%                                                                             %
1355%                                                                             %
1356%                                                                             %
1357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358%
1359%  ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1360%  another.
1361%
1362%  The format of the ClonePixelCacheMethods() method is:
1363%
1364%      void ClonePixelCacheMethods(Cache clone,const Cache cache)
1365%
1366%  A description of each parameter follows:
1367%
1368%    o clone: Specifies a pointer to a Cache structure.
1369%
1370%    o cache: the pixel cache.
1371%
1372*/
1373MagickExport void ClonePixelCacheMethods(Cache clone,const Cache cache)
1374{
1375  CacheInfo
1376    *cache_info,
1377    *source_info;
1378
1379  assert(clone != (Cache) NULL);
1380  source_info=(CacheInfo *) clone;
1381  assert(source_info->signature == MagickSignature);
1382  if (source_info->debug != MagickFalse)
1383    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1384      source_info->filename);
1385  assert(cache != (Cache) NULL);
1386  cache_info=(CacheInfo *) cache;
1387  assert(cache_info->signature == MagickSignature);
1388  source_info->methods=cache_info->methods;
1389}
1390
1391/*
1392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1393%                                                                             %
1394%                                                                             %
1395%                                                                             %
1396+   D e s t r o y I m a g e P i x e l C a c h e                               %
1397%                                                                             %
1398%                                                                             %
1399%                                                                             %
1400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1401%
1402%  DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1403%
1404%  The format of the DestroyImagePixelCache() method is:
1405%
1406%      void DestroyImagePixelCache(Image *image)
1407%
1408%  A description of each parameter follows:
1409%
1410%    o image: the image.
1411%
1412*/
1413static void DestroyImagePixelCache(Image *image)
1414{
1415  assert(image != (Image *) NULL);
1416  assert(image->signature == MagickSignature);
1417  if (image->debug != MagickFalse)
1418    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1419  if (image->cache == (void *) NULL)
1420    return;
1421  image->cache=DestroyPixelCache(image->cache);
1422}
1423
1424/*
1425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1426%                                                                             %
1427%                                                                             %
1428%                                                                             %
1429+   D e s t r o y I m a g e P i x e l s                                       %
1430%                                                                             %
1431%                                                                             %
1432%                                                                             %
1433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1434%
1435%  DestroyImagePixels() deallocates memory associated with the pixel cache.
1436%
1437%  The format of the DestroyImagePixels() method is:
1438%
1439%      void DestroyImagePixels(Image *image)
1440%
1441%  A description of each parameter follows:
1442%
1443%    o image: the image.
1444%
1445*/
1446MagickExport void DestroyImagePixels(Image *image)
1447{
1448  CacheInfo
1449    *cache_info;
1450
1451  assert(image != (const Image *) NULL);
1452  assert(image->signature == MagickSignature);
1453  if (image->debug != MagickFalse)
1454    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1455  assert(image->cache != (Cache) NULL);
1456  cache_info=(CacheInfo *) image->cache;
1457  assert(cache_info->signature == MagickSignature);
1458  if (cache_info->methods.destroy_pixel_handler == (DestroyPixelHandler) NULL)
1459    return;
1460  cache_info->methods.destroy_pixel_handler(image);
1461}
1462
1463/*
1464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465%                                                                             %
1466%                                                                             %
1467%                                                                             %
1468+   D e s t r o y P i x e l C a c h e                                         %
1469%                                                                             %
1470%                                                                             %
1471%                                                                             %
1472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1473%
1474%  DestroyPixelCache() deallocates memory associated with the pixel cache.
1475%
1476%  The format of the DestroyPixelCache() method is:
1477%
1478%      Cache DestroyPixelCache(Cache cache)
1479%
1480%  A description of each parameter follows:
1481%
1482%    o cache: the pixel cache.
1483%
1484*/
1485
1486static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1487{
1488  switch (cache_info->type)
1489  {
1490    case MemoryCache:
1491    {
1492      if (cache_info->mapped == MagickFalse)
1493        cache_info->pixels=(PixelPacket *) RelinquishMagickMemory(
1494          cache_info->pixels);
1495      else
1496        cache_info->pixels=(PixelPacket *) UnmapBlob(cache_info->pixels,
1497          (size_t) cache_info->length);
1498      RelinquishMagickResource(MemoryResource,cache_info->length);
1499      break;
1500    }
1501    case MapCache:
1502    {
1503      cache_info->pixels=(PixelPacket *) UnmapBlob(cache_info->pixels,(size_t)
1504        cache_info->length);
1505      RelinquishMagickResource(MapResource,cache_info->length);
1506    }
1507    case DiskCache:
1508    {
1509      if (cache_info->file != -1)
1510        (void) ClosePixelCacheOnDisk(cache_info);
1511      RelinquishMagickResource(DiskResource,cache_info->length);
1512      break;
1513    }
1514    default:
1515      break;
1516  }
1517  cache_info->type=UndefinedCache;
1518  cache_info->mapped=MagickFalse;
1519  cache_info->indexes=(IndexPacket *) NULL;
1520}
1521
1522MagickExport Cache DestroyPixelCache(Cache cache)
1523{
1524  CacheInfo
1525    *cache_info;
1526
1527  assert(cache != (Cache) NULL);
1528  cache_info=(CacheInfo *) cache;
1529  assert(cache_info->signature == MagickSignature);
1530  if (cache_info->debug != MagickFalse)
1531    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1532      cache_info->filename);
1533  (void) LockSemaphoreInfo(cache_info->semaphore);
1534  cache_info->reference_count--;
1535  if (cache_info->reference_count != 0)
1536    {
1537      (void) UnlockSemaphoreInfo(cache_info->semaphore);
1538      return((Cache) NULL);
1539    }
1540  (void) UnlockSemaphoreInfo(cache_info->semaphore);
1541  if (cache_resources != (SplayTreeInfo *) NULL)
1542    (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
1543  if (cache_info->debug != MagickFalse)
1544    {
1545      char
1546        message[MaxTextExtent];
1547
1548      (void) FormatMagickString(message,MaxTextExtent,"destroy %s",
1549        cache_info->filename);
1550      (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1551    }
1552  if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1553      (cache_info->type != DiskCache)))
1554    RelinquishPixelCachePixels(cache_info);
1555  else
1556    {
1557      RelinquishPixelCachePixels(cache_info);
1558      (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1559    }
1560  *cache_info->cache_filename='\0';
1561  if (cache_info->nexus_info != (NexusInfo **) NULL)
1562    cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1563      cache_info->number_threads);
1564  if (cache_info->random_info != (RandomInfo *) NULL)
1565    cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1566  cache_info->signature=(~MagickSignature);
1567  if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1568    DestroySemaphoreInfo(&cache_info->disk_semaphore);
1569  if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1570    DestroySemaphoreInfo(&cache_info->semaphore);
1571  cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1572  cache=(Cache) NULL;
1573  return(cache);
1574}
1575
1576/*
1577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1578%                                                                             %
1579%                                                                             %
1580%                                                                             %
1581+   D e s t r o y P i x e l C a c h e N e x u s                               %
1582%                                                                             %
1583%                                                                             %
1584%                                                                             %
1585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1586%
1587%  DestroyPixelCacheNexus() destroys a pixel cache nexus.
1588%
1589%  The format of the DestroyPixelCacheNexus() method is:
1590%
1591%      NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1592%        const unsigned long number_threads)
1593%
1594%  A description of each parameter follows:
1595%
1596%    o nexus_info: the nexus to destroy.
1597%
1598%    o number_threads: the number of nexus threads.
1599%
1600*/
1601
1602static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1603{
1604  if (nexus_info->mapped == MagickFalse)
1605    (void) RelinquishMagickMemory(nexus_info->cache);
1606  else
1607    (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1608  nexus_info->cache=(PixelPacket *) NULL;
1609  nexus_info->pixels=(PixelPacket *) NULL;
1610  nexus_info->indexes=(IndexPacket *) NULL;
1611  nexus_info->length=0;
1612  nexus_info->mapped=MagickFalse;
1613}
1614
1615MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1616  const unsigned long number_threads)
1617{
1618  register long
1619    i;
1620
1621  assert(nexus_info != (NexusInfo **) NULL);
1622  for (i=0; i < (long) number_threads; i++)
1623  {
1624    if (nexus_info[i]->cache != (PixelPacket *) NULL)
1625      RelinquishCacheNexusPixels(nexus_info[i]);
1626    nexus_info[i]->signature=(~MagickSignature);
1627    nexus_info[i]=(NexusInfo *) RelinquishAlignedMemory(nexus_info[i]);
1628  }
1629  nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1630  return(nexus_info);
1631}
1632
1633/*
1634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1635%                                                                             %
1636%                                                                             %
1637%                                                                             %
1638+   G e t A u t h e n t i c I n d e x e s F r o m C a c h e                   %
1639%                                                                             %
1640%                                                                             %
1641%                                                                             %
1642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1643%
1644%  GetAuthenticIndexesFromCache() returns the indexes associated with the last
1645%  call to QueueAuthenticPixelsCache() or GetAuthenticPixelsCache().
1646%
1647%  The format of the GetAuthenticIndexesFromCache() method is:
1648%
1649%      IndexPacket *GetAuthenticIndexesFromCache(const Image *image)
1650%
1651%  A description of each parameter follows:
1652%
1653%    o image: the image.
1654%
1655*/
1656static IndexPacket *GetAuthenticIndexesFromCache(const Image *image)
1657{
1658  CacheInfo
1659    *cache_info;
1660
1661  IndexPacket
1662    *indexes;
1663
1664  long
1665    id;
1666
1667  if (image->debug != MagickFalse)
1668    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1669  cache_info=(CacheInfo *) image->cache;
1670  id=GetOpenMPThreadId();
1671  assert(id < (long) cache_info->number_threads);
1672  indexes=GetPixelCacheNexusIndexes(image->cache,cache_info->nexus_info[id]);
1673  return(indexes);
1674}
1675
1676/*
1677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1678%                                                                             %
1679%                                                                             %
1680%                                                                             %
1681%   G e t A u t h e n t i c I n d e x Q u e u e                               %
1682%                                                                             %
1683%                                                                             %
1684%                                                                             %
1685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1686%
1687%  GetAuthenticIndexQueue() returns the authentic black channel or the colormap
1688%  indexes associated with the last call to QueueAuthenticPixels() or
1689%  GetVirtualPixels().  NULL is returned if the black channel or colormap
1690%  indexes are not available.
1691%
1692%  The format of the GetAuthenticIndexQueue() method is:
1693%
1694%      IndexPacket *GetAuthenticIndexQueue(const Image *image)
1695%
1696%  A description of each parameter follows:
1697%
1698%    o image: the image.
1699%
1700*/
1701MagickExport IndexPacket *GetAuthenticIndexQueue(const Image *image)
1702{
1703  CacheInfo
1704    *cache_info;
1705
1706  assert(image != (const Image *) NULL);
1707  assert(image->signature == MagickSignature);
1708  if (image->debug != MagickFalse)
1709    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1710  assert(image->cache != (Cache) NULL);
1711  cache_info=(CacheInfo *) image->cache;
1712  assert(cache_info->signature == MagickSignature);
1713  if (cache_info->methods.get_authentic_indexes_from_handler ==
1714       (GetAuthenticIndexesFromHandler) NULL)
1715    return((IndexPacket *) NULL);
1716  return(cache_info->methods.get_authentic_indexes_from_handler(image));
1717}
1718
1719/*
1720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1721%                                                                             %
1722%                                                                             %
1723%                                                                             %
1724+   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                     %
1725%                                                                             %
1726%                                                                             %
1727%                                                                             %
1728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1729%
1730%  GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1731%  disk pixel cache as defined by the geometry parameters.   A pointer to the
1732%  pixels is returned if the pixels are transferred, otherwise a NULL is
1733%  returned.
1734%
1735%  The format of the GetAuthenticPixelCacheNexus() method is:
1736%
1737%      PixelPacket *GetAuthenticPixelCacheNexus(Image *image,const long x,
1738%        const long y,const unsigned long columns,const unsigned long rows,
1739%        NexusInfo *nexus_info,ExceptionInfo *exception)
1740%
1741%  A description of each parameter follows:
1742%
1743%    o image: the image.
1744%
1745%    o x,y,columns,rows:  These values define the perimeter of a region of
1746%      pixels.
1747%
1748%    o nexus_info: the cache nexus to return.
1749%
1750%    o exception: return any errors or warnings in this structure.
1751%
1752*/
1753
1754static inline MagickBooleanType IsNexusInCore(const CacheInfo *cache_info,
1755  NexusInfo *nexus_info)
1756{
1757  MagickOffsetType
1758    offset;
1759
1760  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1761    nexus_info->region.x;
1762  if (nexus_info->pixels != (cache_info->pixels+offset))
1763    return(MagickFalse);
1764  return(MagickTrue);
1765}
1766
1767MagickExport PixelPacket *GetAuthenticPixelCacheNexus(Image *image,const long x,
1768  const long y,const unsigned long columns,const unsigned long rows,
1769  NexusInfo *nexus_info,ExceptionInfo *exception)
1770{
1771  CacheInfo
1772    *cache_info;
1773
1774  PixelPacket
1775    *pixels;
1776
1777  /*
1778    Transfer pixels from the cache.
1779  */
1780  assert(image != (Image *) NULL);
1781  assert(image->signature == MagickSignature);
1782  if (image->debug != MagickFalse)
1783    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1784  pixels=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
1785  if (pixels == (PixelPacket *) NULL)
1786    return((PixelPacket *) NULL);
1787  cache_info=(CacheInfo *) image->cache;
1788  assert(cache_info->signature == MagickSignature);
1789  if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
1790    return(pixels);
1791  if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1792    return((PixelPacket *) NULL);
1793  if (cache_info->active_index_channel != MagickFalse)
1794    if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1795      return((PixelPacket *) NULL);
1796  return(pixels);
1797}
1798
1799/*
1800%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1801%                                                                             %
1802%                                                                             %
1803%                                                                             %
1804+   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                     %
1805%                                                                             %
1806%                                                                             %
1807%                                                                             %
1808%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1809%
1810%  GetAuthenticPixelsFromCache() returns the pixels associated with the last
1811%  call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1812%
1813%  The format of the GetAuthenticPixelsFromCache() method is:
1814%
1815%      PixelPacket *GetAuthenticPixelsFromCache(const Image image)
1816%
1817%  A description of each parameter follows:
1818%
1819%    o image: the image.
1820%
1821*/
1822static PixelPacket *GetAuthenticPixelsFromCache(const Image *image)
1823{
1824  CacheInfo
1825    *cache_info;
1826
1827  long
1828    id;
1829
1830  PixelPacket
1831    *pixels;
1832
1833  if (image->debug != MagickFalse)
1834    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1835  cache_info=(CacheInfo *) image->cache;
1836  id=GetOpenMPThreadId();
1837  assert(id < (long) cache_info->number_threads);
1838  pixels=GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]);
1839  return(pixels);
1840}
1841
1842/*
1843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1844%                                                                             %
1845%                                                                             %
1846%                                                                             %
1847%   G e t A u t h e n t i c P i x e l Q u e u e                               %
1848%                                                                             %
1849%                                                                             %
1850%                                                                             %
1851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1852%
1853%  GetAuthenticPixelQueue() returns the authentic pixels associated with the
1854%  last call to QueueAuthenticPixels() or GetAuthenticPixels().
1855%
1856%  The format of the GetAuthenticPixelQueue() method is:
1857%
1858%      PixelPacket *GetAuthenticPixelQueue(const Image image)
1859%
1860%  A description of each parameter follows:
1861%
1862%    o image: the image.
1863%
1864*/
1865MagickExport PixelPacket *GetAuthenticPixelQueue(const Image *image)
1866{
1867  CacheInfo
1868    *cache_info;
1869
1870  assert(image != (const Image *) NULL);
1871  assert(image->signature == MagickSignature);
1872  if (image->debug != MagickFalse)
1873    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1874  assert(image->cache != (Cache) NULL);
1875  cache_info=(CacheInfo *) image->cache;
1876  assert(cache_info->signature == MagickSignature);
1877  if (cache_info->methods.get_authentic_pixels_from_handler ==
1878      (GetAuthenticPixelsFromHandler) NULL)
1879    return((PixelPacket *) NULL);
1880  return(cache_info->methods.get_authentic_pixels_from_handler(image));
1881}
1882
1883/*
1884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1885%                                                                             %
1886%                                                                             %
1887%                                                                             %
1888%   G e t A u t h e n t i c P i x e l s                                       %
1889%                                                                             %
1890%                                                                             %
1891%                                                                             %
1892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1893%
1894%  GetAuthenticPixels() obtains a pixel region for read/write access. If the
1895%  region is successfully accessed, a pointer to a PixelPacket array
1896%  representing the region is returned, otherwise NULL is returned.
1897%
1898%  The returned pointer may point to a temporary working copy of the pixels
1899%  or it may point to the original pixels in memory. Performance is maximized
1900%  if the selected region is part of one row, or one or more full rows, since
1901%  then there is opportunity to access the pixels in-place (without a copy)
1902%  if the image is in RAM, or in a memory-mapped file. The returned pointer
1903%  should *never* be deallocated by the user.
1904%
1905%  Pixels accessed via the returned pointer represent a simple array of type
1906%  PixelPacket. If the image type is CMYK or if the storage class is
1907%  PseduoClass, call GetAuthenticIndexQueue() after invoking
1908%  GetAuthenticPixels() to obtain the black color component or colormap indexes
1909%  (of type IndexPacket) corresponding to the region.  Once the PixelPacket
1910%  (and/or IndexPacket) array has been updated, the changes must be saved back
1911%  to the underlying image using SyncAuthenticPixels() or they may be lost.
1912%
1913%  The format of the GetAuthenticPixels() method is:
1914%
1915%      PixelPacket *GetAuthenticPixels(Image *image,const long x,const long y,
1916%        const unsigned long columns,const unsigned long rows,
1917%        ExceptionInfo *exception)
1918%
1919%  A description of each parameter follows:
1920%
1921%    o image: the image.
1922%
1923%    o x,y,columns,rows:  These values define the perimeter of a region of
1924%      pixels.
1925%
1926%    o exception: return any errors or warnings in this structure.
1927%
1928*/
1929MagickExport PixelPacket *GetAuthenticPixels(Image *image,const long x,
1930  const long y,const unsigned long columns,const unsigned long rows,
1931  ExceptionInfo *exception)
1932{
1933  CacheInfo
1934    *cache_info;
1935
1936  PixelPacket
1937    *pixels;
1938
1939  assert(image != (Image *) NULL);
1940  assert(image->signature == MagickSignature);
1941  if (image->debug != MagickFalse)
1942    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1943  assert(image->cache != (Cache) NULL);
1944  cache_info=(CacheInfo *) image->cache;
1945  assert(cache_info->signature == MagickSignature);
1946  if (cache_info->methods.get_authentic_pixels_handler ==
1947      (GetAuthenticPixelsHandler) NULL)
1948    return((PixelPacket *) NULL);
1949  pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1950    rows,exception);
1951  return(pixels);
1952}
1953
1954/*
1955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1956%                                                                             %
1957%                                                                             %
1958%                                                                             %
1959+   G e t A u t h e n t i c P i x e l s C a c h e                             %
1960%                                                                             %
1961%                                                                             %
1962%                                                                             %
1963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1964%
1965%  GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1966%  as defined by the geometry parameters.   A pointer to the pixels is returned
1967%  if the pixels are transferred, otherwise a NULL is returned.
1968%
1969%  The format of the GetAuthenticPixelsCache() method is:
1970%
1971%      PixelPacket *GetAuthenticPixelsCache(Image *image,const long x,
1972%        const long y,const unsigned long columns,const unsigned long rows,
1973%        ExceptionInfo *exception)
1974%
1975%  A description of each parameter follows:
1976%
1977%    o image: the image.
1978%
1979%    o x,y,columns,rows:  These values define the perimeter of a region of
1980%      pixels.
1981%
1982%    o exception: return any errors or warnings in this structure.
1983%
1984*/
1985static PixelPacket *GetAuthenticPixelsCache(Image *image,const long x,
1986  const long y,const unsigned long columns,const unsigned long rows,
1987  ExceptionInfo *exception)
1988{
1989  CacheInfo
1990    *cache_info;
1991
1992  long
1993    id;
1994
1995  PixelPacket
1996    *pixels;
1997
1998  cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
1999  if (cache_info == (Cache) NULL)
2000    return((PixelPacket *) NULL);
2001  id=GetOpenMPThreadId();
2002  assert(id < (long) cache_info->number_threads);
2003  pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
2004    cache_info->nexus_info[id],exception);
2005  return(pixels);
2006}
2007
2008/*
2009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2010%                                                                             %
2011%                                                                             %
2012%                                                                             %
2013+   G e t I m a g e E x t e n t                                               %
2014%                                                                             %
2015%                                                                             %
2016%                                                                             %
2017%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2018%
2019%  GetImageExtent() returns the extent of the pixels associated with the
2020%  last call to QueueAuthenticPixels() or GetAuthenticPixels().
2021%
2022%  The format of the GetImageExtent() method is:
2023%
2024%      MagickSizeType GetImageExtent(const Image *image)
2025%
2026%  A description of each parameter follows:
2027%
2028%    o image: the image.
2029%
2030*/
2031MagickExport MagickSizeType GetImageExtent(const Image *image)
2032{
2033  CacheInfo
2034    *cache_info;
2035
2036  long
2037    id;
2038
2039  MagickSizeType
2040    extent;
2041
2042  assert(image != (Image *) NULL);
2043  assert(image->signature == MagickSignature);
2044  if (image->debug != MagickFalse)
2045    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2046  assert(image->cache != (Cache) NULL);
2047  cache_info=(CacheInfo *) image->cache;
2048  assert(cache_info->signature == MagickSignature);
2049  id=GetOpenMPThreadId();
2050  assert(id < (long) cache_info->number_threads);
2051  extent=GetPixelCacheNexusExtent(image->cache,cache_info->nexus_info[id]);
2052  return(extent);
2053}
2054
2055/*
2056%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2057%                                                                             %
2058%                                                                             %
2059%                                                                             %
2060+   G e t I m a g e P i x e l C a c h e                                       %
2061%                                                                             %
2062%                                                                             %
2063%                                                                             %
2064%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2065%
2066%  GetImagePixelCache() ensures that there is only a single reference to the
2067%  pixel cache to be modified, updating the provided cache pointer to point to
2068%  a clone of the original pixel cache if necessary.
2069%
2070%  The format of the GetImagePixelCache method is:
2071%
2072%      Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
2073%        ExceptionInfo *exception)
2074%
2075%  A description of each parameter follows:
2076%
2077%    o image: the image.
2078%
2079%    o clone: any value other than MagickFalse clones the cache pixels.
2080%
2081%    o exception: return any errors or warnings in this structure.
2082%
2083*/
2084
2085static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
2086{
2087  CacheInfo
2088    *cache_info;
2089
2090  /*
2091    Does the image match the pixel cache morphology?
2092  */
2093  cache_info=(CacheInfo *) image->cache;
2094  if ((image->storage_class != cache_info->storage_class) ||
2095      (image->colorspace != cache_info->colorspace) ||
2096      (image->columns != cache_info->columns) ||
2097      (image->rows != cache_info->rows) ||
2098      (cache_info->nexus_info == (NexusInfo **) NULL) ||
2099      (cache_info->number_threads < GetOpenMPMaximumThreads()))
2100    return(MagickFalse);
2101  return(MagickTrue);
2102}
2103
2104MagickExport Cache GetImagePixelCache(Image *image,
2105  const MagickBooleanType clone,ExceptionInfo *exception)
2106{
2107  CacheInfo
2108    *cache_info;
2109
2110  MagickSizeType
2111    time_limit;
2112
2113  MagickBooleanType
2114    destroy,
2115    status;
2116
2117  if (image->debug != MagickFalse)
2118    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2119  status=MagickTrue;
2120  (void) LockSemaphoreInfo(image->semaphore);
2121  time_limit=GetMagickResourceLimit(TimeResource);
2122  if (cache_timer == 0)
2123    cache_timer=time((time_t *) NULL);
2124  if ((time_limit != MagickResourceInfinity) &&
2125      ((MagickSizeType) (time((time_t *) NULL)-cache_timer) >= time_limit))
2126    ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
2127  assert(image->cache != (Cache) NULL);
2128  cache_info=(CacheInfo *) image->cache;
2129  destroy=MagickFalse;
2130  (void) LockSemaphoreInfo(cache_info->semaphore);
2131  if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2132    {
2133      Image
2134        clone_image;
2135
2136      CacheInfo
2137        *clone_info;
2138
2139      /*
2140        Clone pixel cache.
2141      */
2142      clone_image=(*image);
2143      clone_image.cache=ClonePixelCache(cache_info);
2144      clone_info=(CacheInfo *) clone_image.cache;
2145      status=ClonePixelCacheNexus(cache_info,clone_info,exception);
2146      if (status != MagickFalse)
2147        {
2148          status=OpenPixelCache(&clone_image,IOMode,exception);
2149          if (status != MagickFalse)
2150            {
2151              if (clone != MagickFalse)
2152                status=ClonePixelCachePixels(clone_info,cache_info,exception);
2153              if (status != MagickFalse)
2154                {
2155                  destroy=MagickTrue;
2156                  image->cache=clone_image.cache;
2157                }
2158            }
2159        }
2160    }
2161  (void) UnlockSemaphoreInfo(cache_info->semaphore);
2162  if (destroy != MagickFalse)
2163    cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
2164  if (status != MagickFalse)
2165    {
2166      /*
2167        Ensure the image matches the pixel cache morphology.
2168      */
2169      image->taint=MagickTrue;
2170      image->type=UndefinedType;
2171      if (image->colorspace == GRAYColorspace)
2172        image->colorspace=RGBColorspace;
2173      if (ValidatePixelCacheMorphology(image) == MagickFalse)
2174        status=OpenPixelCache(image,IOMode,exception);
2175    }
2176  (void) UnlockSemaphoreInfo(image->semaphore);
2177  if (status == MagickFalse)
2178    return((Cache) NULL);
2179  return(image->cache);
2180}
2181
2182/*
2183%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2184%                                                                             %
2185%                                                                             %
2186%                                                                             %
2187%   G e t O n e A u t h e n t i c P i x e l                                   %
2188%                                                                             %
2189%                                                                             %
2190%                                                                             %
2191%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2192%
2193%  GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2194%  location.  The image background color is returned if an error occurs.
2195%
2196%  The format of the GetOneAuthenticPixel() method is:
2197%
2198%      MagickBooleanType GetOneAuthenticPixel(const Image image,const long x,
2199%        const long y,PixelPacket *pixel,ExceptionInfo *exception)
2200%
2201%  A description of each parameter follows:
2202%
2203%    o image: the image.
2204%
2205%    o x,y:  These values define the location of the pixel to return.
2206%
2207%    o pixel: return a pixel at the specified (x,y) location.
2208%
2209%    o exception: return any errors or warnings in this structure.
2210%
2211*/
2212MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,const long x,
2213  const long y,PixelPacket *pixel,ExceptionInfo *exception)
2214{
2215  CacheInfo
2216    *cache_info;
2217
2218  GetOneAuthenticPixelFromHandler
2219    get_one_authentic_pixel_from_handler;
2220
2221  MagickBooleanType
2222    status;
2223
2224  assert(image != (Image *) NULL);
2225  assert(image->signature == MagickSignature);
2226  if (image->debug != MagickFalse)
2227    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2228  assert(image->cache != (Cache) NULL);
2229  cache_info=(CacheInfo *) image->cache;
2230  assert(cache_info->signature == MagickSignature);
2231  *pixel=image->background_color;
2232  get_one_authentic_pixel_from_handler=
2233    cache_info->methods.get_one_authentic_pixel_from_handler;
2234  if (get_one_authentic_pixel_from_handler ==
2235      (GetOneAuthenticPixelFromHandler) NULL)
2236    return(MagickFalse);
2237  status=cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2238    pixel,exception);
2239  return(status);
2240}
2241
2242/*
2243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2244%                                                                             %
2245%                                                                             %
2246%                                                                             %
2247+   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                 %
2248%                                                                             %
2249%                                                                             %
2250%                                                                             %
2251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2252%
2253%  GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2254%  location.  The image background color is returned if an error occurs.
2255%
2256%  The format of the GetOneAuthenticPixelFromCache() method is:
2257%
2258%      MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2259%        const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
2260%
2261%  A description of each parameter follows:
2262%
2263%    o image: the image.
2264%
2265%    o x,y:  These values define the location of the pixel to return.
2266%
2267%    o pixel: return a pixel at the specified (x,y) location.
2268%
2269%    o exception: return any errors or warnings in this structure.
2270%
2271*/
2272static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2273  const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
2274{
2275  PixelPacket
2276    *pixels;
2277
2278  if (image->debug != MagickFalse)
2279    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2280  *pixel=image->background_color;
2281  pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2282  if (pixels == (PixelPacket *) NULL)
2283    return(MagickFalse);
2284  *pixel=(*pixels);
2285  return(MagickTrue);
2286}
2287
2288/*
2289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2290%                                                                             %
2291%                                                                             %
2292%                                                                             %
2293%   G e t O n e V i r t u a l M a g i c k P i x e l                           %
2294%                                                                             %
2295%                                                                             %
2296%                                                                             %
2297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2298%
2299%  GetOneVirtualMagickPixel() returns a single pixel at the specified (x,y)
2300%  location.  The image background color is returned if an error occurs.  If
2301%  you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2302%
2303%  The format of the GetOneVirtualMagickPixel() method is:
2304%
2305%      MagickBooleanType GetOneVirtualMagickPixel(const Image image,
2306%        const long x,const long y,MagickPixelPacket *pixel,
2307%        ExceptionInfo exception)
2308%
2309%  A description of each parameter follows:
2310%
2311%    o image: the image.
2312%
2313%    o x,y:  these values define the location of the pixel to return.
2314%
2315%    o pixel: return a pixel at the specified (x,y) location.
2316%
2317%    o exception: return any errors or warnings in this structure.
2318%
2319*/
2320MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
2321  const long x,const long y,MagickPixelPacket *pixel,ExceptionInfo *exception)
2322{
2323  CacheInfo
2324    *cache_info;
2325
2326  register const IndexPacket
2327    *indexes;
2328
2329  register const PixelPacket
2330    *p;
2331
2332  assert(image != (const Image *) NULL);
2333  assert(image->signature == MagickSignature);
2334  assert(image->cache != (Cache) NULL);
2335  cache_info=(CacheInfo *) image->cache;
2336  assert(cache_info->signature == MagickSignature);
2337  GetMagickPixelPacket(image,pixel);
2338  p=GetVirtualPixelCache(image,GetPixelCacheVirtualMethod(image),x,y,1,1,
2339    exception);
2340  if (p == (const PixelPacket *) NULL)
2341    return(MagickFalse);
2342  indexes=GetVirtualIndexQueue(image);
2343  SetMagickPixelPacket(image,p,indexes,pixel);
2344  return(MagickTrue);
2345}
2346
2347/*
2348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2349%                                                                             %
2350%                                                                             %
2351%                                                                             %
2352%   G e t O n e V i r t u a l M e t h o d P i x e l                           %
2353%                                                                             %
2354%                                                                             %
2355%                                                                             %
2356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2357%
2358%  GetOneVirtualMethodPixel() returns a single pixel at the specified (x,y)
2359%  location as defined by specified pixel method.  The image background color
2360%  is returned if an error occurs.  If you plan to modify the pixel, use
2361%  GetOneAuthenticPixel() instead.
2362%
2363%  The format of the GetOneVirtualMethodPixel() method is:
2364%
2365%      MagickBooleanType GetOneVirtualMethodPixel(const Image image,
2366%        const VirtualPixelMethod virtual_pixel_method,const long x,
2367%        const long y,Pixelpacket *pixel,ExceptionInfo exception)
2368%
2369%  A description of each parameter follows:
2370%
2371%    o image: the image.
2372%
2373%    o virtual_pixel_method: the virtual pixel method.
2374%
2375%    o x,y:  These values define the location of the pixel to return.
2376%
2377%    o pixel: return a pixel at the specified (x,y) location.
2378%
2379%    o exception: return any errors or warnings in this structure.
2380%
2381*/
2382MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
2383  const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
2384  PixelPacket *pixel,ExceptionInfo *exception)
2385{
2386  GetOneVirtualPixelFromHandler
2387    get_one_virtual_pixel_from_handler;
2388
2389  CacheInfo
2390    *cache_info;
2391
2392  MagickBooleanType
2393    status;
2394
2395  assert(image != (const Image *) NULL);
2396  assert(image->signature == MagickSignature);
2397  assert(image->cache != (Cache) NULL);
2398  cache_info=(CacheInfo *) image->cache;
2399  assert(cache_info->signature == MagickSignature);
2400  *pixel=image->background_color;
2401  get_one_virtual_pixel_from_handler=
2402    cache_info->methods.get_one_virtual_pixel_from_handler;
2403  if (get_one_virtual_pixel_from_handler ==
2404      (GetOneVirtualPixelFromHandler) NULL)
2405    return(MagickFalse);
2406  status=get_one_virtual_pixel_from_handler(image,virtual_pixel_method,x,y,
2407    pixel,exception);
2408  return(status);
2409}
2410
2411/*
2412%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2413%                                                                             %
2414%                                                                             %
2415%                                                                             %
2416%   G e t O n e V i r t u a l P i x e l                                       %
2417%                                                                             %
2418%                                                                             %
2419%                                                                             %
2420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2421%
2422%  GetOneVirtualPixel() returns a single virtual pixel at the specified
2423%  (x,y) location.  The image background color is returned if an error occurs.
2424%  If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2425%
2426%  The format of the GetOneVirtualPixel() method is:
2427%
2428%      MagickBooleanType GetOneVirtualPixel(const Image image,const long x,
2429%        const long y,PixelPacket *pixel,ExceptionInfo exception)
2430%
2431%  A description of each parameter follows:
2432%
2433%    o image: the image.
2434%
2435%    o x,y:  These values define the location of the pixel to return.
2436%
2437%    o pixel: return a pixel at the specified (x,y) location.
2438%
2439%    o exception: return any errors or warnings in this structure.
2440%
2441*/
2442MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2443  const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
2444{
2445  GetOneVirtualPixelFromHandler
2446    get_one_virtual_pixel_from_handler;
2447
2448  CacheInfo
2449    *cache_info;
2450
2451  MagickBooleanType
2452    status;
2453
2454  assert(image != (const Image *) NULL);
2455  assert(image->signature == MagickSignature);
2456  assert(image->cache != (Cache) NULL);
2457  cache_info=(CacheInfo *) image->cache;
2458  assert(cache_info->signature == MagickSignature);
2459  *pixel=image->background_color;
2460  get_one_virtual_pixel_from_handler=
2461    cache_info->methods.get_one_virtual_pixel_from_handler;
2462  if (get_one_virtual_pixel_from_handler ==
2463      (GetOneVirtualPixelFromHandler) NULL)
2464    return(MagickFalse);
2465  status=get_one_virtual_pixel_from_handler(image,GetPixelCacheVirtualMethod(
2466    image),x,y,pixel,exception);
2467  return(status);
2468}
2469
2470/*
2471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2472%                                                                             %
2473%                                                                             %
2474%                                                                             %
2475+   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                     %
2476%                                                                             %
2477%                                                                             %
2478%                                                                             %
2479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2480%
2481%  GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2482%  specified (x,y) location.  The image background color is returned if an
2483%  error occurs.
2484%
2485%  The format of the GetOneVirtualPixelFromCache() method is:
2486%
2487%      MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2488%        const VirtualPixelPacket method,const long x,const long y,
2489%        PixelPacket *pixel,ExceptionInfo *exception)
2490%
2491%  A description of each parameter follows:
2492%
2493%    o image: the image.
2494%
2495%    o virtual_pixel_method: the virtual pixel method.
2496%
2497%    o x,y:  These values define the location of the pixel to return.
2498%
2499%    o pixel: return a pixel at the specified (x,y) location.
2500%
2501%    o exception: return any errors or warnings in this structure.
2502%
2503*/
2504static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2505  const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
2506  PixelPacket *pixel,ExceptionInfo *exception)
2507{
2508  const PixelPacket
2509    *pixels;
2510
2511  *pixel=image->background_color;
2512  pixels=GetVirtualPixelCache(image,virtual_pixel_method,x,y,1UL,1UL,exception);
2513  if (pixels == (const PixelPacket *) NULL)
2514    return(MagickFalse);
2515  *pixel=(*pixels);
2516  return(MagickTrue);
2517}
2518
2519/*
2520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2521%                                                                             %
2522%                                                                             %
2523%                                                                             %
2524+   G e t P i x e l C a c h e C o l o r s p a c e                             %
2525%                                                                             %
2526%                                                                             %
2527%                                                                             %
2528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2529%
2530%  GetPixelCacheColorspace() returns the class type of the pixel cache.
2531%
2532%  The format of the GetPixelCacheColorspace() method is:
2533%
2534%      Colorspace GetPixelCacheColorspace(Cache cache)
2535%
2536%  A description of each parameter follows:
2537%
2538%    o cache: the pixel cache.
2539%
2540*/
2541MagickExport ColorspaceType GetPixelCacheColorspace(const Cache cache)
2542{
2543  CacheInfo
2544    *cache_info;
2545
2546  assert(cache != (Cache) NULL);
2547  cache_info=(CacheInfo *) cache;
2548  assert(cache_info->signature == MagickSignature);
2549  if (cache_info->debug != MagickFalse)
2550    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2551      cache_info->filename);
2552  return(cache_info->colorspace);
2553}
2554
2555/*
2556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2557%                                                                             %
2558%                                                                             %
2559%                                                                             %
2560+   G e t P i x e l C a c h e M e t h o d s                                   %
2561%                                                                             %
2562%                                                                             %
2563%                                                                             %
2564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2565%
2566%  GetPixelCacheMethods() initializes the CacheMethods structure.
2567%
2568%  The format of the GetPixelCacheMethods() method is:
2569%
2570%      void GetPixelCacheMethods(CacheMethods *cache_methods)
2571%
2572%  A description of each parameter follows:
2573%
2574%    o cache_methods: Specifies a pointer to a CacheMethods structure.
2575%
2576*/
2577MagickExport void GetPixelCacheMethods(CacheMethods *cache_methods)
2578{
2579  assert(cache_methods != (CacheMethods *) NULL);
2580  (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2581  cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2582  cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2583  cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2584  cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2585  cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2586  cache_methods->get_authentic_indexes_from_handler=
2587    GetAuthenticIndexesFromCache;
2588  cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2589  cache_methods->get_one_authentic_pixel_from_handler=
2590    GetOneAuthenticPixelFromCache;
2591  cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2592  cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2593  cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2594}
2595
2596/*
2597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2598%                                                                             %
2599%                                                                             %
2600%                                                                             %
2601+   G e t P i x e l C a c h e N e x u s E x t e n t                           %
2602%                                                                             %
2603%                                                                             %
2604%                                                                             %
2605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2606%
2607%  GetPixelCacheNexusExtent() returns the extent of the pixels associated with
2608%  the last call to SetPixelCacheNexusPixels() or GetPixelCacheNexusPixels().
2609%
2610%  The format of the GetPixelCacheNexusExtent() method is:
2611%
2612%      MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2613%        NexusInfo *nexus_info)
2614%
2615%  A description of each parameter follows:
2616%
2617%    o nexus_info: the nexus info.
2618%
2619*/
2620MagickExport MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2621  NexusInfo *nexus_info)
2622{
2623  CacheInfo
2624    *cache_info;
2625
2626  MagickSizeType
2627    extent;
2628
2629  if (cache == (Cache) NULL)
2630    return(0);
2631  cache_info=(CacheInfo *) cache;
2632  assert(cache_info->signature == MagickSignature);
2633  extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2634  if (extent == 0)
2635    return((MagickSizeType) cache_info->columns*cache_info->rows);
2636  return(extent);
2637}
2638
2639/*
2640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2641%                                                                             %
2642%                                                                             %
2643%                                                                             %
2644+   G e t P i x e l C a c h e N e x u s I n d e x e s                         %
2645%                                                                             %
2646%                                                                             %
2647%                                                                             %
2648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2649%
2650%  GetPixelCacheNexusIndexes() returns the indexes associated with the
2651%  specified cache nexus.
2652%
2653%  The format of the GetPixelCacheNexusIndexes() method is:
2654%
2655%      IndexPacket *GetPixelCacheNexusIndexes(const Cache cache,
2656%        NexusInfo *nexus_info)
2657%
2658%  A description of each parameter follows:
2659%
2660%    o cache: the pixel cache.
2661%
2662%    o nexus_info: the cache nexus to return the colormap indexes.
2663%
2664*/
2665MagickExport IndexPacket *GetPixelCacheNexusIndexes(const Cache cache,
2666  NexusInfo *nexus_info)
2667{
2668  CacheInfo
2669    *cache_info;
2670
2671  if (cache == (Cache) NULL)
2672    return((IndexPacket *) NULL);
2673  cache_info=(CacheInfo *) cache;
2674  assert(cache_info->signature == MagickSignature);
2675  if (cache_info->storage_class == UndefinedClass)
2676    return((IndexPacket *) NULL);
2677  return(nexus_info->indexes);
2678}
2679
2680/*
2681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2682%                                                                             %
2683%                                                                             %
2684%                                                                             %
2685+   G e t P i x e l C a c h e N e x u s P i x e l s                           %
2686%                                                                             %
2687%                                                                             %
2688%                                                                             %
2689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2690%
2691%  GetPixelCacheNexusPixels() returns the pixels associated with the specified
2692%  cache nexus.
2693%
2694%  The format of the GetPixelCacheNexusPixels() method is:
2695%
2696%      PixelPacket *GetPixelCacheNexusPixels(const Cache cache,
2697%        NexusInfo *nexus_info)
2698%
2699%  A description of each parameter follows:
2700%
2701%    o cache: the pixel cache.
2702%
2703%    o nexus_info: the cache nexus to return the pixels.
2704%
2705*/
2706MagickExport PixelPacket *GetPixelCacheNexusPixels(const Cache cache,
2707  NexusInfo *nexus_info)
2708{
2709  CacheInfo
2710    *cache_info;
2711
2712  if (cache == (Cache) NULL)
2713    return((PixelPacket *) NULL);
2714  cache_info=(CacheInfo *) cache;
2715  assert(cache_info->signature == MagickSignature);
2716  if (cache_info->debug != MagickFalse)
2717    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2718      cache_info->filename);
2719  if (cache_info->storage_class == UndefinedClass)
2720    return((PixelPacket *) NULL);
2721  return(nexus_info->pixels);
2722}
2723
2724/*
2725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2726%                                                                             %
2727%                                                                             %
2728%                                                                             %
2729+   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                         %
2730%                                                                             %
2731%                                                                             %
2732%                                                                             %
2733%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2734%
2735%  GetPixelCacheStorageClass() returns the class type of the pixel cache.
2736%
2737%  The format of the GetPixelCacheStorageClass() method is:
2738%
2739%      ClassType GetPixelCacheStorageClass(Cache cache)
2740%
2741%  A description of each parameter follows:
2742%
2743%    o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2744%
2745%    o cache: the pixel cache.
2746%
2747*/
2748MagickExport ClassType GetPixelCacheStorageClass(const Cache cache)
2749{
2750  CacheInfo
2751    *cache_info;
2752
2753  assert(cache != (Cache) NULL);
2754  cache_info=(CacheInfo *) cache;
2755  assert(cache_info->signature == MagickSignature);
2756  if (cache_info->debug != MagickFalse)
2757    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2758      cache_info->filename);
2759  return(cache_info->storage_class);
2760}
2761
2762/*
2763%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2764%                                                                             %
2765%                                                                             %
2766%                                                                             %
2767+   G e t P i x e l C a c h e T i l e S i z e                                 %
2768%                                                                             %
2769%                                                                             %
2770%                                                                             %
2771%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2772%
2773%  GetPixelCacheTileSize() returns the pixel cache tile size.
2774%
2775%  The format of the GetPixelCacheTileSize() method is:
2776%
2777%      void GetPixelCacheTileSize(const Image *image,unsigned long *width,
2778%        unsigned long *height)
2779%
2780%  A description of each parameter follows:
2781%
2782%    o image: the image.
2783%
2784%    o width: the optimize cache tile width in pixels.
2785%
2786%    o height: the optimize cache tile height in pixels.
2787%
2788*/
2789MagickExport void GetPixelCacheTileSize(const Image *image,unsigned long *width,
2790  unsigned long *height)
2791{
2792  CacheInfo
2793    *cache_info;
2794
2795  assert(image != (Image *) NULL);
2796  assert(image->signature == MagickSignature);
2797  if (image->debug != MagickFalse)
2798    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2799  assert(image->cache != (Cache) NULL);
2800  cache_info=(CacheInfo *) image->cache;
2801  assert(cache_info->signature == MagickSignature);
2802  *width=2048UL/sizeof(PixelPacket);
2803  if (GetPixelCacheType(image) == DiskCache)
2804    *width=8192UL/sizeof(PixelPacket);
2805  *height=(*width);
2806}
2807
2808/*
2809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2810%                                                                             %
2811%                                                                             %
2812%                                                                             %
2813+   G e t P i x e l C a c h e T y p e                                         %
2814%                                                                             %
2815%                                                                             %
2816%                                                                             %
2817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2818%
2819%  GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2820%
2821%  The format of the GetPixelCacheType() method is:
2822%
2823%      CacheType GetPixelCacheType(const Image *image)
2824%
2825%  A description of each parameter follows:
2826%
2827%    o image: the image.
2828%
2829*/
2830MagickExport CacheType GetPixelCacheType(const Image *image)
2831{
2832  CacheInfo
2833    *cache_info;
2834
2835  assert(image != (Image *) NULL);
2836  assert(image->signature == MagickSignature);
2837  if (image->debug != MagickFalse)
2838    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2839  assert(image->cache != (Cache) NULL);
2840  cache_info=(CacheInfo *) image->cache;
2841  assert(cache_info->signature == MagickSignature);
2842  return(cache_info->type);
2843}
2844
2845/*
2846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2847%                                                                             %
2848%                                                                             %
2849%                                                                             %
2850+   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                       %
2851%                                                                             %
2852%                                                                             %
2853%                                                                             %
2854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2855%
2856%  GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2857%  pixel cache.  A virtual pixel is any pixel access that is outside the
2858%  boundaries of the image cache.
2859%
2860%  The format of the GetPixelCacheVirtualMethod() method is:
2861%
2862%      VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2863%
2864%  A description of each parameter follows:
2865%
2866%    o image: the image.
2867%
2868*/
2869MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2870{
2871  CacheInfo
2872    *cache_info;
2873
2874  assert(image != (Image *) NULL);
2875  assert(image->signature == MagickSignature);
2876  if (image->debug != MagickFalse)
2877    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2878  assert(image->cache != (Cache) NULL);
2879  cache_info=(CacheInfo *) image->cache;
2880  assert(cache_info->signature == MagickSignature);
2881  return(cache_info->virtual_pixel_method);
2882}
2883
2884/*
2885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2886%                                                                             %
2887%                                                                             %
2888%                                                                             %
2889+   G e t V i r t u a l I n d e x e s F r o m C a c h e                       %
2890%                                                                             %
2891%                                                                             %
2892%                                                                             %
2893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894%
2895%  GetVirtualIndexesFromCache() returns the indexes associated with the last
2896%  call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2897%
2898%  The format of the GetVirtualIndexesFromCache() method is:
2899%
2900%      IndexPacket *GetVirtualIndexesFromCache(const Image *image)
2901%
2902%  A description of each parameter follows:
2903%
2904%    o image: the image.
2905%
2906*/
2907static const IndexPacket *GetVirtualIndexesFromCache(const Image *image)
2908{
2909  CacheInfo
2910    *cache_info;
2911
2912  const IndexPacket
2913    *indexes;
2914
2915  long
2916    id;
2917
2918  if (image->debug != MagickFalse)
2919    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2920  cache_info=(CacheInfo *) image->cache;
2921  id=GetOpenMPThreadId();
2922  assert(id < (long) cache_info->number_threads);
2923  indexes=GetVirtualIndexesFromNexus(image->cache,cache_info->nexus_info[id]);
2924  return(indexes);
2925}
2926
2927/*
2928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2929%                                                                             %
2930%                                                                             %
2931%                                                                             %
2932+   G e t V i r t u a l I n d e x e s F r o m N e x u s                       %
2933%                                                                             %
2934%                                                                             %
2935%                                                                             %
2936%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2937%
2938%  GetVirtualIndexesFromNexus() returns the indexes associated with the
2939%  specified cache nexus.
2940%
2941%  The format of the GetVirtualIndexesFromNexus() method is:
2942%
2943%      const IndexPacket *GetVirtualIndexesFromNexus(const Cache cache,
2944%        NexusInfo *nexus_info)
2945%
2946%  A description of each parameter follows:
2947%
2948%    o cache: the pixel cache.
2949%
2950%    o nexus_info: the cache nexus to return the colormap indexes.
2951%
2952*/
2953MagickExport const IndexPacket *GetVirtualIndexesFromNexus(const Cache cache,
2954  NexusInfo *nexus_info)
2955{
2956  CacheInfo
2957    *cache_info;
2958
2959  if (cache == (Cache) NULL)
2960    return((IndexPacket *) NULL);
2961  cache_info=(CacheInfo *) cache;
2962  assert(cache_info->signature == MagickSignature);
2963  if (cache_info->storage_class == UndefinedClass)
2964    return((IndexPacket *) NULL);
2965  return(nexus_info->indexes);
2966}
2967
2968/*
2969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2970%                                                                             %
2971%                                                                             %
2972%                                                                             %
2973%   G e t V i r t u a l I n d e x Q u e u e                                   %
2974%                                                                             %
2975%                                                                             %
2976%                                                                             %
2977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2978%
2979%  GetVirtualIndexQueue() returns the virtual black channel or the
2980%  colormap indexes associated with the last call to QueueAuthenticPixels() or
2981%  GetVirtualPixels().  NULL is returned if the black channel or colormap
2982%  indexes are not available.
2983%
2984%  The format of the GetVirtualIndexQueue() method is:
2985%
2986%      const IndexPacket *GetVirtualIndexQueue(const Image *image)
2987%
2988%  A description of each parameter follows:
2989%
2990%    o image: the image.
2991%
2992*/
2993MagickExport const IndexPacket *GetVirtualIndexQueue(const Image *image)
2994{
2995  CacheInfo
2996    *cache_info;
2997
2998  assert(image != (const Image *) NULL);
2999  assert(image->signature == MagickSignature);
3000  if (image->debug != MagickFalse)
3001    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3002  assert(image->cache != (Cache) NULL);
3003  cache_info=(CacheInfo *) image->cache;
3004  assert(cache_info->signature == MagickSignature);
3005  if (cache_info->methods.get_virtual_indexes_from_handler ==
3006      (GetVirtualIndexesFromHandler) NULL)
3007    return((IndexPacket *) NULL);
3008  return(cache_info->methods.get_virtual_indexes_from_handler(image));
3009}
3010
3011/*
3012%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3013%                                                                             %
3014%                                                                             %
3015%                                                                             %
3016+   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                         %
3017%                                                                             %
3018%                                                                             %
3019%                                                                             %
3020%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3021%
3022%  GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
3023%  pixel cache as defined by the geometry parameters.   A pointer to the pixels
3024%  is returned if the pixels are transferred, otherwise a NULL is returned.
3025%
3026%  The format of the GetVirtualPixelsFromNexus() method is:
3027%
3028%      PixelPacket *GetVirtualPixelsFromNexus(const Image *image,
3029%        const VirtualPixelMethod method,const long x,const long y,
3030%        const unsigned long columns,const unsigned long rows,
3031%        NexusInfo *nexus_info,ExceptionInfo *exception)
3032%
3033%  A description of each parameter follows:
3034%
3035%    o image: the image.
3036%
3037%    o virtual_pixel_method: the virtual pixel method.
3038%
3039%    o x,y,columns,rows:  These values define the perimeter of a region of
3040%      pixels.
3041%
3042%    o nexus_info: the cache nexus to acquire.
3043%
3044%    o exception: return any errors or warnings in this structure.
3045%
3046*/
3047
3048static long
3049  DitherMatrix[64] =
3050  {
3051     0,  48,  12,  60,   3,  51,  15,  63,
3052    32,  16,  44,  28,  35,  19,  47,  31,
3053     8,  56,   4,  52,  11,  59,   7,  55,
3054    40,  24,  36,  20,  43,  27,  39,  23,
3055     2,  50,  14,  62,   1,  49,  13,  61,
3056    34,  18,  46,  30,  33,  17,  45,  29,
3057    10,  58,   6,  54,   9,  57,   5,  53,
3058    42,  26,  38,  22,  41,  25,  37,  21
3059  };
3060
3061static inline long DitherX(const unsigned long columns,const long x)
3062{
3063  long
3064    index;
3065
3066  index=x+DitherMatrix[x & 0x07]-32L;
3067  if (index < 0L)
3068    return(0L);
3069  if (index >= (long) columns)
3070    return((long) columns-1L);
3071  return(index);
3072}
3073
3074static inline long DitherY(const unsigned long rows,const long y)
3075{
3076  long
3077    index;
3078
3079  index=y+DitherMatrix[y & 0x07]-32L;
3080  if (index < 0L)
3081    return(0L);
3082  if (index >= (long) rows)
3083    return((long) rows-1L);
3084  return(index);
3085}
3086
3087static inline long EdgeX(const unsigned long columns,const long x)
3088{
3089  if (x < 0L)
3090    return(0L);
3091  if (x >= (long) columns)
3092    return((long) columns-1L);
3093  return(x);
3094}
3095
3096static inline long EdgeY(const unsigned long rows,const long y)
3097{
3098  if (y < 0L)
3099    return(0L);
3100  if (y >= (long) rows)
3101    return((long) rows-1L);
3102  return(y);
3103}
3104
3105static inline long RandomX(const unsigned long columns,RandomInfo *random_info)
3106{
3107  return((long) (columns*GetPseudoRandomValue(random_info)));
3108}
3109
3110static inline long RandomY(const unsigned long rows,RandomInfo *random_info)
3111{
3112  return((long) (rows*GetPseudoRandomValue(random_info)));
3113}
3114
3115/*
3116  VirtualPixelModulo() computes the remainder of dividing offset by extent.  It
3117  returns not only the quotient (tile the offset falls in) but also the positive
3118  remainer within that tile such that 0 <= remainder < extent.  This method is
3119  essentially a ldiv() using a floored modulo division rather than the normal
3120  default truncated modulo division.
3121*/
3122static inline MagickModulo VirtualPixelModulo(const long offset,
3123  const unsigned long extent)
3124{
3125  MagickModulo
3126    modulo;
3127
3128  modulo.quotient=offset/(long) extent;
3129  if (offset < 0L)
3130    modulo.quotient--;
3131  modulo.remainder=offset-modulo.quotient*(long) extent;
3132  return(modulo);
3133}
3134
3135MagickExport const PixelPacket *GetVirtualPixelsFromNexus(const Image *image,
3136  const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
3137  const unsigned long columns,const unsigned long rows,NexusInfo *nexus_info,
3138  ExceptionInfo *exception)
3139{
3140  CacheInfo
3141    *cache_info;
3142
3143  MagickOffsetType
3144    offset;
3145
3146  MagickSizeType
3147    length,
3148    number_pixels;
3149
3150  NexusInfo
3151    **virtual_nexus;
3152
3153  PixelPacket
3154    *pixels,
3155    virtual_pixel;
3156
3157  RectangleInfo
3158    region;
3159
3160  register const IndexPacket
3161    *__restrict nexus_indexes;
3162
3163  register const PixelPacket
3164    *__restrict p;
3165
3166  register IndexPacket
3167    *__restrict indexes;
3168
3169  register long
3170    u,
3171    v;
3172
3173  register PixelPacket
3174    *__restrict q;
3175
3176  /*
3177    Acquire pixels.
3178  */
3179  if (image->debug != MagickFalse)
3180    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3181  cache_info=(CacheInfo *) image->cache;
3182  if (cache_info->type == UndefinedCache)
3183    return((const PixelPacket *) NULL);
3184  region.x=x;
3185  region.y=y;
3186  region.width=columns;
3187  region.height=rows;
3188  pixels=SetPixelCacheNexusPixels(image,&region,nexus_info,exception);
3189  if (pixels == (PixelPacket *) NULL)
3190    return((const PixelPacket *) NULL);
3191  offset=(MagickOffsetType) region.y*cache_info->columns+region.x;
3192  length=(MagickSizeType) (region.height-1)*cache_info->columns+region.width-1;
3193  number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3194  if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3195    if ((x >= 0) && ((long) (x+columns) <= (long) cache_info->columns) &&
3196        (y >= 0) && ((long) (y+rows) <= (long) cache_info->rows))
3197      {
3198        MagickBooleanType
3199          status;
3200
3201        /*
3202          Pixel request is inside cache extents.
3203        */
3204        if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
3205          return(pixels);
3206        status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3207        if (status == MagickFalse)
3208          return((const PixelPacket *) NULL);
3209        if ((cache_info->storage_class == PseudoClass) ||
3210            (cache_info->colorspace == CMYKColorspace))
3211          {
3212            status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3213            if (status == MagickFalse)
3214              return((const PixelPacket *) NULL);
3215          }
3216        return(pixels);
3217      }
3218  /*
3219    Pixel request is outside cache extents.
3220  */
3221  q=pixels;
3222  indexes=GetPixelCacheNexusIndexes(cache_info,nexus_info);
3223  virtual_nexus=AcquirePixelCacheNexus(1);
3224  if (virtual_nexus == (NexusInfo **) NULL)
3225    {
3226      (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3227        "UnableToGetCacheNexus","`%s'",image->filename);
3228      return((const PixelPacket *) NULL);
3229    }
3230  switch (virtual_pixel_method)
3231  {
3232    case BlackVirtualPixelMethod:
3233    {
3234      virtual_pixel.red=0;
3235      virtual_pixel.green=0;
3236      virtual_pixel.blue=0;
3237      virtual_pixel.opacity=OpaqueOpacity;
3238      break;
3239    }
3240    case GrayVirtualPixelMethod:
3241    {
3242      virtual_pixel.red=(Quantum) QuantumRange/2;
3243      virtual_pixel.green=(Quantum) QuantumRange/2;
3244      virtual_pixel.blue=(Quantum) QuantumRange/2;
3245      virtual_pixel.opacity=(Quantum) OpaqueOpacity;
3246      break;
3247    }
3248    case TransparentVirtualPixelMethod:
3249    {
3250      virtual_pixel.red=(Quantum) 0;
3251      virtual_pixel.green=(Quantum) 0;
3252      virtual_pixel.blue=(Quantum) 0;
3253      virtual_pixel.opacity=(Quantum) TransparentOpacity;
3254      break;
3255    }
3256    case MaskVirtualPixelMethod:
3257    case WhiteVirtualPixelMethod:
3258    {
3259      virtual_pixel.red=(Quantum) QuantumRange;
3260      virtual_pixel.green=(Quantum) QuantumRange;
3261      virtual_pixel.blue=(Quantum) QuantumRange;
3262      virtual_pixel.opacity=OpaqueOpacity;
3263      break;
3264    }
3265    default:
3266    {
3267      virtual_pixel=image->background_color;
3268      break;
3269    }
3270  }
3271  for (v=0; v < (long) rows; v++)
3272  {
3273    for (u=0; u < (long) columns; u+=length)
3274    {
3275      length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3276      if ((((x+u) < 0) || ((x+u) >= (long) cache_info->columns)) ||
3277          (((y+v) < 0) || ((y+v) >= (long) cache_info->rows)) || (length == 0))
3278        {
3279          MagickModulo
3280            x_modulo,
3281            y_modulo;
3282
3283          /*
3284            Transfer a single pixel.
3285          */
3286          length=(MagickSizeType) 1;
3287          switch (virtual_pixel_method)
3288          {
3289            case BackgroundVirtualPixelMethod:
3290            case ConstantVirtualPixelMethod:
3291            case BlackVirtualPixelMethod:
3292            case GrayVirtualPixelMethod:
3293            case TransparentVirtualPixelMethod:
3294            case MaskVirtualPixelMethod:
3295            case WhiteVirtualPixelMethod:
3296            {
3297              p=(&virtual_pixel);
3298              break;
3299            }
3300            case EdgeVirtualPixelMethod:
3301            default:
3302            {
3303              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3304                EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
3305                1UL,1UL,virtual_nexus[0],exception);
3306              break;
3307            }
3308            case RandomVirtualPixelMethod:
3309            {
3310              if (cache_info->random_info == (RandomInfo *) NULL)
3311                cache_info->random_info=AcquireRandomInfo();
3312              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3313                RandomX(cache_info->columns,cache_info->random_info),
3314                RandomY(cache_info->rows,cache_info->random_info),1UL,1UL,
3315                virtual_nexus[0],exception);
3316              break;
3317            }
3318            case DitherVirtualPixelMethod:
3319            {
3320              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3321                DitherX(cache_info->columns,x+u),DitherY(cache_info->rows,y+v),
3322                1UL,1UL,virtual_nexus[0],exception);
3323              break;
3324            }
3325            case TileVirtualPixelMethod:
3326            {
3327              x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3328              y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3329              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3330                x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3331                exception);
3332              break;
3333            }
3334            case MirrorVirtualPixelMethod:
3335            {
3336              x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3337              if ((x_modulo.quotient & 0x01) == 1L)
3338                x_modulo.remainder=(long) cache_info->columns-
3339                  x_modulo.remainder-1L;
3340              y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3341              if ((y_modulo.quotient & 0x01) == 1L)
3342                y_modulo.remainder=(long) cache_info->rows-
3343                  y_modulo.remainder-1L;
3344              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3345                x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3346                exception);
3347              break;
3348            }
3349            case CheckerTileVirtualPixelMethod:
3350            {
3351              x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3352              y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3353              if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3354                {
3355                  p=(&virtual_pixel);
3356                  break;
3357                }
3358              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3359                x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3360                exception);
3361              break;
3362            }
3363            case HorizontalTileVirtualPixelMethod:
3364            {
3365              if (((y+v) < 0) || ((y+v) >= (long) cache_info->rows))
3366                {
3367                  p=(&virtual_pixel);
3368                  break;
3369                }
3370              x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3371              y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3372              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3373                x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3374                exception);
3375              break;
3376            }
3377            case VerticalTileVirtualPixelMethod:
3378            {
3379              if (((x+u) < 0) || ((x+u) >= (long) cache_info->columns))
3380                {
3381                  p=(&virtual_pixel);
3382                  break;
3383                }
3384              x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3385              y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3386              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3387                x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3388                exception);
3389              break;
3390            }
3391            case HorizontalTileEdgeVirtualPixelMethod:
3392            {
3393              x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3394              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3395                x_modulo.remainder,EdgeY(cache_info->rows,y+v),1UL,1UL,
3396                virtual_nexus[0],exception);
3397              break;
3398            }
3399            case VerticalTileEdgeVirtualPixelMethod:
3400            {
3401              y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3402              p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3403                EdgeX(cache_info->columns,x+u),y_modulo.remainder,1UL,1UL,
3404                virtual_nexus[0],exception);
3405              break;
3406            }
3407          }
3408          if (p == (const PixelPacket *) NULL)
3409            break;
3410          *q++=(*p);
3411          if (indexes != (IndexPacket *) NULL)
3412            {
3413              nexus_indexes=GetVirtualIndexesFromNexus(cache_info,
3414                virtual_nexus[0]);
3415              if (nexus_indexes != (const IndexPacket *) NULL)
3416                *indexes++=(*nexus_indexes);
3417            }
3418          continue;
3419        }
3420      /*
3421        Transfer a run of pixels.
3422      */
3423      p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,
3424        (unsigned long) length,1UL,virtual_nexus[0],exception);
3425      if (p == (const PixelPacket *) NULL)
3426        break;
3427      (void) CopyMagickMemory(q,p,(size_t) length*sizeof(*p));
3428      q+=length;
3429      if (indexes != (IndexPacket *) NULL)
3430        {
3431          nexus_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus[0]);
3432          if (nexus_indexes != (const IndexPacket *) NULL)
3433            {
3434              (void) CopyMagickMemory(indexes,nexus_indexes,(size_t) length*
3435                sizeof(*nexus_indexes));
3436              indexes+=length;
3437            }
3438        }
3439    }
3440  }
3441  virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3442  return(pixels);
3443}
3444
3445/*
3446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3447%                                                                             %
3448%                                                                             %
3449%                                                                             %
3450+   G e t V i r t u a l P i x e l C a c h e                                   %
3451%                                                                             %
3452%                                                                             %
3453%                                                                             %
3454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3455%
3456%  GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3457%  cache as defined by the geometry parameters.   A pointer to the pixels
3458%  is returned if the pixels are transferred, otherwise a NULL is returned.
3459%
3460%  The format of the GetVirtualPixelCache() method is:
3461%
3462%      const PixelPacket *GetVirtualPixelCache(const Image *image,
3463%        const VirtualPixelMethod virtual_pixel_method,const long x,
3464%        const long y,const unsigned long columns,const unsigned long rows,
3465%        ExceptionInfo *exception)
3466%
3467%  A description of each parameter follows:
3468%
3469%    o image: the image.
3470%
3471%    o virtual_pixel_method: the virtual pixel method.
3472%
3473%    o x,y,columns,rows:  These values define the perimeter of a region of
3474%      pixels.
3475%
3476%    o exception: return any errors or warnings in this structure.
3477%
3478*/
3479static const PixelPacket *GetVirtualPixelCache(const Image *image,
3480  const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
3481  const unsigned long columns,const unsigned long rows,ExceptionInfo *exception)
3482{
3483  CacheInfo
3484   *cache_info;
3485
3486  const PixelPacket
3487    *pixels;
3488
3489  long
3490    id;
3491
3492  if (image->debug != MagickFalse)
3493    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3494  cache_info=(CacheInfo *) image->cache;
3495  id=GetOpenMPThreadId();
3496  assert(id < (long) cache_info->number_threads);
3497  pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3498    cache_info->nexus_info[id],exception);
3499  return(pixels);
3500}
3501
3502/*
3503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3504%                                                                             %
3505%                                                                             %
3506%                                                                             %
3507%   G e t V i r t u a l P i x e l Q u e u e                                   %
3508%                                                                             %
3509%                                                                             %
3510%                                                                             %
3511%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3512%
3513%  GetVirtualPixelQueue() returns the virtual pixels associated with the
3514%  last call to QueueAuthenticPixels() or GetVirtualPixels().
3515%
3516%  The format of the GetVirtualPixelQueue() method is:
3517%
3518%      const PixelPacket *GetVirtualPixelQueue(const Image image)
3519%
3520%  A description of each parameter follows:
3521%
3522%    o image: the image.
3523%
3524*/
3525MagickExport const PixelPacket *GetVirtualPixelQueue(const Image *image)
3526{
3527  CacheInfo
3528    *cache_info;
3529
3530  assert(image != (const Image *) NULL);
3531  assert(image->signature == MagickSignature);
3532  if (image->debug != MagickFalse)
3533    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3534  assert(image->cache != (Cache) NULL);
3535  cache_info=(CacheInfo *) image->cache;
3536  assert(cache_info->signature == MagickSignature);
3537  if (cache_info->methods.get_virtual_pixels_handler ==
3538      (GetVirtualPixelsHandler) NULL)
3539    return((PixelPacket *) NULL);
3540  return(cache_info->methods.get_virtual_pixels_handler(image));
3541}
3542
3543/*
3544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3545%                                                                             %
3546%                                                                             %
3547%                                                                             %
3548%   G e t V i r t u a l P i x e l s                                           %
3549%                                                                             %
3550%                                                                             %
3551%                                                                             %
3552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3553%
3554%  GetVirtualPixels() returns an immutable pixel region. If the
3555%  region is successfully accessed, a pointer to it is returned, otherwise
3556%  NULL is returned. The returned pointer may point to a temporary working
3557%  copy of the pixels or it may point to the original pixels in memory.
3558%  Performance is maximized if the selected region is part of one row, or one
3559%  or more full rows, since there is opportunity to access the pixels in-place
3560%  (without a copy) if the image is in RAM, or in a memory-mapped file.  The
3561%  returned pointer should *never* be deallocated by the user.
3562%
3563%  Pixels accessed via the returned pointer represent a simple array of type
3564%  PixelPacket.  If the image type is CMYK or the storage class is PseudoClass,
3565%  call GetAuthenticIndexQueue() after invoking GetAuthenticPixels() to access
3566%  the black color component or to obtain the colormap indexes (of type
3567%  IndexPacket) corresponding to the region.
3568%
3569%  If you plan to modify the pixels, use GetAuthenticPixels() instead.
3570%
3571%  Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3572%  safe.  In a threaded environment, use GetCacheViewVirtualPixels() or
3573%  GetCacheViewAuthenticPixels() instead.
3574%
3575%  The format of the GetVirtualPixels() method is:
3576%
3577%      const PixelPacket *GetVirtualPixels(const Image *image,const long x,
3578%        const long y,const unsigned long columns,const unsigned long rows,
3579%        ExceptionInfo *exception)
3580%
3581%  A description of each parameter follows:
3582%
3583%    o image: the image.
3584%
3585%    o x,y,columns,rows:  These values define the perimeter of a region of
3586%      pixels.
3587%
3588%    o exception: return any errors or warnings in this structure.
3589%
3590*/
3591MagickExport const PixelPacket *GetVirtualPixels(const Image *image,
3592  const long x,const long y,const unsigned long columns,
3593  const unsigned long rows,ExceptionInfo *exception)
3594{
3595  CacheInfo
3596    *cache_info;
3597
3598  const PixelPacket
3599    *pixels;
3600
3601  assert(image != (const Image *) NULL);
3602  assert(image->signature == MagickSignature);
3603  if (image->debug != MagickFalse)
3604    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3605  assert(image->cache != (Cache) NULL);
3606  cache_info=(CacheInfo *) image->cache;
3607  assert(cache_info->signature == MagickSignature);
3608  if (cache_info->methods.get_virtual_pixel_handler ==
3609      (GetVirtualPixelHandler) NULL)
3610    return((const PixelPacket *) NULL);
3611  pixels=cache_info->methods.get_virtual_pixel_handler(image,
3612    GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception);
3613  return(pixels);
3614}
3615
3616/*
3617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3618%                                                                             %
3619%                                                                             %
3620%                                                                             %
3621+   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                         %
3622%                                                                             %
3623%                                                                             %
3624%                                                                             %
3625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3626%
3627%  GetVirtualPixelsCache() returns the pixels associated with the last call
3628%  to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3629%
3630%  The format of the GetVirtualPixelsCache() method is:
3631%
3632%      PixelPacket *GetVirtualPixelsCache(const Image *image)
3633%
3634%  A description of each parameter follows:
3635%
3636%    o image: the image.
3637%
3638*/
3639static const PixelPacket *GetVirtualPixelsCache(const Image *image)
3640{
3641  CacheInfo
3642    *cache_info;
3643
3644  const PixelPacket
3645    *pixels;
3646
3647  long
3648    id;
3649
3650  if (image->debug != MagickFalse)
3651    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3652  cache_info=(CacheInfo *) image->cache;
3653  id=GetOpenMPThreadId();
3654  assert(id < (long) cache_info->number_threads);
3655  pixels=GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]);
3656  return(pixels);
3657}
3658
3659/*
3660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3661%                                                                             %
3662%                                                                             %
3663%                                                                             %
3664+   G e t V i r t u a l P i x e l s N e x u s                                 %
3665%                                                                             %
3666%                                                                             %
3667%                                                                             %
3668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3669%
3670%  GetVirtualPixelsNexus() returns the pixels associated with the specified
3671%  cache nexus.
3672%
3673%  The format of the GetVirtualPixelsNexus() method is:
3674%
3675%      const IndexPacket *GetVirtualPixelsNexus(const Cache cache,
3676%        NexusInfo *nexus_info)
3677%
3678%  A description of each parameter follows:
3679%
3680%    o cache: the pixel cache.
3681%
3682%    o nexus_info: the cache nexus to return the colormap pixels.
3683%
3684*/
3685MagickExport const PixelPacket *GetVirtualPixelsNexus(const Cache cache,
3686  NexusInfo *nexus_info)
3687{
3688  CacheInfo
3689    *cache_info;
3690
3691  if (cache == (Cache) NULL)
3692    return((PixelPacket *) NULL);
3693  cache_info=(CacheInfo *) cache;
3694  assert(cache_info->signature == MagickSignature);
3695  if (cache_info->storage_class == UndefinedClass)
3696    return((PixelPacket *) NULL);
3697  return((const PixelPacket *) nexus_info->pixels);
3698}
3699
3700/*
3701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3702%                                                                             %
3703%                                                                             %
3704%                                                                             %
3705+   M a s k P i x e l C a c h e N e x u s                                     %
3706%                                                                             %
3707%                                                                             %
3708%                                                                             %
3709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3710%
3711%  MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3712%  The method returns MagickTrue if the pixel region is masked, otherwise
3713%  MagickFalse.
3714%
3715%  The format of the MaskPixelCacheNexus() method is:
3716%
3717%      MagickBooleanType MaskPixelCacheNexus(Image *image,
3718%        NexusInfo *nexus_info,ExceptionInfo *exception)
3719%
3720%  A description of each parameter follows:
3721%
3722%    o image: the image.
3723%
3724%    o nexus_info: the cache nexus to clip.
3725%
3726%    o exception: return any errors or warnings in this structure.
3727%
3728*/
3729
3730static inline void MagickPixelCompositeMask(const MagickPixelPacket *p,
3731  const MagickRealType alpha,const MagickPixelPacket *q,
3732  const MagickRealType beta,MagickPixelPacket *composite)
3733{
3734  MagickRealType
3735    gamma;
3736
3737  if (alpha == TransparentOpacity)
3738    {
3739      *composite=(*q);
3740      return;
3741    }
3742  gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3743  gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3744  composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3745  composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3746  composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3747  if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3748    composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3749}
3750
3751static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3752  ExceptionInfo *exception)
3753{
3754  CacheInfo
3755    *cache_info;
3756
3757  MagickPixelPacket
3758    alpha,
3759    beta;
3760
3761  MagickSizeType
3762    number_pixels;
3763
3764  NexusInfo
3765    **clip_nexus,
3766    **image_nexus;
3767
3768  register const PixelPacket
3769    *__restrict r;
3770
3771  register IndexPacket
3772    *__restrict nexus_indexes,
3773    *__restrict indexes;
3774
3775  register long
3776    i;
3777
3778  register PixelPacket
3779    *__restrict p,
3780    *__restrict q;
3781
3782  /*
3783    Apply clip mask.
3784  */
3785  if (image->debug != MagickFalse)
3786    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3787  if (image->mask == (Image *) NULL)
3788    return(MagickFalse);
3789  cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
3790  if (cache_info == (Cache) NULL)
3791    return(MagickFalse);
3792  image_nexus=AcquirePixelCacheNexus(1);
3793  clip_nexus=AcquirePixelCacheNexus(1);
3794  if ((image_nexus == (NexusInfo **) NULL) ||
3795      (clip_nexus == (NexusInfo **) NULL))
3796    ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3797  p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3798    nexus_info->region.width,nexus_info->region.height,image_nexus[0],
3799    exception);
3800  indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
3801  q=nexus_info->pixels;
3802  nexus_indexes=nexus_info->indexes;
3803  r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3804    nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3805    nexus_info->region.height,clip_nexus[0],&image->exception);
3806  GetMagickPixelPacket(image,&alpha);
3807  GetMagickPixelPacket(image,&beta);
3808  number_pixels=(MagickSizeType) nexus_info->region.width*
3809    nexus_info->region.height;
3810  for (i=0; i < (long) number_pixels; i++)
3811  {
3812    if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
3813      break;
3814    SetMagickPixelPacket(image,p,indexes+i,&alpha);
3815    SetMagickPixelPacket(image,q,nexus_indexes+i,&beta);
3816    MagickPixelCompositeMask(&beta,(MagickRealType) PixelIntensityToQuantum(r),
3817      &alpha,alpha.opacity,&beta);
3818    q->red=RoundToQuantum(beta.red);
3819    q->green=RoundToQuantum(beta.green);
3820    q->blue=RoundToQuantum(beta.blue);
3821    q->opacity=RoundToQuantum(beta.opacity);
3822    if (cache_info->active_index_channel != MagickFalse)
3823      nexus_indexes[i]=indexes[i];
3824    p++;
3825    q++;
3826    r++;
3827  }
3828  clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3829  image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3830  if (i < (long) number_pixels)
3831    return(MagickFalse);
3832  return(MagickTrue);
3833}
3834
3835/*
3836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3837%                                                                             %
3838%                                                                             %
3839%                                                                             %
3840+   O p e n P i x e l C a c h e                                               %
3841%                                                                             %
3842%                                                                             %
3843%                                                                             %
3844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3845%
3846%  OpenPixelCache() allocates the pixel cache.  This includes defining the cache
3847%  dimensions, allocating space for the image pixels and optionally the
3848%  colormap indexes, and memory mapping the cache if it is disk based.  The
3849%  cache nexus array is initialized as well.
3850%
3851%  The format of the OpenPixelCache() method is:
3852%
3853%      MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3854%        ExceptionInfo *exception)
3855%
3856%  A description of each parameter follows:
3857%
3858%    o image: the image.
3859%
3860%    o mode: ReadMode, WriteMode, or IOMode.
3861%
3862%    o exception: return any errors or warnings in this structure.
3863%
3864*/
3865
3866static inline void AcquirePixelCachePixels(CacheInfo *cache_info)
3867{
3868  cache_info->mapped=MagickFalse;
3869  cache_info->pixels=(PixelPacket *) AcquireMagickMemory((size_t)
3870    cache_info->length);
3871  if (cache_info->pixels == (PixelPacket *) NULL)
3872    {
3873      cache_info->mapped=MagickTrue;
3874      cache_info->pixels=(PixelPacket *) MapBlob(-1,IOMode,0,(size_t)
3875        cache_info->length);
3876    }
3877}
3878
3879static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3880{
3881  CacheInfo
3882    *cache_info;
3883
3884  MagickOffsetType
3885    count,
3886    extent,
3887    offset;
3888
3889  cache_info=(CacheInfo *) image->cache;
3890  if (image->debug != MagickFalse)
3891    {
3892      char
3893        format[MaxTextExtent],
3894        message[MaxTextExtent];
3895
3896      (void) FormatMagickSize(length,format);
3897      (void) FormatMagickString(message,MaxTextExtent,
3898        "extend %s (%s[%d], disk, %s)",cache_info->filename,
3899        cache_info->cache_filename,cache_info->file,format);
3900      (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3901    }
3902  if (length != (MagickSizeType) ((MagickOffsetType) length))
3903    return(MagickFalse);
3904  extent=(MagickOffsetType) MagickSeek(cache_info->file,0,SEEK_END);
3905  if (extent < 0)
3906    return(MagickFalse);
3907  if ((MagickSizeType) extent >= length)
3908    return(MagickTrue);
3909  offset=(MagickOffsetType) length-1;
3910  count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3911  return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3912}
3913
3914static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3915  ExceptionInfo *exception)
3916{
3917  char
3918    format[MaxTextExtent],
3919    message[MaxTextExtent];
3920