root / ImageMagick / branches / ImageMagick-6.3.6 / magick / cache.c

Revision 8289, 175.1 kB (checked in by cristy, 14 months 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%                      ImageMagick Pixel Cache Methods                        %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 1999                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2007 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/utility.h"
64#if defined(HasZLIB)
65#include "zlib.h"
66#endif
67#if defined(HAVE_PTHREAD)
68#include <pthread.h>
69#endif
70#if defined(__WINDOWS__)
71#include <windows.h>
72#endif
73
74/*
75  Define declarations.
76*/
77#define DefaultNumberCacheViews  8UL
78
79/*
80  Typedef declarations.
81*/
82struct _NexusInfo
83{
84  MagickBooleanType
85    available,
86    mapped;
87
88  unsigned long
89    columns,
90    rows;
91
92  long
93    x,
94    y;
95
96  MagickSizeType
97    length;
98
99  PixelPacket
100    *cache,
101    *pixels;
102
103  IndexPacket
104    *indexes;
105};
106
107/*
108  Forward declarations.
109*/
110#if defined(__cplusplus) || defined(c_plusplus)
111extern "C" {
112#endif
113
114static const PixelPacket
115  *AcquirePixelCache(const Image *,const VirtualPixelMethod,const long,
116    const long,const unsigned long,const unsigned long,ExceptionInfo *);
117
118static IndexPacket
119  *GetIndexesFromCache(const Image *);
120
121static MagickBooleanType
122  OpenCache(Image *,const MapMode,ExceptionInfo *),
123  SyncCache(Image *),
124  SyncPixelCache(Image *);
125
126static PixelPacket
127  AcquireOnePixelFromCache(const Image *,const VirtualPixelMethod,const long,
128    const long,ExceptionInfo *),
129  GetOnePixelFromCache(Image *,const long,const long),
130  *GetPixelCache(Image *,const long,const long,const unsigned long,
131    const unsigned long),
132  *GetPixelsFromCache(const Image *),
133  *SetPixelCache(Image *,const long,const long,const unsigned long,
134    const unsigned long);
135
136static void
137  DestroyPixelCache(Image *);
138
139#if defined(__cplusplus) || defined(c_plusplus)
140}
141#endif
142
143/*
144  Forward declarations.
145*/
146static PixelPacket
147  *SetNexus(const Image *,const RectangleInfo *,const unsigned long);
148
149static MagickBooleanType
150  ReadCacheIndexes(CacheInfo *,const unsigned long,ExceptionInfo *),
151  ReadCachePixels(CacheInfo *,const unsigned long,ExceptionInfo *),
152  WriteCacheIndexes(CacheInfo *,const unsigned long,ExceptionInfo *),
153  WriteCachePixels(CacheInfo *,const unsigned long,ExceptionInfo *);
154
155/*
156  Global declarations.
157*/
158static MagickSizeType
159  serial_number = 0;
160
161static SemaphoreInfo
162  *cache_semaphore = (SemaphoreInfo *) NULL;
163
164static SplayTreeInfo
165  *cache_resources = (SplayTreeInfo *) NULL;
166
167/*
168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169%                                                                             %
170%                                                                             %
171%                                                                             %
172+   A c q u i r e C a c h e N e x u s                                         %
173%                                                                             %
174%                                                                             %
175%                                                                             %
176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177%
178%  AcquireCacheNexus() acquires pixels from the in-memory or disk pixel cache
179%  as defined by the geometry parameters.   A pointer to the pixels is
180%  returned if the pixels are transferred, otherwise a NULL is returned.
181%
182%  The format of the AcquireCacheNexus() method is:
183%
184%      PixelPacket *AcquireCacheNexus(const Image *image,
185%        const VirtualPixelMethod method,const long x,const long y,
186%        const unsigned long columns,const unsigned long rows,
187%        const unsigned long nexus,ExceptionInfo *exception)
188%
189%  A description of each parameter follows:
190%
191%    o image: The image.
192%
193%    o virtual_pixel_method: The virtual pixel method.
194%
195%    o x,y,columns,rows:  These values define the perimeter of a region of
196%      pixels.
197%
198%    o nexus: specifies which cache nexus to acquire.
199%
200%    o exception: Return any errors or warnings in this structure.
201%
202*/
203
204static long
205  DitherMatrix[64] =
206  {
207     0,  48,  12,  60,   3,  51,  15,  63,
208    32,  16,  44,  28,  35,  19,  47,  31,
209     8,  56,   4,  52,  11,  59,   7,  55,
210    40,  24,  36,  20,  43,  27,  39,  23,
211     2,  50,  14,  62,   1,  49,  13,  61,
212    34,  18,  46,  30,  33,  17,  45,  29,
213    10,  58,   6,  54,   9,  57,   5,  53,
214    42,  26,  38,  22,  41,  25,  37,  21
215  };
216
217static inline long DitherX(const unsigned long columns,const long x)
218{
219  long
220    index;
221
222  index=x+DitherMatrix[x & 0x07]-32L;
223  if (index < 0L)
224    return(0L);
225  if (index >= (long) columns)
226    return((long) columns-1L);
227  return(index);
228}
229
230static inline long DitherY(const unsigned long rows,const long y)
231{
232  long
233    index;
234
235  index=y+DitherMatrix[y & 0x07]-32L;
236  if (index < 0L)
237    return(0L);
238  if (index >= (long) rows)
239    return((long) rows-1L);
240  return(index);
241}
242
243static inline long EdgeX(const unsigned long columns,const long x)
244{
245  if (x < 0L)
246    return(0L);
247  if (x >= (long) columns)
248    return((long) columns-1L);
249  return(x);
250}
251
252static inline long EdgeY(const unsigned long rows,const long y)
253{
254  if (y < 0L)
255    return(0L);
256  if (y >= (long) rows)
257    return((long) rows-1L);
258  return(y);
259}
260
261static inline MagickSizeType MagickMax(const MagickSizeType x,
262  const MagickSizeType y)
263{
264  if (x > y)
265    return(x);
266  return(y);
267}
268
269static inline MagickSizeType MagickMin(const MagickSizeType x,
270  const MagickSizeType y)
271{
272  if (x < y)
273    return(x);
274  return(y);
275}
276
277
278static inline long RandomX(const unsigned long columns)
279{
280  long
281    x;
282
283  x=(long) (columns*GetRandomValue()+0.5);
284  if (x >= (long) columns)
285    return((long) columns-1L);
286  return(x);
287}
288
289static inline long RandomY(const unsigned long rows)
290{
291  long
292    y;
293
294  y=(long) (rows*GetRandomValue()+0.5);
295  if (y >= (long) rows)
296    return((long) rows-1L);
297  return(y);
298}
299
300static inline long TileX(const unsigned long columns,const long x)
301{
302  if (x < 0L)
303    return((long) columns+((x+1) % (long) columns)-1);
304  if (x >= (long) columns)
305    return(x % (long) columns);
306  return(x);
307}
308
309static inline long TileY(const unsigned long rows,const long y)
310{
311  if (y < 0L)
312    return((long) rows+((y+1) % (long) rows)-1L);
313  if (y >= (long) rows)
314    return(y % (long) rows);
315  return(y);
316}
317
318static inline long MirrorX(const unsigned long columns,const long x)
319{
320  if ((x < 0) || (x >= (long) columns))
321    return((long) columns-TileX(columns,x)-1L);
322  return(x);
323}
324
325static inline long MirrorY(const unsigned long rows,const long y)
326{
327  if ((y < 0) || (y >= (long) rows))
328    return((long) rows-TileX(rows,y)-1L);
329  return(y);
330}
331
332static inline MagickBooleanType IsNexusInCore(const CacheInfo *cache_info,
333  const unsigned long nexus)
334{
335  MagickOffsetType
336    offset;
337
338  register NexusInfo
339    *nexus_info;
340
341  nexus_info=cache_info->nexus_info+nexus;
342  offset=(MagickOffsetType) nexus_info->y*cache_info->columns+nexus_info->x;
343  if (nexus_info->pixels != (cache_info->pixels+offset))
344    return(MagickFalse);
345  return(MagickTrue);
346}
347
348MagickExport const PixelPacket *AcquireCacheNexus(const Image *image,
349  const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
350  const unsigned long columns,const unsigned long rows,
351  const unsigned long nexus,ExceptionInfo *exception)
352{
353  CacheInfo
354    *cache_info;
355
356  IndexPacket
357    *indexes,
358    *nexus_indexes;
359
360  MagickOffsetType
361    offset;
362
363  MagickSizeType
364    length,
365    number_pixels;
366
367  PixelPacket
368    *pixels;
369
370  RectangleInfo
371    region;
372
373  register const PixelPacket
374    *p;
375
376  register long
377    u,
378    v;
379
380  register PixelPacket
381    *q;
382
383  unsigned long
384    image_nexus;
385
386  /*
387    Acquire pixels.
388  */
389  assert(image != (const Image *) NULL);
390  assert(image->signature == MagickSignature);
391  if (image->debug != MagickFalse)
392    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
393  assert(image->cache != (Cache) NULL);
394  cache_info=(CacheInfo *) image->cache;
395  if (cache_info->type == UndefinedCache)
396    return((const PixelPacket *) NULL);
397  region.x=x;
398  region.y=y;
399  region.width=columns;
400  region.height=rows;
401  pixels=SetNexus(image,&region,nexus);
402  offset=(MagickOffsetType) region.y*cache_info->columns+region.x;
403  length=(MagickSizeType) (region.height-1)*cache_info->columns+region.width-1;
404  number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
405  if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
406    if ((x >= 0) && ((long) (x+columns) <= (long) cache_info->columns) &&
407        (y >= 0) && ((long) (y+rows) <= (long) cache_info->rows))
408      {
409        MagickBooleanType
410          status;
411
412        /*
413          Pixel request is inside cache extents.
414        */
415        if (IsNexusInCore(cache_info,nexus) != MagickFalse)
416          return(pixels);
417        status=ReadCachePixels(cache_info,nexus,exception);
418        if ((cache_info->storage_class == PseudoClass) ||
419            (cache_info->colorspace == CMYKColorspace))
420          if (ReadCacheIndexes(cache_info,nexus,exception) == MagickFalse)
421            status=MagickFalse;
422        if (status == MagickFalse)
423          return((const PixelPacket *) NULL);
424        return(pixels);
425      }
426  /*
427    Pixel request is outside cache extents.
428  */
429  indexes=GetNexusIndexes(cache_info,nexus);
430  image_nexus=GetNexus(cache_info);
431  if (image_nexus == 0)
432    {
433      (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
434        "UnableToGetCacheNexus","`%s'",image->filename);
435      return((const PixelPacket *) NULL);
436    }
437  q=pixels;
438  for (v=0; v < (long) rows; v++)
439  {
440    for (u=0; u < (long) columns; u+=length)
441    {
442      length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
443      if ((((x+u) < 0) || ((x+u) >= (long) cache_info->columns)) ||
444          (((y+v) < 0) || ((y+v) >= (long) cache_info->rows)) || (length == 0))
445        {
446          /*
447            Transfer a single pixel.
448          */
449          length=(MagickSizeType) 1;
450          switch (virtual_pixel_method)
451          {
452            case BackgroundVirtualPixelMethod:
453            case ConstantVirtualPixelMethod:
454            {
455              p=AcquireCacheNexus(image,virtual_pixel_method,
456                EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
457                1UL,1UL,image_nexus,exception);
458              cache_info->virtual_pixel=image->background_color;
459              p=(&cache_info->virtual_pixel);
460              break;
461            }
462            case BlackVirtualPixelMethod:
463            {
464              p=AcquireCacheNexus(image,virtual_pixel_method,
465                EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
466                1UL,1UL,image_nexus,exception);
467              cache_info->virtual_pixel.red=0;
468              cache_info->virtual_pixel.green=0;
469              cache_info->virtual_pixel.blue=0;
470              cache_info->virtual_pixel.opacity=OpaqueOpacity;
471              p=(&cache_info->virtual_pixel);
472              break;
473            }
474            case DitherVirtualPixelMethod:
475            {
476              p=AcquireCacheNexus(image,virtual_pixel_method,
477                DitherX(cache_info->columns,x+u),DitherY(cache_info->rows,y+v),
478                1UL,1UL,image_nexus,exception);
479              break;
480            }
481            case EdgeVirtualPixelMethod:
482            default:
483            {
484              p=AcquireCacheNexus(image,virtual_pixel_method,
485                EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
486                1UL,1UL,image_nexus,exception);
487              break;
488            }
489            case GrayVirtualPixelMethod:
490            {
491              p=AcquireCacheNexus(image,virtual_pixel_method,
492                EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
493                1UL,1UL,image_nexus,exception);
494              cache_info->virtual_pixel.red=(Quantum) QuantumRange/2;
495              cache_info->virtual_pixel.green=(Quantum) QuantumRange/2;
496              cache_info->virtual_pixel.blue=(Quantum) QuantumRange/2;
497              cache_info->virtual_pixel.opacity=(Quantum) OpaqueOpacity;
498              p=(&cache_info->virtual_pixel);
499              break;
500            }
501            case MaskVirtualPixelMethod:
502            {
503              p=AcquireCacheNexus(image,virtual_pixel_method,
504                EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
505                1UL,1UL,image_nexus,exception);
506              cache_info->virtual_pixel.red=(Quantum) QuantumRange;
507              cache_info->virtual_pixel.green=(Quantum) QuantumRange;
508              cache_info->virtual_pixel.blue=(Quantum) QuantumRange;
509              cache_info->virtual_pixel.opacity=(Quantum) OpaqueOpacity;
510              p=(&cache_info->virtual_pixel);
511              break;
512            }
513            case MirrorVirtualPixelMethod:
514            {
515              p=AcquireCacheNexus(image,virtual_pixel_method,
516                MirrorX(cache_info->columns,x+u),MirrorY(cache_info->rows,y+v),
517                1UL,1UL,image_nexus,exception);
518              break;
519            }
520            case RandomVirtualPixelMethod:
521            {
522              p=AcquireCacheNexus(image,virtual_pixel_method,
523                RandomX(cache_info->columns),RandomY(cache_info->rows),
524                1UL,1UL,image_nexus,exception);
525              break;
526            }
527            case TileVirtualPixelMethod:
528            {
529              p=AcquireCacheNexus(image,virtual_pixel_method,
530                TileX(cache_info->columns,x+u),TileY(cache_info->rows,y+v),
531                1UL,1UL,image_nexus,exception);
532              break;
533            }
534            case TransparentVirtualPixelMethod:
535            {
536              p=AcquireCacheNexus(image,virtual_pixel_method,
537                EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
538                1UL,1UL,image_nexus,exception);
539              cache_info->virtual_pixel.red=(Quantum) 0;
540              cache_info->virtual_pixel.green=(Quantum) 0;
541              cache_info->virtual_pixel.blue=(Quantum) 0;
542              cache_info->virtual_pixel.opacity=(Quantum) TransparentOpacity;
543              p=(&cache_info->virtual_pixel);
544              break;
545            }
546            case WhiteVirtualPixelMethod:
547            {
548              p=AcquireCacheNexus(image,virtual_pixel_method,
549                EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
550                1UL,1UL,image_nexus,exception);
551              cache_info->virtual_pixel.red=(Quantum) QuantumRange;
552              cache_info->virtual_pixel.green=(Quantum) QuantumRange;
553              cache_info->virtual_pixel.blue=(Quantum) QuantumRange;
554              cache_info->virtual_pixel.opacity=OpaqueOpacity;
555              p=(&cache_info->virtual_pixel);
556              break;
557            }
558          }
559          if (p == (const PixelPacket *) NULL)
560            break;
561          *q++=(*p);
562          if (indexes == (IndexPacket *) NULL)
563            continue;
564          nexus_indexes=GetNexusIndexes(cache_info,image_nexus);
565          if (nexus_indexes == (IndexPacket *) NULL)
566            continue;
567          *indexes++=(*nexus_indexes);
568          continue;
569        }
570      /*
571        Transfer a run of pixels.
572      */
573      p=AcquireCacheNexus(image,virtual_pixel_method,x+u,y+v,(unsigned long)
574        length,1UL,image_nexus,exception);
575      if (p == (const PixelPacket *) NULL)
576        break;
577      (void) CopyMagickMemory(q,p,(size_t) length*sizeof(*q));
578      q+=length;
579      if (indexes == (IndexPacket *) NULL)
580        continue;
581      nexus_indexes=GetNexusIndexes(cache_info,image_nexus);
582      if (nexus_indexes == (IndexPacket *) NULL)
583        continue;
584      (void) CopyMagickMemory(indexes,nexus_indexes,(size_t) length*
585        sizeof(*indexes));
586      indexes+=length;
587    }
588  }
589  DestroyCacheNexus(cache_info,image_nexus);
590  return(pixels);
591}
592
593/*
594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595%                                                                             %
596%                                                                             %
597%                                                                             %
598%   A c q u i r e I m a g e P i x e l s                                       %
599%                                                                             %
600%                                                                             %
601%                                                                             %
602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603%
604%  AcquireImagePixels() obtains a pixel region for read-only access. If the
605%  region is successfully accessed, a pointer to it is returned, otherwise
606%  NULL is returned. The returned pointer may point to a temporary working
607%  copy of the pixels or it may point to the original pixels in memory.
608%  Performance is maximized if the selected area is part of one row, or one
609%  or more full rows, since there is opportunity to access the pixels in-place
610%  (without a copy) if the image is in RAM, or in a memory-mapped file.  The
611%  returned pointer should *never* be deallocated by the user.
612%
613%  Pixels accessed via the returned pointer represent a simple array of type
614%  PixelPacket.  If the image type is CMYK or the storage class is PseudoClass,
615%  call GetIndexes() after invoking GetImagePixels() to access the black
616%  color component or to obtain the colormap indexes (of type IndexPacket)
617%  corresponding to the region.
618%
619%  If you plan to modify the pixels, use GetImagePixels() instead.
620%
621%  Note, the AcquireImagePixels() and GetImagePixels() methods are not thread-
622%  safe.  In a threaded environment, use AcquireCacheViewPixels() or
623%  GetCacheViewPixels() instead.
624%
625%  The format of the AcquireImagePixels() method is:
626%
627%      const PixelPacket *AcquireImagePixels(const Image *image,const long x,
628%        const long y,const unsigned long columns,const unsigned long rows,
629%        ExceptionInfo *exception)
630%
631%  A description of each parameter follows:
632%
633%    o image: The image.
634%
635%    o x,y,columns,rows:  These values define the perimeter of a region of
636%      pixels.
637%
638%    o exception: Return any errors or warnings in this structure.
639%
640*/
641MagickExport const PixelPacket *AcquireImagePixels(const Image *image,
642  const long x,const long y,const unsigned long columns,
643  const unsigned long rows,ExceptionInfo *exception)
644{
645  CacheInfo
646    *cache_info;
647
648  const PixelPacket
649    *pixels;
650
651  assert(image != (const Image *) NULL);
652  assert(image->signature == MagickSignature);
653  if (image->debug != MagickFalse)
654    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
655  assert(image->cache != (Cache) NULL);
656  cache_info=(CacheInfo *) image->cache;
657  assert(cache_info->signature == MagickSignature);
658  if (cache_info->methods.acquire_pixel_handler == (AcquirePixelHandler) NULL)
659    return((const PixelPacket *) NULL);
660  pixels=cache_info->methods.acquire_pixel_handler(image,
661    GetCacheVirtualPixelMethod(image),x,y,columns,rows,exception);
662  return(pixels);
663}
664
665/*
666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667%                                                                             %
668%                                                                             %
669%                                                                             %
670%   A c q u i r e I n d e x e s                                               %
671%                                                                             %
672%                                                                             %
673%                                                                             %
674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675%
676%  AcquireIndexes() returns the black channel or the colormap indexes
677%  associated with the last call to SetImagePixels() or AcquireImagePixels().
678%  NULL is returned if the black channel or colormap indexes are not available.
679%
680%  The format of the AcquireIndexes() method is:
681%
682%      const IndexPacket *AcquireIndexes(const Image *image)
683%
684%  A description of each parameter follows:
685%
686%    o indexes: AcquireIndexes() returns the indexes associated with the last
687%      call to SetImagePixels() or AcquireImagePixels().
688%
689%    o image: The image.
690%
691*/
692MagickExport const IndexPacket *AcquireIndexes(const Image *image)
693{
694  CacheInfo
695    *cache_info;
696
697  assert(image != (const Image *) NULL);
698  assert(image->signature == MagickSignature);
699  if (image->debug != MagickFalse)
700    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
701  assert(image->cache != (Cache) NULL);
702  cache_info=(CacheInfo *) image->cache;
703  assert(cache_info->signature == MagickSignature);
704  if (cache_info->methods.acquire_indexes_from_handler ==
705       (AcquireIndexesFromHandler) NULL)
706    return((IndexPacket *) NULL);
707  return(cache_info->methods.acquire_indexes_from_handler(image));
708}
709
710/*
711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712%                                                                             %
713%                                                                             %
714%                                                                             %
715+   G e t I n d e x e s F r o m C a c h e                                     %
716%                                                                             %
717%                                                                             %
718%                                                                             %
719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720%
721%  AcquireIndexesFromCache() returns the indexes associated with the last callV
722%  to SetPixelCache() or AcquirePixelCache().
723%
724%  The format of the AcquireIndexesFromCache() method is:
725%
726%      IndexPacket *AcquireIndexesFromCache(const Image *image)
727%
728%  A description of each parameter follows:
729%
730%    o indexes: AcquireIndexesFromCache() returns the indexes associated with the
731%      last call to SetPixelCache() or AcquirePixelCache().
732%
733%    o image: The image.
734%
735*/
736static const IndexPacket *AcquireIndexesFromCache(const Image *image)
737{
738  assert(image != (Image *) NULL);
739  assert(image->signature == MagickSignature);
740  if (image->debug != MagickFalse)
741    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
742  assert(image->cache != (Cache) NULL);
743  return(AcquireNexusIndexes(image->cache,0));
744}
745
746/*
747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748%                                                                             %
749%                                                                             %
750%                                                                             %
751+   A c q u i r e N e x u s I n d e x e s                                     %
752%                                                                             %
753%                                                                             %
754%                                                                             %
755%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
756%
757%  AcquireNexusIndexes() returns the indexes associated with the specified
758%  cache nexus.
759%
760%  The format of the AcquireNexusIndexes() method is:
761%
762%      const IndexPacket *AcquireNexusIndexes(const Cache cache,
763%        const unsigned long nexus)
764%
765%  A description of each parameter follows:
766%
767%    o indexes: AcquireNexusIndexes returns the indexes associated with the
768%      specified cache nexus.
769%
770%    o cache: The pixel cache.
771%
772%    o nexus: specifies which cache nexus to return the colormap indexes.
773%
774*/
775MagickExport const IndexPacket *AcquireNexusIndexes(const Cache cache,
776  const unsigned long nexus)
777{
778  CacheInfo
779    *cache_info;
780
781  register NexusInfo
782    *nexus_info;
783
784  if (cache == (Cache) NULL)
785    return((IndexPacket *) NULL);
786  cache_info=(CacheInfo *) cache;
787  assert(cache_info->signature == MagickSignature);
788  if (cache_info->storage_class == UndefinedClass)
789    return((IndexPacket *) NULL);
790  nexus_info=cache_info->nexus_info+nexus;
791  return(nexus_info->indexes);
792}
793
794/*
795%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796%                                                                             %
797%                                                                             %
798%                                                                             %
799+   A c q u i r e P i x e l C a c h e                                         %
800%                                                                             %
801%                                                                             %
802%                                                                             %
803%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804%
805%  AcquirePixelCache() acquires pixels from the in-memory or disk pixel
806%  cache as defined by the geometry parameters.   A pointer to the pixels
807%  is returned if the pixels are transferred, otherwise a NULL is returned.
808%
809%  The format of the AcquirePixelCache() method is:
810%
811%      const PixelPacket *AcquirePixelCache(const Image *image,
812%        const VirtualPixelMethod virtual_pixel_method,const long x,
813%        const long y,const unsigned long columns,const unsigned long rows,
814%        ExceptionInfo *exception)
815%
816%  A description of each parameter follows:
817%
818%    o image: The image.
819%
820%    o virtual_pixel_method: The virtual pixel method.
821%
822%    o x,y,columns,rows:  These values define the perimeter of a region of
823%      pixels.
824%
825%    o exception: Return any errors or warnings in this structure.
826%
827*/
828static const PixelPacket *AcquirePixelCache(const Image *image,
829  const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
830  const unsigned long columns,const unsigned long rows,ExceptionInfo *exception)
831{
832  const PixelPacket
833    *pixels;
834
835  if (image->debug != MagickFalse)
836    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
837  pixels=AcquireCacheNexus(image,virtual_pixel_method,x,y,columns,
838    rows,0,exception);
839  return(pixels);
840}
841
842/*
843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
844%                                                                             %
845%                                                                             %
846%                                                                             %
847%   A c q u i r e O n e M a g i c k P i x e l                                 %
848%                                                                             %
849%                                                                             %
850%                                                                             %
851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852%
853%  AcquireOneMagickPixel() returns a single pixel at the specified (x,y)
854%  location.  The image background color is returned if an error occurs.  If
855%  you plan to modify the pixel, use GetOnePixel() instead.
856%
857%  The format of the AcquireOneMagickPixel() method is:
858%
859%      MagickPixelPacket AcquireOneMagickPixel(const Image image,const long x,
860%        const long y,ExceptionInfo exception)
861%
862%  A description of each parameter follows:
863%
864%    o pixels: AcquireOneMagickPixel() returns a pixel at the specified (x,y)
865%      location.
866%
867%    o image: The image.
868%
869%    o x,y:  These values define the location of the pixel to return.
870%
871%    o exception: Return any errors or warnings in this structure.
872%
873*/
874MagickExport MagickPixelPacket AcquireOneMagickPixel(const Image *image,
875  const long x,const long y,ExceptionInfo *exception)
876{
877  CacheInfo
878    *cache_info;
879
880  MagickPixelPacket
881    pixel;
882
883  register const PixelPacket
884    *p;
885
886  register IndexPacket
887    *indexes;
888
889  assert(image != (const Image *) NULL);
890  assert(image->signature == MagickSignature);
891  assert(image->cache != (Cache) NULL);
892  cache_info=(CacheInfo *) image->cache;
893  assert(cache_info->signature == MagickSignature);
894  GetMagickPixelPacket(image,&pixel);
895  p=AcquirePixelCache(image,GetCacheVirtualPixelMethod(image),x,y,1,1,
896    exception);
897  indexes=GetIndexes(image);
898  SetMagickPixelPacket(image,p,indexes,&pixel);
899  return(pixel);
900}
901
902/*
903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904%                                                                             %
905%                                                                             %
906%                                                                             %
907%   A c q u i r e O n e P i x e l                                             %
908%                                                                             %
909%                                                                             %
910%                                                                             %
911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912%
913%  AcquireOnePixel() returns a single pixel at the specified (x,y) location.
914%  The image background color is returned if an error occurs.  If you plan to
915%  modify the pixel, use GetOnePixel() instead.
916%
917%  The format of the AcquireOnePixel() method is:
918%
919%      PixelPacket AcquireOnePixel(const Image image,const long x,
920%        const long y,ExceptionInfo exception)