2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % CCCC AAA CCCC H H EEEEE %
8 % C AAAAA C HHHHH EEE %
10 % CCCC A A CCCC H H EEEEE %
13 % MagickCore Pixel Cache Methods %
20 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.h"
57 #include "magick/pixel-private.h"
58 #include "magick/quantum.h"
59 #include "magick/random_.h"
60 #include "magick/resource_.h"
61 #include "magick/semaphore.h"
62 #include "magick/splay-tree.h"
63 #include "magick/string_.h"
64 #include "magick/thread-private.h"
65 #include "magick/utility.h"
66 #if defined(MAGICKCORE_ZLIB_DELEGATE)
73 typedef struct _MagickModulo
103 Forward declarations.
105 #if defined(__cplusplus) || defined(c_plusplus)
109 static const IndexPacket
110 *GetVirtualIndexesFromCache(const Image *);
112 static const PixelPacket
113 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const long,
114 const long,const unsigned long,const unsigned long,ExceptionInfo *),
115 *GetVirtualPixelsCache(const Image *);
117 static MagickBooleanType
118 GetOneAuthenticPixelFromCache(Image *,const long,const long,PixelPacket *,
120 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
121 const long,const long,PixelPacket *,ExceptionInfo *),
122 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
123 ReadPixelCacheIndexes(CacheInfo *,NexusInfo *,ExceptionInfo *),
124 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
125 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
126 WritePixelCacheIndexes(CacheInfo *,NexusInfo *,ExceptionInfo *),
127 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
130 *GetAuthenticPixelsCache(Image *,const long,const long,const unsigned long,
131 const unsigned long,ExceptionInfo *),
132 *QueueAuthenticPixelsCache(Image *,const long,const long,const unsigned long,
133 const unsigned long,ExceptionInfo *),
134 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *,
137 #if defined(__cplusplus) || defined(c_plusplus)
144 static volatile MagickBooleanType
145 instantiate_cache = MagickFalse;
148 *cache_semaphore = (SemaphoreInfo *) NULL;
151 *cache_resources = (SplayTreeInfo *) NULL;
157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161 + A c q u i r e P i x e l C a c h e %
165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167 % AcquirePixelCache() acquires a pixel cache.
169 % The format of the AcquirePixelCache() method is:
171 % Cache AcquirePixelCache(const unsigned long number_threads)
173 % A description of each parameter follows:
175 % o number_threads: the number of nexus threads.
178 MagickExport Cache AcquirePixelCache(const unsigned long number_threads)
183 cache_info=(CacheInfo *) AcquireAlignedMemory(1,sizeof(*cache_info));
184 if (cache_info == (CacheInfo *) NULL)
185 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
186 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
187 cache_info->type=UndefinedCache;
188 cache_info->mode=IOMode;
189 cache_info->colorspace=RGBColorspace;
190 cache_info->file=(-1);
191 cache_info->id=GetMagickThreadId();
192 cache_info->number_threads=number_threads;
193 if (number_threads == 0)
194 cache_info->number_threads=GetOpenMPMaximumThreads();
195 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
196 if (cache_info->nexus_info == (NexusInfo **) NULL)
197 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
198 GetPixelCacheMethods(&cache_info->methods);
199 cache_info->reference_count=1;
200 cache_info->semaphore=AllocateSemaphoreInfo();
201 cache_info->disk_semaphore=AllocateSemaphoreInfo();
202 cache_info->debug=IsEventLogging();
203 cache_info->signature=MagickSignature;
204 if ((cache_resources == (SplayTreeInfo *) NULL) &&
205 (instantiate_cache == MagickFalse))
207 if (cache_semaphore == (SemaphoreInfo *) NULL)
208 AcquireSemaphoreInfo(&cache_semaphore);
209 LockSemaphoreInfo(cache_semaphore);
210 if ((cache_resources == (SplayTreeInfo *) NULL) &&
211 (instantiate_cache == MagickFalse))
213 cache_resources=NewSplayTree((int (*)(const void *,const void *))
214 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
215 instantiate_cache=MagickTrue;
217 UnlockSemaphoreInfo(cache_semaphore);
219 (void) AddValueToSplayTree(cache_resources,cache_info,cache_info);
220 return((Cache ) cache_info);
224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228 % A c q u i r e P i x e l C a c h e N e x u s %
232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 % AcquirePixelCacheNexus() allocates the NexusInfo structure.
236 % The format of the AcquirePixelCacheNexus method is:
238 % NexusInfo **AcquirePixelCacheNexus(const unsigned long number_threads)
240 % A description of each parameter follows:
242 % o number_threads: the number of nexus threads.
245 MagickExport NexusInfo **AcquirePixelCacheNexus(
246 const unsigned long number_threads)
254 nexus_info=(NexusInfo **) AcquireAlignedMemory(number_threads,
255 sizeof(*nexus_info));
256 if (nexus_info == (NexusInfo **) NULL)
257 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
258 for (i=0; i < (long) number_threads; i++)
260 nexus_info[i]=(NexusInfo *) AcquireAlignedMemory(1,sizeof(**nexus_info));
261 if (nexus_info[i] == (NexusInfo *) NULL)
262 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
263 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
264 nexus_info[i]->signature=MagickSignature;
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 + C a c h e C o m p o n e n t G e n e s i s %
278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 % CacheComponentGenesis() instantiates the cache component.
282 % The format of the CacheComponentGenesis method is:
284 % MagickBooleanType CacheComponentGenesis(void)
287 MagickExport MagickBooleanType CacheComponentGenesis(void)
289 AcquireSemaphoreInfo(&cache_semaphore);
294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298 + C a c h e C o m p o n e n t T e r m i n u s %
302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304 % CacheComponentTerminus() destroys the cache component.
306 % The format of the CacheComponentTerminus() method is:
308 % CacheComponentTerminus(void)
311 MagickExport void CacheComponentTerminus(void)
313 if (cache_semaphore == (SemaphoreInfo *) NULL)
314 AcquireSemaphoreInfo(&cache_semaphore);
315 LockSemaphoreInfo(cache_semaphore);
316 if (cache_resources != (SplayTreeInfo *) NULL)
317 cache_resources=DestroySplayTree(cache_resources);
318 instantiate_cache=MagickFalse;
319 UnlockSemaphoreInfo(cache_semaphore);
320 DestroySemaphoreInfo(&cache_semaphore);
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 + C l i p P i x e l C a c h e N e x u s %
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 % ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
335 % mask. The method returns MagickTrue if the pixel region is clipped,
336 % otherwise MagickFalse.
338 % The format of the ClipPixelCacheNexus() method is:
340 % MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
341 % ExceptionInfo *exception)
343 % A description of each parameter follows:
345 % o image: the image.
347 % o nexus_info: the cache nexus to clip.
349 % o exception: return any errors or warnings in this structure.
352 static MagickBooleanType ClipPixelCacheNexus(Image *image,
353 NexusInfo *nexus_info,ExceptionInfo *exception)
365 register const PixelPacket
369 *restrict nexus_indexes,
382 if (image->debug != MagickFalse)
383 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
384 if (image->clip_mask == (Image *) NULL)
386 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
387 if (cache_info == (Cache) NULL)
389 image_nexus=AcquirePixelCacheNexus(1);
390 clip_nexus=AcquirePixelCacheNexus(1);
391 if ((image_nexus == (NexusInfo **) NULL) ||
392 (clip_nexus == (NexusInfo **) NULL))
393 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
394 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
395 nexus_info->region.width,nexus_info->region.height,image_nexus[0],
397 indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
398 q=nexus_info->pixels;
399 nexus_indexes=nexus_info->indexes;
400 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
401 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
402 nexus_info->region.height,clip_nexus[0],exception);
403 number_pixels=(MagickSizeType) nexus_info->region.width*
404 nexus_info->region.height;
405 for (i=0; i < (long) number_pixels; i++)
407 if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
409 if (PixelIntensityToQuantum(r) > ((Quantum) QuantumRange/2))
411 SetRedPixelComponent(q,GetRedPixelComponent(p));
412 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
413 SetBluePixelComponent(q,GetBluePixelComponent(p));
414 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
415 if (cache_info->active_index_channel != MagickFalse)
416 nexus_indexes[i]=indexes[i];
422 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
423 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
424 if (i < (long) number_pixels)
430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434 + C l o n e P i x e l C a c h e %
438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440 % ClonePixelCache() clones a pixel cache.
442 % The format of the ClonePixelCache() method is:
444 % Cache ClonePixelCache(const Cache cache)
446 % A description of each parameter follows:
448 % o cache: the pixel cache.
451 MagickExport Cache ClonePixelCache(const Cache cache)
459 assert(cache != (const Cache) NULL);
460 cache_info=(const CacheInfo *) cache;
461 assert(cache_info->signature == MagickSignature);
462 if (cache_info->debug != MagickFalse)
463 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
464 cache_info->filename);
465 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
466 if (clone_info == (Cache) NULL)
467 return((Cache) NULL);
468 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
469 return((Cache ) clone_info);
473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 + C l o n e P i x e l C a c h e N e x u s %
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483 % ClonePixelCacheNexus() clones the source cache nexus to the destination
486 % The format of the ClonePixelCacheNexus() method is:
488 % MagickBooleanType ClonePixelCacheNexus(CacheInfo *destination,
489 % CacheInfo *source,ExceptionInfo *exception)
491 % A description of each parameter follows:
493 % o destination: the destination cache nexus.
495 % o source: the source cache nexus.
497 % o exception: return any errors or warnings in this structure.
501 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
502 NexusInfo *nexus_info,ExceptionInfo *exception)
504 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
506 nexus_info->mapped=MagickFalse;
507 nexus_info->cache=(PixelPacket *) AcquireMagickMemory((size_t)
509 if (nexus_info->cache == (PixelPacket *) NULL)
511 nexus_info->mapped=MagickTrue;
512 nexus_info->cache=(PixelPacket *) MapBlob(-1,IOMode,0,(size_t)
515 if (nexus_info->cache == (PixelPacket *) NULL)
517 (void) ThrowMagickException(exception,GetMagickModule(),
518 ResourceLimitError,"MemoryAllocationFailed","`%s'",
519 cache_info->filename);
525 static MagickBooleanType ClonePixelCacheNexus(CacheInfo *destination,
526 CacheInfo *source,ExceptionInfo *exception)
537 register const NexusInfo
544 for (i=0; i < (long) source->number_threads; i++)
546 p=source->nexus_info[i];
547 q=destination->nexus_info[i];
553 q->indexes=p->indexes;
554 if (p->cache != (PixelPacket *) NULL)
556 status=AcquireCacheNexusPixels(source,q,exception);
557 if (status != MagickFalse)
559 (void) CopyMagickMemory(q->cache,p->cache,(size_t) p->length);
561 q->indexes=(IndexPacket *) NULL;
562 number_pixels=(MagickSizeType) q->region.width*q->region.height;
563 if (p->indexes != (IndexPacket *) NULL)
564 q->indexes=(IndexPacket *) (q->pixels+number_pixels);
572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576 + C l o n e P i x e l C a c h e P i x e l s %
580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
581 % ClonePixelCachePixels() clones the source pixel cache to the destination
584 % The format of the ClonePixelCachePixels() method is:
586 % MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
587 % CacheInfo *source_info,ExceptionInfo *exception)
589 % A description of each parameter follows:
591 % o cache_info: the pixel cache.
593 % o source_info: the source pixel cache.
595 % o exception: return any errors or warnings in this structure.
599 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
604 LockSemaphoreInfo(cache_info->disk_semaphore);
605 status=close(cache_info->file);
606 cache_info->file=(-1);
607 RelinquishMagickResource(FileResource,1);
608 UnlockSemaphoreInfo(cache_info->disk_semaphore);
609 return(status == -1 ? MagickFalse : MagickTrue);
612 static void LimitPixelCacheDescriptors(void)
619 Limit # of open file descriptors.
621 if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
623 LockSemaphoreInfo(cache_semaphore);
624 if (cache_resources == (SplayTreeInfo *) NULL)
626 UnlockSemaphoreInfo(cache_semaphore);
629 ResetSplayTreeIterator(cache_resources);
630 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
631 while (p != (CacheInfo *) NULL)
633 if ((p->type == DiskCache) && (p->file != -1))
635 if (IsMagickThreadEqual(p->id) != MagickFalse)
638 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
640 for (q=p; p != (CacheInfo *) NULL; )
642 if ((p->type == DiskCache) && (p->file != -1) &&
643 (p->timestamp < q->timestamp))
645 if (IsMagickThreadEqual(p->id) != MagickFalse)
648 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
650 if (q != (CacheInfo *) NULL)
651 (void) ClosePixelCacheOnDisk(q); /* relinquish least recently used cache */
652 UnlockSemaphoreInfo(cache_semaphore);
655 static inline MagickSizeType MagickMax(const MagickSizeType x,
656 const MagickSizeType y)
663 static inline MagickSizeType MagickMin(const MagickSizeType x,
664 const MagickSizeType y)
671 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
678 Open pixel cache on disk.
680 LockSemaphoreInfo(cache_info->disk_semaphore);
681 if (cache_info->file != -1)
683 UnlockSemaphoreInfo(cache_info->disk_semaphore);
684 return(MagickTrue); /* cache already open */
686 LimitPixelCacheDescriptors();
687 if (*cache_info->cache_filename == '\0')
688 file=AcquireUniqueFileResource(cache_info->cache_filename);
694 file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
699 file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
702 file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
708 file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
711 file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
717 UnlockSemaphoreInfo(cache_info->disk_semaphore);
720 (void) AcquireMagickResource(FileResource,1);
721 cache_info->file=file;
722 cache_info->timestamp=time(0);
723 UnlockSemaphoreInfo(cache_info->disk_semaphore);
727 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
728 const MagickOffsetType offset,const MagickSizeType length,
729 unsigned char *restrict buffer)
731 register MagickOffsetType
737 #if !defined(MAGICKCORE_HAVE_PREAD)
738 LockSemaphoreInfo(cache_info->disk_semaphore);
739 cache_info->timestamp=time(0);
740 if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
742 UnlockSemaphoreInfo(cache_info->disk_semaphore);
743 return((MagickOffsetType) -1);
747 for (i=0; i < (MagickOffsetType) length; i+=count)
749 #if !defined(MAGICKCORE_HAVE_PREAD)
750 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
751 (MagickSizeType) SSIZE_MAX));
753 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
754 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
765 #if !defined(MAGICKCORE_HAVE_PREAD)
766 UnlockSemaphoreInfo(cache_info->disk_semaphore);
771 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
772 const MagickOffsetType offset,const MagickSizeType length,
773 const unsigned char *restrict buffer)
775 register MagickOffsetType
781 #if !defined(MAGICKCORE_HAVE_PWRITE)
782 LockSemaphoreInfo(cache_info->disk_semaphore);
783 cache_info->timestamp=time(0);
784 if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
786 UnlockSemaphoreInfo(cache_info->disk_semaphore);
787 return((MagickOffsetType) -1);
791 for (i=0; i < (MagickOffsetType) length; i+=count)
793 #if !defined(MAGICKCORE_HAVE_PWRITE)
794 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
795 (MagickSizeType) SSIZE_MAX));
797 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
798 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
809 #if !defined(MAGICKCORE_HAVE_PWRITE)
810 UnlockSemaphoreInfo(cache_info->disk_semaphore);
815 static MagickBooleanType CloneDiskToDiskPixelCache(CacheInfo *clone_info,
816 CacheInfo *cache_info,ExceptionInfo *exception)
836 if (cache_info->debug != MagickFalse)
837 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
838 if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
840 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
841 clone_info->cache_filename);
844 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
846 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
847 cache_info->cache_filename);
850 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
851 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
852 if ((clone_info->active_index_channel != MagickFalse) &&
853 (cache_info->active_index_channel != MagickFalse))
861 length=MagickMax(clone_info->columns,cache_info->columns)*
863 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
864 if (indexes == (IndexPacket *) NULL)
866 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
867 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
870 (void) ResetMagickMemory(indexes,0,(size_t) length);
871 length=columns*sizeof(*indexes);
872 source_offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
873 sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
874 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
875 sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
876 for (y=0; y < (long) rows; y++)
878 source_offset-=cache_info->columns*sizeof(*indexes);
879 count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
880 length,(unsigned char *) indexes);
881 if ((MagickSizeType) count != length)
883 offset-=clone_info->columns*sizeof(*indexes);
884 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
885 (unsigned char *) indexes);
886 if ((MagickSizeType) count != length)
891 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
892 ThrowFileException(exception,CacheError,"UnableToCloneCache",
893 cache_info->cache_filename);
896 if (clone_info->columns > cache_info->columns)
898 length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
899 (void) ResetMagickMemory(indexes,0,(size_t) length);
900 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
901 sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
902 for (y=0; y < (long) rows; y++)
904 offset-=clone_info->columns*sizeof(*indexes);
905 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
906 length,(unsigned char *) indexes);
907 if ((MagickSizeType) count != length)
912 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
913 ThrowFileException(exception,CacheError,"UnableToCloneCache",
914 cache_info->cache_filename);
918 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
923 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
924 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
925 if (pixels == (PixelPacket *) NULL)
927 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
928 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
931 (void) ResetMagickMemory(pixels,0,(size_t) length);
932 length=columns*sizeof(*pixels);
933 source_offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
934 offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
935 for (y=0; y < (long) rows; y++)
937 source_offset-=cache_info->columns*sizeof(*pixels);
938 count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
939 length,(unsigned char *) pixels);
940 if ((MagickSizeType) count != length)
942 offset-=clone_info->columns*sizeof(*pixels);
943 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
944 (unsigned char *) pixels);
945 if ((MagickSizeType) count != length)
950 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
951 ThrowFileException(exception,CacheError,"UnableToCloneCache",
952 cache_info->cache_filename);
955 if (clone_info->columns > cache_info->columns)
957 offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
959 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
960 (void) ResetMagickMemory(pixels,0,(size_t) length);
961 for (y=0; y < (long) rows; y++)
963 offset-=clone_info->columns*sizeof(*pixels);
964 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
965 (unsigned char *) pixels);
966 if ((MagickSizeType) count != length)
971 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
972 ThrowFileException(exception,CacheError,"UnableToCloneCache",
973 cache_info->cache_filename);
977 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
981 static MagickBooleanType CloneDiskToMemoryPixelCache(CacheInfo *clone_info,
982 CacheInfo *cache_info,ExceptionInfo *exception)
1002 if (cache_info->debug != MagickFalse)
1003 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
1004 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
1006 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1007 cache_info->cache_filename);
1008 return(MagickFalse);
1010 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
1011 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
1012 if ((clone_info->active_index_channel != MagickFalse) &&
1013 (cache_info->active_index_channel != MagickFalse))
1015 register IndexPacket
1020 Clone cache indexes.
1022 length=MagickMax(clone_info->columns,cache_info->columns)*
1024 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
1025 if (indexes == (IndexPacket *) NULL)
1027 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
1028 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
1029 return(MagickFalse);
1031 (void) ResetMagickMemory(indexes,0,(size_t) length);
1032 length=columns*sizeof(IndexPacket);
1033 offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
1034 sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
1035 q=clone_info->indexes+clone_info->columns*rows;
1036 for (y=0; y < (long) rows; y++)
1038 offset-=cache_info->columns*sizeof(IndexPacket);
1039 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset,
1040 length,(unsigned char *) indexes);
1041 if ((MagickSizeType) count != length)
1043 q-=clone_info->columns;
1044 (void) CopyMagickMemory(q,indexes,(size_t) length);
1045 if ((MagickSizeType) count != length)
1048 if (y < (long) rows)
1050 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1051 ThrowFileException(exception,CacheError,"UnableToCloneCache",
1052 cache_info->cache_filename);
1053 return(MagickFalse);
1055 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1060 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
1061 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
1062 if (pixels == (PixelPacket *) NULL)
1064 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
1065 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
1066 return(MagickFalse);
1068 (void) ResetMagickMemory(pixels,0,(size_t) length);
1069 length=columns*sizeof(*pixels);
1070 offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
1071 q=clone_info->pixels+clone_info->columns*rows;
1072 for (y=0; y < (long) rows; y++)
1074 offset-=cache_info->columns*sizeof(*pixels);
1075 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset,length,
1076 (unsigned char *) pixels);
1077 if ((MagickSizeType) count != length)
1079 q-=clone_info->columns;
1080 (void) CopyMagickMemory(q,pixels,(size_t) length);
1082 if (y < (long) rows)
1084 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1085 ThrowFileException(exception,CacheError,"UnableToCloneCache",
1086 cache_info->cache_filename);
1087 return(MagickFalse);
1089 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1093 static MagickBooleanType CloneMemoryToDiskPixelCache(CacheInfo *clone_info,
1094 CacheInfo *cache_info,ExceptionInfo *exception)
1106 register PixelPacket
1114 if (cache_info->debug != MagickFalse)
1115 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
1116 if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
1118 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1119 clone_info->cache_filename);
1120 return(MagickFalse);
1122 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
1123 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
1124 if ((clone_info->active_index_channel != MagickFalse) &&
1125 (cache_info->active_index_channel != MagickFalse))
1127 register IndexPacket
1132 Clone cache indexes.
1134 length=MagickMax(clone_info->columns,cache_info->columns)*
1136 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
1137 if (indexes == (IndexPacket *) NULL)
1139 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
1140 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
1141 return(MagickFalse);
1143 (void) ResetMagickMemory(indexes,0,(size_t) length);
1144 length=columns*sizeof(*indexes);
1145 p=cache_info->indexes+cache_info->columns*rows;
1146 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
1147 sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
1148 for (y=0; y < (long) rows; y++)
1150 p-=cache_info->columns;
1151 (void) CopyMagickMemory(indexes,p,(size_t) length);
1152 offset-=clone_info->columns*sizeof(*indexes);
1153 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
1154 (unsigned char *) indexes);
1155 if ((MagickSizeType) count != length)
1158 if (y < (long) rows)
1160 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1161 ThrowFileException(exception,CacheError,"UnableToCloneCache",
1162 cache_info->cache_filename);
1163 return(MagickFalse);
1165 if (clone_info->columns > cache_info->columns)
1167 length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
1168 (void) ResetMagickMemory(indexes,0,(size_t) length);
1169 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
1170 sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
1171 for (y=0; y < (long) rows; y++)
1173 offset-=clone_info->columns*sizeof(*indexes);
1174 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
1175 length,(unsigned char *) indexes);
1176 if ((MagickSizeType) count != length)
1179 if (y < (long) rows)
1181 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1182 ThrowFileException(exception,CacheError,"UnableToCloneCache",
1183 cache_info->cache_filename);
1184 return(MagickFalse);
1187 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
1192 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
1193 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
1194 if (pixels == (PixelPacket *) NULL)
1196 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
1197 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
1198 return(MagickFalse);
1200 (void) ResetMagickMemory(pixels,0,(size_t) length);
1201 length=columns*sizeof(*pixels);
1202 p=cache_info->pixels+cache_info->columns*rows;
1203 offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
1204 for (y=0; y < (long) rows; y++)
1206 p-=cache_info->columns;
1207 (void) CopyMagickMemory(pixels,p,(size_t) length);
1208 offset-=clone_info->columns*sizeof(*pixels);
1209 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
1210 (unsigned char *) pixels);
1211 if ((MagickSizeType) count != length)
1214 if (y < (long) rows)
1216 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1217 ThrowFileException(exception,CacheError,"UnableToCloneCache",
1218 cache_info->cache_filename);
1219 return(MagickFalse);
1221 if (clone_info->columns > cache_info->columns)
1223 offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
1225 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
1226 (void) ResetMagickMemory(pixels,0,(size_t) length);
1227 for (y=0; y < (long) rows; y++)
1229 offset-=clone_info->columns*sizeof(*pixels);
1230 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
1231 (unsigned char *) pixels);
1232 if ((MagickSizeType) count != length)
1235 if (y < (long) rows)
1237 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1238 ThrowFileException(exception,CacheError,"UnableToCloneCache",
1239 cache_info->cache_filename);
1240 return(MagickFalse);
1243 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
1247 static MagickBooleanType CloneMemoryToMemoryPixelCache(CacheInfo *clone_info,
1248 CacheInfo *cache_info,ExceptionInfo *magick_unused(exception))
1253 register PixelPacket
1255 *restrict source_pixels;
1264 if (cache_info->debug != MagickFalse)
1265 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
1266 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
1267 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
1268 if ((clone_info->active_index_channel != MagickFalse) &&
1269 (cache_info->active_index_channel != MagickFalse))
1271 register IndexPacket
1276 Clone cache indexes.
1278 length=columns*sizeof(*indexes);
1279 if (clone_info->columns == cache_info->columns)
1280 (void) CopyMagickMemory(clone_info->indexes,cache_info->indexes,
1284 source_indexes=cache_info->indexes+cache_info->columns*rows;
1285 indexes=clone_info->indexes+clone_info->columns*rows;
1286 for (y=0; y < (long) rows; y++)
1288 source_indexes-=cache_info->columns;
1289 indexes-=clone_info->columns;
1290 (void) CopyMagickMemory(indexes,source_indexes,length);
1292 if (clone_info->columns > cache_info->columns)
1294 length=(clone_info->columns-cache_info->columns)*
1296 indexes=clone_info->indexes+clone_info->columns*rows+
1297 cache_info->columns;
1298 for (y=0; y < (long) rows; y++)
1300 indexes-=clone_info->columns;
1301 (void) ResetMagickMemory(indexes,0,length);
1309 length=columns*sizeof(*pixels);
1310 if (clone_info->columns == cache_info->columns)
1311 (void) CopyMagickMemory(clone_info->pixels,cache_info->pixels,length*rows);
1314 source_pixels=cache_info->pixels+cache_info->columns*rows;
1315 pixels=clone_info->pixels+clone_info->columns*rows;
1316 for (y=0; y < (long) rows; y++)
1318 source_pixels-=cache_info->columns;
1319 pixels-=clone_info->columns;
1320 (void) CopyMagickMemory(pixels,source_pixels,length);
1322 if (clone_info->columns > cache_info->columns)
1324 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
1325 pixels=clone_info->pixels+clone_info->columns*rows+
1326 cache_info->columns;
1327 for (y=0; y < (long) rows; y++)
1329 pixels-=clone_info->columns;
1330 (void) ResetMagickMemory(pixels,0,length);
1337 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1338 CacheInfo *cache_info,ExceptionInfo *exception)
1340 if ((clone_info->type != DiskCache) && (cache_info->type != DiskCache))
1341 return(CloneMemoryToMemoryPixelCache(clone_info,cache_info,exception));
1342 if ((clone_info->type == DiskCache) && (cache_info->type == DiskCache))
1343 return(CloneDiskToDiskPixelCache(clone_info,cache_info,exception));
1344 if (cache_info->type == DiskCache)
1345 return(CloneDiskToMemoryPixelCache(clone_info,cache_info,exception));
1346 return(CloneMemoryToDiskPixelCache(clone_info,cache_info,exception));
1350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1354 + C l o n e P i x e l C a c h e M e t h o d s %
1358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1360 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1363 % The format of the ClonePixelCacheMethods() method is:
1365 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
1367 % A description of each parameter follows:
1369 % o clone: Specifies a pointer to a Cache structure.
1371 % o cache: the pixel cache.
1374 MagickExport void ClonePixelCacheMethods(Cache clone,const Cache cache)
1380 assert(clone != (Cache) NULL);
1381 source_info=(CacheInfo *) clone;
1382 assert(source_info->signature == MagickSignature);
1383 if (source_info->debug != MagickFalse)
1384 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1385 source_info->filename);
1386 assert(cache != (Cache) NULL);
1387 cache_info=(CacheInfo *) cache;
1388 assert(cache_info->signature == MagickSignature);
1389 source_info->methods=cache_info->methods;
1393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1397 + D e s t r o y I m a g e P i x e l C a c h e %
1401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1403 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1405 % The format of the DestroyImagePixelCache() method is:
1407 % void DestroyImagePixelCache(Image *image)
1409 % A description of each parameter follows:
1411 % o image: the image.
1414 static void DestroyImagePixelCache(Image *image)
1416 assert(image != (Image *) NULL);
1417 assert(image->signature == MagickSignature);
1418 if (image->debug != MagickFalse)
1419 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1420 if (image->cache == (void *) NULL)
1422 image->cache=DestroyPixelCache(image->cache);
1426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430 + D e s t r o y I m a g e P i x e l s %
1434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 % DestroyImagePixels() deallocates memory associated with the pixel cache.
1438 % The format of the DestroyImagePixels() method is:
1440 % void DestroyImagePixels(Image *image)
1442 % A description of each parameter follows:
1444 % o image: the image.
1447 MagickExport void DestroyImagePixels(Image *image)
1452 assert(image != (const Image *) NULL);
1453 assert(image->signature == MagickSignature);
1454 if (image->debug != MagickFalse)
1455 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1456 assert(image->cache != (Cache) NULL);
1457 cache_info=(CacheInfo *) image->cache;
1458 assert(cache_info->signature == MagickSignature);
1459 if (cache_info->methods.destroy_pixel_handler == (DestroyPixelHandler) NULL)
1461 cache_info->methods.destroy_pixel_handler(image);
1465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1469 + D e s t r o y P i x e l C a c h e %
1473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1475 % DestroyPixelCache() deallocates memory associated with the pixel cache.
1477 % The format of the DestroyPixelCache() method is:
1479 % Cache DestroyPixelCache(Cache cache)
1481 % A description of each parameter follows:
1483 % o cache: the pixel cache.
1487 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1489 switch (cache_info->type)
1493 if (cache_info->mapped == MagickFalse)
1494 cache_info->pixels=(PixelPacket *) RelinquishMagickMemory(
1495 cache_info->pixels);
1497 cache_info->pixels=(PixelPacket *) UnmapBlob(cache_info->pixels,
1498 (size_t) cache_info->length);
1499 RelinquishMagickResource(MemoryResource,cache_info->length);
1504 cache_info->pixels=(PixelPacket *) UnmapBlob(cache_info->pixels,(size_t)
1505 cache_info->length);
1506 RelinquishMagickResource(MapResource,cache_info->length);
1510 if (cache_info->file != -1)
1511 (void) ClosePixelCacheOnDisk(cache_info);
1512 RelinquishMagickResource(DiskResource,cache_info->length);
1518 cache_info->type=UndefinedCache;
1519 cache_info->mapped=MagickFalse;
1520 cache_info->indexes=(IndexPacket *) NULL;
1523 MagickExport Cache DestroyPixelCache(Cache cache)
1528 assert(cache != (Cache) NULL);
1529 cache_info=(CacheInfo *) cache;
1530 assert(cache_info->signature == MagickSignature);
1531 if (cache_info->debug != MagickFalse)
1532 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1533 cache_info->filename);
1534 LockSemaphoreInfo(cache_info->semaphore);
1535 cache_info->reference_count--;
1536 if (cache_info->reference_count != 0)
1538 UnlockSemaphoreInfo(cache_info->semaphore);
1539 return((Cache) NULL);
1541 UnlockSemaphoreInfo(cache_info->semaphore);
1542 if (cache_resources != (SplayTreeInfo *) NULL)
1543 (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
1544 if (cache_info->debug != MagickFalse)
1547 message[MaxTextExtent];
1549 (void) FormatMagickString(message,MaxTextExtent,"destroy %s",
1550 cache_info->filename);
1551 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1553 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1554 (cache_info->type != DiskCache)))
1555 RelinquishPixelCachePixels(cache_info);
1558 RelinquishPixelCachePixels(cache_info);
1559 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1561 *cache_info->cache_filename='\0';
1562 if (cache_info->nexus_info != (NexusInfo **) NULL)
1563 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1564 cache_info->number_threads);
1565 if (cache_info->random_info != (RandomInfo *) NULL)
1566 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1567 cache_info->signature=(~MagickSignature);
1568 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1569 DestroySemaphoreInfo(&cache_info->disk_semaphore);
1570 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1571 DestroySemaphoreInfo(&cache_info->semaphore);
1572 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1582 + D e s t r o y P i x e l C a c h e N e x u s %
1586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1588 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1590 % The format of the DestroyPixelCacheNexus() method is:
1592 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1593 % const unsigned long number_threads)
1595 % A description of each parameter follows:
1597 % o nexus_info: the nexus to destroy.
1599 % o number_threads: the number of nexus threads.
1603 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1605 if (nexus_info->mapped == MagickFalse)
1606 (void) RelinquishMagickMemory(nexus_info->cache);
1608 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1609 nexus_info->cache=(PixelPacket *) NULL;
1610 nexus_info->pixels=(PixelPacket *) NULL;
1611 nexus_info->indexes=(IndexPacket *) NULL;
1612 nexus_info->length=0;
1613 nexus_info->mapped=MagickFalse;
1616 MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1617 const unsigned long number_threads)
1622 assert(nexus_info != (NexusInfo **) NULL);
1623 for (i=0; i < (long) number_threads; i++)
1625 if (nexus_info[i]->cache != (PixelPacket *) NULL)
1626 RelinquishCacheNexusPixels(nexus_info[i]);
1627 nexus_info[i]->signature=(~MagickSignature);
1628 nexus_info[i]=(NexusInfo *) RelinquishAlignedMemory(nexus_info[i]);
1630 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1639 + 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 %
1643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1645 % GetAuthenticIndexesFromCache() returns the indexes associated with the last
1646 % call to QueueAuthenticPixelsCache() or GetAuthenticPixelsCache().
1648 % The format of the GetAuthenticIndexesFromCache() method is:
1650 % IndexPacket *GetAuthenticIndexesFromCache(const Image *image)
1652 % A description of each parameter follows:
1654 % o image: the image.
1657 static IndexPacket *GetAuthenticIndexesFromCache(const Image *image)
1668 if (image->debug != MagickFalse)
1669 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1670 cache_info=(CacheInfo *) image->cache;
1671 id=GetOpenMPThreadId();
1672 assert(id < (long) cache_info->number_threads);
1673 indexes=GetPixelCacheNexusIndexes(image->cache,cache_info->nexus_info[id]);
1678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1682 % G e t A u t h e n t i c I n d e x Q u e u e %
1686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1688 % GetAuthenticIndexQueue() returns the authentic black channel or the colormap
1689 % indexes associated with the last call to QueueAuthenticPixels() or
1690 % GetVirtualPixels(). NULL is returned if the black channel or colormap
1691 % indexes are not available.
1693 % The format of the GetAuthenticIndexQueue() method is:
1695 % IndexPacket *GetAuthenticIndexQueue(const Image *image)
1697 % A description of each parameter follows:
1699 % o image: the image.
1702 MagickExport IndexPacket *GetAuthenticIndexQueue(const Image *image)
1707 assert(image != (const Image *) NULL);
1708 assert(image->signature == MagickSignature);
1709 if (image->debug != MagickFalse)
1710 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1711 assert(image->cache != (Cache) NULL);
1712 cache_info=(CacheInfo *) image->cache;
1713 assert(cache_info->signature == MagickSignature);
1714 if (cache_info->methods.get_authentic_indexes_from_handler ==
1715 (GetAuthenticIndexesFromHandler) NULL)
1716 return((IndexPacket *) NULL);
1717 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 + 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 %
1729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1731 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1732 % disk pixel cache as defined by the geometry parameters. A pointer to the
1733 % pixels is returned if the pixels are transferred, otherwise a NULL is
1736 % The format of the GetAuthenticPixelCacheNexus() method is:
1738 % PixelPacket *GetAuthenticPixelCacheNexus(Image *image,const long x,
1739 % const long y,const unsigned long columns,const unsigned long rows,
1740 % NexusInfo *nexus_info,ExceptionInfo *exception)
1742 % A description of each parameter follows:
1744 % o image: the image.
1746 % o x,y,columns,rows: These values define the perimeter of a region of
1749 % o nexus_info: the cache nexus to return.
1751 % o exception: return any errors or warnings in this structure.
1755 static inline MagickBooleanType IsNexusInCore(const CacheInfo *cache_info,
1756 NexusInfo *nexus_info)
1761 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1762 nexus_info->region.x;
1763 if (nexus_info->pixels != (cache_info->pixels+offset))
1764 return(MagickFalse);
1768 MagickExport PixelPacket *GetAuthenticPixelCacheNexus(Image *image,const long x,
1769 const long y,const unsigned long columns,const unsigned long rows,
1770 NexusInfo *nexus_info,ExceptionInfo *exception)
1779 Transfer pixels from the cache.
1781 assert(image != (Image *) NULL);
1782 assert(image->signature == MagickSignature);
1783 if (image->debug != MagickFalse)
1784 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1785 pixels=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
1786 if (pixels == (PixelPacket *) NULL)
1787 return((PixelPacket *) NULL);
1788 cache_info=(CacheInfo *) image->cache;
1789 assert(cache_info->signature == MagickSignature);
1790 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
1792 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1793 return((PixelPacket *) NULL);
1794 if (cache_info->active_index_channel != MagickFalse)
1795 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1796 return((PixelPacket *) NULL);
1801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1805 + 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 %
1809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1811 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1812 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1814 % The format of the GetAuthenticPixelsFromCache() method is:
1816 % PixelPacket *GetAuthenticPixelsFromCache(const Image image)
1818 % A description of each parameter follows:
1820 % o image: the image.
1823 static PixelPacket *GetAuthenticPixelsFromCache(const Image *image)
1834 if (image->debug != MagickFalse)
1835 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1836 cache_info=(CacheInfo *) image->cache;
1837 id=GetOpenMPThreadId();
1838 assert(id < (long) cache_info->number_threads);
1839 pixels=GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]);
1844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1848 % G e t A u t h e n t i c P i x e l Q u e u e %
1852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1854 % GetAuthenticPixelQueue() returns the authentic pixels associated with the
1855 % last call to QueueAuthenticPixels() or GetAuthenticPixels().
1857 % The format of the GetAuthenticPixelQueue() method is:
1859 % PixelPacket *GetAuthenticPixelQueue(const Image image)
1861 % A description of each parameter follows:
1863 % o image: the image.
1866 MagickExport PixelPacket *GetAuthenticPixelQueue(const Image *image)
1871 assert(image != (const Image *) NULL);
1872 assert(image->signature == MagickSignature);
1873 if (image->debug != MagickFalse)
1874 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1875 assert(image->cache != (Cache) NULL);
1876 cache_info=(CacheInfo *) image->cache;
1877 assert(cache_info->signature == MagickSignature);
1878 if (cache_info->methods.get_authentic_pixels_from_handler ==
1879 (GetAuthenticPixelsFromHandler) NULL)
1880 return((PixelPacket *) NULL);
1881 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1889 % G e t A u t h e n t i c P i x e l s %
1893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1895 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1896 % region is successfully accessed, a pointer to a PixelPacket array
1897 % representing the region is returned, otherwise NULL is returned.
1899 % The returned pointer may point to a temporary working copy of the pixels
1900 % or it may point to the original pixels in memory. Performance is maximized
1901 % if the selected region is part of one row, or one or more full rows, since
1902 % then there is opportunity to access the pixels in-place (without a copy)
1903 % if the image is in memory, or in a memory-mapped file. The returned pointer
1904 % must *never* be deallocated by the user.
1906 % Pixels accessed via the returned pointer represent a simple array of type
1907 % PixelPacket. If the image type is CMYK or if the storage class is
1908 % PseduoClass, call GetAuthenticIndexQueue() after invoking
1909 % GetAuthenticPixels() to obtain the black color component or colormap indexes
1910 % (of type IndexPacket) corresponding to the region. Once the PixelPacket
1911 % (and/or IndexPacket) array has been updated, the changes must be saved back
1912 % to the underlying image using SyncAuthenticPixels() or they may be lost.
1914 % The format of the GetAuthenticPixels() method is:
1916 % PixelPacket *GetAuthenticPixels(Image *image,const long x,const long y,
1917 % const unsigned long columns,const unsigned long rows,
1918 % ExceptionInfo *exception)
1920 % A description of each parameter follows:
1922 % o image: the image.
1924 % o x,y,columns,rows: These values define the perimeter of a region of
1927 % o exception: return any errors or warnings in this structure.
1930 MagickExport PixelPacket *GetAuthenticPixels(Image *image,const long x,
1931 const long y,const unsigned long columns,const unsigned long rows,
1932 ExceptionInfo *exception)
1940 assert(image != (Image *) NULL);
1941 assert(image->signature == MagickSignature);
1942 if (image->debug != MagickFalse)
1943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1944 assert(image->cache != (Cache) NULL);
1945 cache_info=(CacheInfo *) image->cache;
1946 assert(cache_info->signature == MagickSignature);
1947 if (cache_info->methods.get_authentic_pixels_handler ==
1948 (GetAuthenticPixelsHandler) NULL)
1949 return((PixelPacket *) NULL);
1950 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1960 + G e t A u t h e n t i c P i x e l s C a c h e %
1964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1966 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1967 % as defined by the geometry parameters. A pointer to the pixels is returned
1968 % if the pixels are transferred, otherwise a NULL is returned.
1970 % The format of the GetAuthenticPixelsCache() method is:
1972 % PixelPacket *GetAuthenticPixelsCache(Image *image,const long x,
1973 % const long y,const unsigned long columns,const unsigned long rows,
1974 % ExceptionInfo *exception)
1976 % A description of each parameter follows:
1978 % o image: the image.
1980 % o x,y,columns,rows: These values define the perimeter of a region of
1983 % o exception: return any errors or warnings in this structure.
1986 static PixelPacket *GetAuthenticPixelsCache(Image *image,const long x,
1987 const long y,const unsigned long columns,const unsigned long rows,
1988 ExceptionInfo *exception)
1999 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
2000 if (cache_info == (Cache) NULL)
2001 return((PixelPacket *) NULL);
2002 id=GetOpenMPThreadId();
2003 assert(id < (long) cache_info->number_threads);
2004 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
2005 cache_info->nexus_info[id],exception);
2010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2014 + G e t I m a g e E x t e n t %
2018 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2020 % GetImageExtent() returns the extent of the pixels associated with the
2021 % last call to QueueAuthenticPixels() or GetAuthenticPixels().
2023 % The format of the GetImageExtent() method is:
2025 % MagickSizeType GetImageExtent(const Image *image)
2027 % A description of each parameter follows:
2029 % o image: the image.
2032 MagickExport MagickSizeType GetImageExtent(const Image *image)
2043 assert(image != (Image *) NULL);
2044 assert(image->signature == MagickSignature);
2045 if (image->debug != MagickFalse)
2046 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2047 assert(image->cache != (Cache) NULL);
2048 cache_info=(CacheInfo *) image->cache;
2049 assert(cache_info->signature == MagickSignature);
2050 id=GetOpenMPThreadId();
2051 assert(id < (long) cache_info->number_threads);
2052 extent=GetPixelCacheNexusExtent(image->cache,cache_info->nexus_info[id]);
2057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2061 + G e t I m a g e P i x e l C a c h e %
2065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2067 % GetImagePixelCache() ensures that there is only a single reference to the
2068 % pixel cache to be modified, updating the provided cache pointer to point to
2069 % a clone of the original pixel cache if necessary.
2071 % The format of the GetImagePixelCache method is:
2073 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
2074 % ExceptionInfo *exception)
2076 % A description of each parameter follows:
2078 % o image: the image.
2080 % o clone: any value other than MagickFalse clones the cache pixels.
2082 % o exception: return any errors or warnings in this structure.
2086 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
2092 Does the image match the pixel cache morphology?
2094 cache_info=(CacheInfo *) image->cache;
2095 if ((image->storage_class != cache_info->storage_class) ||
2096 (image->colorspace != cache_info->colorspace) ||
2097 (image->columns != cache_info->columns) ||
2098 (image->rows != cache_info->rows) ||
2099 (cache_info->nexus_info == (NexusInfo **) NULL) ||
2100 (cache_info->number_threads < GetOpenMPMaximumThreads()))
2101 return(MagickFalse);
2105 MagickExport Cache GetImagePixelCache(Image *image,
2106 const MagickBooleanType clone,ExceptionInfo *exception)
2118 if (image->debug != MagickFalse)
2119 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2121 LockSemaphoreInfo(image->semaphore);
2122 time_limit=GetMagickResourceLimit(TimeResource);
2123 if (cache_timer == 0)
2124 cache_timer=time((time_t *) NULL);
2125 if ((time_limit != MagickResourceInfinity) &&
2126 ((MagickSizeType) (time((time_t *) NULL)-cache_timer) >= time_limit))
2127 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
2128 assert(image->cache != (Cache) NULL);
2129 cache_info=(CacheInfo *) image->cache;
2130 destroy=MagickFalse;
2131 LockSemaphoreInfo(cache_info->semaphore);
2132 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2143 clone_image=(*image);
2144 clone_image.cache=ClonePixelCache(cache_info);
2145 clone_info=(CacheInfo *) clone_image.cache;
2146 status=ClonePixelCacheNexus(cache_info,clone_info,exception);
2147 if (status != MagickFalse)
2149 status=OpenPixelCache(&clone_image,IOMode,exception);
2150 if (status != MagickFalse)
2152 if (clone != MagickFalse)
2153 status=ClonePixelCachePixels(clone_info,cache_info,exception);
2154 if (status != MagickFalse)
2157 image->cache=clone_image.cache;
2162 UnlockSemaphoreInfo(cache_info->semaphore);
2163 if (destroy != MagickFalse)
2164 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
2165 if (status != MagickFalse)
2168 Ensure the image matches the pixel cache morphology.
2170 image->taint=MagickTrue;
2171 image->type=UndefinedType;
2172 if (image->colorspace == GRAYColorspace)
2173 image->colorspace=RGBColorspace;
2174 if (ValidatePixelCacheMorphology(image) == MagickFalse)
2175 status=OpenPixelCache(image,IOMode,exception);
2177 UnlockSemaphoreInfo(image->semaphore);
2178 if (status == MagickFalse)
2179 return((Cache) NULL);
2180 return(image->cache);
2184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2188 % G e t O n e A u t h e n t i c P i x e l %
2192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2194 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2195 % location. The image background color is returned if an error occurs.
2197 % The format of the GetOneAuthenticPixel() method is:
2199 % MagickBooleanType GetOneAuthenticPixel(const Image image,const long x,
2200 % const long y,PixelPacket *pixel,ExceptionInfo *exception)
2202 % A description of each parameter follows:
2204 % o image: the image.
2206 % o x,y: These values define the location of the pixel to return.
2208 % o pixel: return a pixel at the specified (x,y) location.
2210 % o exception: return any errors or warnings in this structure.
2213 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,const long x,
2214 const long y,PixelPacket *pixel,ExceptionInfo *exception)
2219 GetOneAuthenticPixelFromHandler
2220 get_one_authentic_pixel_from_handler;
2225 assert(image != (Image *) NULL);
2226 assert(image->signature == MagickSignature);
2227 if (image->debug != MagickFalse)
2228 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2229 assert(image->cache != (Cache) NULL);
2230 cache_info=(CacheInfo *) image->cache;
2231 assert(cache_info->signature == MagickSignature);
2232 *pixel=image->background_color;
2233 get_one_authentic_pixel_from_handler=
2234 cache_info->methods.get_one_authentic_pixel_from_handler;
2235 if (get_one_authentic_pixel_from_handler ==
2236 (GetOneAuthenticPixelFromHandler) NULL)
2237 return(MagickFalse);
2238 status=cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2248 + 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 %
2252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2254 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2255 % location. The image background color is returned if an error occurs.
2257 % The format of the GetOneAuthenticPixelFromCache() method is:
2259 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2260 % const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
2262 % A description of each parameter follows:
2264 % o image: the image.
2266 % o x,y: These values define the location of the pixel to return.
2268 % o pixel: return a pixel at the specified (x,y) location.
2270 % o exception: return any errors or warnings in this structure.
2273 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2274 const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
2279 if (image->debug != MagickFalse)
2280 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2281 *pixel=image->background_color;
2282 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2283 if (pixels == (PixelPacket *) NULL)
2284 return(MagickFalse);
2290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2294 % G e t O n e V i r t u a l M a g i c k P i x e l %
2298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2300 % GetOneVirtualMagickPixel() returns a single pixel at the specified (x,y)
2301 % location. The image background color is returned if an error occurs. If
2302 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2304 % The format of the GetOneVirtualMagickPixel() method is:
2306 % MagickBooleanType GetOneVirtualMagickPixel(const Image image,
2307 % const long x,const long y,MagickPixelPacket *pixel,
2308 % ExceptionInfo exception)
2310 % A description of each parameter follows:
2312 % o image: the image.
2314 % o x,y: these values define the location of the pixel to return.
2316 % o pixel: return a pixel at the specified (x,y) location.
2318 % o exception: return any errors or warnings in this structure.
2321 MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
2322 const long x,const long y,MagickPixelPacket *pixel,ExceptionInfo *exception)
2327 register const IndexPacket
2330 register const PixelPacket
2333 assert(image != (const Image *) NULL);
2334 assert(image->signature == MagickSignature);
2335 assert(image->cache != (Cache) NULL);
2336 cache_info=(CacheInfo *) image->cache;
2337 assert(cache_info->signature == MagickSignature);
2338 GetMagickPixelPacket(image,pixel);
2339 p=GetVirtualPixelCache(image,GetPixelCacheVirtualMethod(image),x,y,1,1,
2341 if (p == (const PixelPacket *) NULL)
2342 return(MagickFalse);
2343 indexes=GetVirtualIndexQueue(image);
2344 SetMagickPixelPacket(image,p,indexes,pixel);
2349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2353 % G e t O n e V i r t u a l M e t h o d P i x e l %
2357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2359 % GetOneVirtualMethodPixel() returns a single pixel at the specified (x,y)
2360 % location as defined by specified pixel method. The image background color
2361 % is returned if an error occurs. If you plan to modify the pixel, use
2362 % GetOneAuthenticPixel() instead.
2364 % The format of the GetOneVirtualMethodPixel() method is:
2366 % MagickBooleanType GetOneVirtualMethodPixel(const Image image,
2367 % const VirtualPixelMethod virtual_pixel_method,const long x,
2368 % const long y,Pixelpacket *pixel,ExceptionInfo exception)
2370 % A description of each parameter follows:
2372 % o image: the image.
2374 % o virtual_pixel_method: the virtual pixel method.
2376 % o x,y: These values define the location of the pixel to return.
2378 % o pixel: return a pixel at the specified (x,y) location.
2380 % o exception: return any errors or warnings in this structure.
2383 MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
2384 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
2385 PixelPacket *pixel,ExceptionInfo *exception)
2387 GetOneVirtualPixelFromHandler
2388 get_one_virtual_pixel_from_handler;
2396 assert(image != (const Image *) NULL);
2397 assert(image->signature == MagickSignature);
2398 assert(image->cache != (Cache) NULL);
2399 cache_info=(CacheInfo *) image->cache;
2400 assert(cache_info->signature == MagickSignature);
2401 *pixel=image->background_color;
2402 get_one_virtual_pixel_from_handler=
2403 cache_info->methods.get_one_virtual_pixel_from_handler;
2404 if (get_one_virtual_pixel_from_handler ==
2405 (GetOneVirtualPixelFromHandler) NULL)
2406 return(MagickFalse);
2407 status=get_one_virtual_pixel_from_handler(image,virtual_pixel_method,x,y,
2413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2417 % G e t O n e V i r t u a l P i x e l %
2421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2423 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2424 % (x,y) location. The image background color is returned if an error occurs.
2425 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2427 % The format of the GetOneVirtualPixel() method is:
2429 % MagickBooleanType GetOneVirtualPixel(const Image image,const long x,
2430 % const long y,PixelPacket *pixel,ExceptionInfo exception)
2432 % A description of each parameter follows:
2434 % o image: the image.
2436 % o x,y: These values define the location of the pixel to return.
2438 % o pixel: return a pixel at the specified (x,y) location.
2440 % o exception: return any errors or warnings in this structure.
2443 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2444 const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
2446 GetOneVirtualPixelFromHandler
2447 get_one_virtual_pixel_from_handler;
2455 assert(image != (const Image *) NULL);
2456 assert(image->signature == MagickSignature);
2457 assert(image->cache != (Cache) NULL);
2458 cache_info=(CacheInfo *) image->cache;
2459 assert(cache_info->signature == MagickSignature);
2460 *pixel=image->background_color;
2461 get_one_virtual_pixel_from_handler=
2462 cache_info->methods.get_one_virtual_pixel_from_handler;
2463 if (get_one_virtual_pixel_from_handler ==
2464 (GetOneVirtualPixelFromHandler) NULL)
2465 return(MagickFalse);
2466 status=get_one_virtual_pixel_from_handler(image,GetPixelCacheVirtualMethod(
2467 image),x,y,pixel,exception);
2472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2476 + 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 %
2480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2482 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2483 % specified (x,y) location. The image background color is returned if an
2486 % The format of the GetOneVirtualPixelFromCache() method is:
2488 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2489 % const VirtualPixelPacket method,const long x,const long y,
2490 % PixelPacket *pixel,ExceptionInfo *exception)
2492 % A description of each parameter follows:
2494 % o image: the image.
2496 % o virtual_pixel_method: the virtual pixel method.
2498 % o x,y: These values define the location of the pixel to return.
2500 % o pixel: return a pixel at the specified (x,y) location.
2502 % o exception: return any errors or warnings in this structure.
2505 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2506 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
2507 PixelPacket *pixel,ExceptionInfo *exception)
2512 *pixel=image->background_color;
2513 pixels=GetVirtualPixelCache(image,virtual_pixel_method,x,y,1UL,1UL,exception);
2514 if (pixels == (const PixelPacket *) NULL)
2515 return(MagickFalse);
2521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2525 + G e t P i x e l C a c h e C o l o r s p a c e %
2529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2531 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2533 % The format of the GetPixelCacheColorspace() method is:
2535 % Colorspace GetPixelCacheColorspace(Cache cache)
2537 % A description of each parameter follows:
2539 % o cache: the pixel cache.
2542 MagickExport ColorspaceType GetPixelCacheColorspace(const Cache cache)
2547 assert(cache != (Cache) NULL);
2548 cache_info=(CacheInfo *) cache;
2549 assert(cache_info->signature == MagickSignature);
2550 if (cache_info->debug != MagickFalse)
2551 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2552 cache_info->filename);
2553 return(cache_info->colorspace);
2557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2561 + G e t P i x e l C a c h e M e t h o d s %
2565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2567 % GetPixelCacheMethods() initializes the CacheMethods structure.
2569 % The format of the GetPixelCacheMethods() method is:
2571 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2573 % A description of each parameter follows:
2575 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2578 MagickExport void GetPixelCacheMethods(CacheMethods *cache_methods)
2580 assert(cache_methods != (CacheMethods *) NULL);
2581 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2582 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2583 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2584 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2585 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2586 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2587 cache_methods->get_authentic_indexes_from_handler=
2588 GetAuthenticIndexesFromCache;
2589 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2590 cache_methods->get_one_authentic_pixel_from_handler=
2591 GetOneAuthenticPixelFromCache;
2592 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2593 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2594 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2602 + G e t P i x e l C a c h e N e x u s E x t e n t %
2606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2608 % GetPixelCacheNexusExtent() returns the extent of the pixels associated with
2609 % the last call to SetPixelCacheNexusPixels() or GetPixelCacheNexusPixels().
2611 % The format of the GetPixelCacheNexusExtent() method is:
2613 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2614 % NexusInfo *nexus_info)
2616 % A description of each parameter follows:
2618 % o nexus_info: the nexus info.
2621 MagickExport MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2622 NexusInfo *nexus_info)
2630 if (cache == (Cache) NULL)
2632 cache_info=(CacheInfo *) cache;
2633 assert(cache_info->signature == MagickSignature);
2634 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2636 return((MagickSizeType) cache_info->columns*cache_info->rows);
2641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2645 + 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 %
2649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2651 % GetPixelCacheNexusIndexes() returns the indexes associated with the
2652 % specified cache nexus.
2654 % The format of the GetPixelCacheNexusIndexes() method is:
2656 % IndexPacket *GetPixelCacheNexusIndexes(const Cache cache,
2657 % NexusInfo *nexus_info)
2659 % A description of each parameter follows:
2661 % o cache: the pixel cache.
2663 % o nexus_info: the cache nexus to return the colormap indexes.
2666 MagickExport IndexPacket *GetPixelCacheNexusIndexes(const Cache cache,
2667 NexusInfo *nexus_info)
2672 if (cache == (Cache) NULL)
2673 return((IndexPacket *) NULL);
2674 cache_info=(CacheInfo *) cache;
2675 assert(cache_info->signature == MagickSignature);
2676 if (cache_info->storage_class == UndefinedClass)
2677 return((IndexPacket *) NULL);
2678 return(nexus_info->indexes);
2682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2686 + G e t P i x e l C a c h e N e x u s P i x e l s %
2690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2692 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2695 % The format of the GetPixelCacheNexusPixels() method is:
2697 % PixelPacket *GetPixelCacheNexusPixels(const Cache cache,
2698 % NexusInfo *nexus_info)
2700 % A description of each parameter follows:
2702 % o cache: the pixel cache.
2704 % o nexus_info: the cache nexus to return the pixels.
2707 MagickExport PixelPacket *GetPixelCacheNexusPixels(const Cache cache,
2708 NexusInfo *nexus_info)
2713 if (cache == (Cache) NULL)
2714 return((PixelPacket *) NULL);
2715 cache_info=(CacheInfo *) cache;
2716 assert(cache_info->signature == MagickSignature);
2717 if (cache_info->debug != MagickFalse)
2718 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2719 cache_info->filename);
2720 if (cache_info->storage_class == UndefinedClass)
2721 return((PixelPacket *) NULL);
2722 return(nexus_info->pixels);
2726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2730 + G e t P i x e l C a c h e P i x e l s %
2734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2736 % GetPixelCachePixels() returns the pixels associated with the specified image.
2738 % The format of the GetPixelCachePixels() method is:
2740 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2741 % ExceptionInfo *exception)
2743 % A description of each parameter follows:
2745 % o image: the image.
2747 % o length: the pixel cache length.
2749 % o exception: return any errors or warnings in this structure.
2752 MagickExport void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2753 ExceptionInfo *exception)
2758 assert(image != (const Image *) NULL);
2759 assert(image->signature == MagickSignature);
2760 if (image->debug != MagickFalse)
2761 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2762 assert(image->cache != (Cache) NULL);
2763 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
2764 assert(cache_info->signature == MagickSignature);
2766 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2767 return((void *) NULL);
2768 *length=cache_info->length;
2769 return((void *) cache_info->pixels);
2773 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2777 + 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 %
2781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2783 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2785 % The format of the GetPixelCacheStorageClass() method is:
2787 % ClassType GetPixelCacheStorageClass(Cache cache)
2789 % A description of each parameter follows:
2791 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2793 % o cache: the pixel cache.
2796 MagickExport ClassType GetPixelCacheStorageClass(const Cache cache)
2801 assert(cache != (Cache) NULL);
2802 cache_info=(CacheInfo *) cache;
2803 assert(cache_info->signature == MagickSignature);
2804 if (cache_info->debug != MagickFalse)
2805 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2806 cache_info->filename);
2807 return(cache_info->storage_class);
2811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2815 + G e t P i x e l C a c h e T i l e S i z e %
2819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2821 % GetPixelCacheTileSize() returns the pixel cache tile size.
2823 % The format of the GetPixelCacheTileSize() method is:
2825 % void GetPixelCacheTileSize(const Image *image,unsigned long *width,
2826 % unsigned long *height)
2828 % A description of each parameter follows:
2830 % o image: the image.
2832 % o width: the optimize cache tile width in pixels.
2834 % o height: the optimize cache tile height in pixels.
2837 MagickExport void GetPixelCacheTileSize(const Image *image,unsigned long *width,
2838 unsigned long *height)
2843 assert(image != (Image *) NULL);
2844 assert(image->signature == MagickSignature);
2845 if (image->debug != MagickFalse)
2846 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2847 assert(image->cache != (Cache) NULL);
2848 cache_info=(CacheInfo *) image->cache;
2849 assert(cache_info->signature == MagickSignature);
2850 *width=2048UL/sizeof(PixelPacket);
2851 if (GetPixelCacheType(image) == DiskCache)
2852 *width=8192UL/sizeof(PixelPacket);
2857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2861 + G e t P i x e l C a c h e T y p e %
2865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2867 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2869 % The format of the GetPixelCacheType() method is:
2871 % CacheType GetPixelCacheType(const Image *image)
2873 % A description of each parameter follows:
2875 % o image: the image.
2878 MagickExport CacheType GetPixelCacheType(const Image *image)
2883 assert(image != (Image *) NULL);
2884 assert(image->signature == MagickSignature);
2885 if (image->debug != MagickFalse)
2886 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2887 assert(image->cache != (Cache) NULL);
2888 cache_info=(CacheInfo *) image->cache;
2889 assert(cache_info->signature == MagickSignature);
2890 return(cache_info->type);
2894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2898 + 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 %
2902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2904 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2905 % pixel cache. A virtual pixel is any pixel access that is outside the
2906 % boundaries of the image cache.
2908 % The format of the GetPixelCacheVirtualMethod() method is:
2910 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2912 % A description of each parameter follows:
2914 % o image: the image.
2917 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2922 assert(image != (Image *) NULL);
2923 assert(image->signature == MagickSignature);
2924 if (image->debug != MagickFalse)
2925 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2926 assert(image->cache != (Cache) NULL);
2927 cache_info=(CacheInfo *) image->cache;
2928 assert(cache_info->signature == MagickSignature);
2929 return(cache_info->virtual_pixel_method);
2933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2937 + 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 %
2941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2943 % GetVirtualIndexesFromCache() returns the indexes associated with the last
2944 % call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2946 % The format of the GetVirtualIndexesFromCache() method is:
2948 % IndexPacket *GetVirtualIndexesFromCache(const Image *image)
2950 % A description of each parameter follows:
2952 % o image: the image.
2955 static const IndexPacket *GetVirtualIndexesFromCache(const Image *image)
2966 if (image->debug != MagickFalse)
2967 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2968 cache_info=(CacheInfo *) image->cache;
2969 id=GetOpenMPThreadId();
2970 assert(id < (long) cache_info->number_threads);
2971 indexes=GetVirtualIndexesFromNexus(image->cache,cache_info->nexus_info[id]);
2976 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2980 + 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 %
2984 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2986 % GetVirtualIndexesFromNexus() returns the indexes associated with the
2987 % specified cache nexus.
2989 % The format of the GetVirtualIndexesFromNexus() method is:
2991 % const IndexPacket *GetVirtualIndexesFromNexus(const Cache cache,
2992 % NexusInfo *nexus_info)
2994 % A description of each parameter follows:
2996 % o cache: the pixel cache.
2998 % o nexus_info: the cache nexus to return the colormap indexes.
3001 MagickExport const IndexPacket *GetVirtualIndexesFromNexus(const Cache cache,
3002 NexusInfo *nexus_info)
3007 if (cache == (Cache) NULL)
3008 return((IndexPacket *) NULL);
3009 cache_info=(CacheInfo *) cache;
3010 assert(cache_info->signature == MagickSignature);
3011 if (cache_info->storage_class == UndefinedClass)
3012 return((IndexPacket *) NULL);
3013 return(nexus_info->indexes);
3017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3021 % G e t V i r t u a l I n d e x Q u e u e %
3025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3027 % GetVirtualIndexQueue() returns the virtual black channel or the
3028 % colormap indexes associated with the last call to QueueAuthenticPixels() or
3029 % GetVirtualPixels(). NULL is returned if the black channel or colormap
3030 % indexes are not available.
3032 % The format of the GetVirtualIndexQueue() method is:
3034 % const IndexPacket *GetVirtualIndexQueue(const Image *image)
3036 % A description of each parameter follows:
3038 % o image: the image.
3041 MagickExport const IndexPacket *GetVirtualIndexQueue(const Image *image)
3046 assert(image != (const Image *) NULL);
3047 assert(image->signature == MagickSignature);
3048 if (image->debug != MagickFalse)
3049 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3050 assert(image->cache != (Cache) NULL);
3051 cache_info=(CacheInfo *) image->cache;
3052 assert(cache_info->signature == MagickSignature);
3053 if (cache_info->methods.get_virtual_indexes_from_handler ==
3054 (GetVirtualIndexesFromHandler) NULL)
3055 return((IndexPacket *) NULL);
3056 return(cache_info->methods.get_virtual_indexes_from_handler(image));
3060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3064 + 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 %
3068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3070 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
3071 % pixel cache as defined by the geometry parameters. A pointer to the pixels
3072 % is returned if the pixels are transferred, otherwise a NULL is returned.
3074 % The format of the GetVirtualPixelsFromNexus() method is:
3076 % PixelPacket *GetVirtualPixelsFromNexus(const Image *image,
3077 % const VirtualPixelMethod method,const long x,const long y,
3078 % const unsigned long columns,const unsigned long rows,
3079 % NexusInfo *nexus_info,ExceptionInfo *exception)
3081 % A description of each parameter follows:
3083 % o image: the image.
3085 % o virtual_pixel_method: the virtual pixel method.
3087 % o x,y,columns,rows: These values define the perimeter of a region of
3090 % o nexus_info: the cache nexus to acquire.
3092 % o exception: return any errors or warnings in this structure.
3099 0, 48, 12, 60, 3, 51, 15, 63,
3100 32, 16, 44, 28, 35, 19, 47, 31,
3101 8, 56, 4, 52, 11, 59, 7, 55,
3102 40, 24, 36, 20, 43, 27, 39, 23,
3103 2, 50, 14, 62, 1, 49, 13, 61,
3104 34, 18, 46, 30, 33, 17, 45, 29,
3105 10, 58, 6, 54, 9, 57, 5, 53,
3106 42, 26, 38, 22, 41, 25, 37, 21
3109 static inline long DitherX(const long x,const unsigned long columns)
3114 index=x+DitherMatrix[x & 0x07]-32L;
3117 if (index >= (long) columns)
3118 return((long) columns-1L);
3122 static inline long DitherY(const long y,const unsigned long rows)
3127 index=y+DitherMatrix[y & 0x07]-32L;
3130 if (index >= (long) rows)
3131 return((long) rows-1L);
3135 static inline long EdgeX(const long x,const unsigned long columns)
3139 if (x >= (long) columns)
3140 return((long) (columns-1));
3144 static inline long EdgeY(const long y,const unsigned long rows)
3148 if (y >= (long) rows)
3149 return((long) (rows-1));
3153 static inline long RandomX(RandomInfo *random_info,const unsigned long columns)
3155 return((long) (columns*GetPseudoRandomValue(random_info)));
3158 static inline long RandomY(RandomInfo *random_info,const unsigned long rows)
3160 return((long) (rows*GetPseudoRandomValue(random_info)));
3164 VirtualPixelModulo() computes the remainder of dividing offset by extent. It
3165 returns not only the quotient (tile the offset falls in) but also the positive
3166 remainer within that tile such that 0 <= remainder < extent. This method is
3167 essentially a ldiv() using a floored modulo division rather than the normal
3168 default truncated modulo division.
3170 static inline MagickModulo VirtualPixelModulo(const long offset,
3171 const unsigned long extent)
3176 modulo.quotient=offset/(long) extent;
3179 modulo.remainder=offset-modulo.quotient*(long) extent;
3183 MagickExport const PixelPacket *GetVirtualPixelsFromNexus(const Image *image,
3184 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
3185 const unsigned long columns,const unsigned long rows,NexusInfo *nexus_info,
3186 ExceptionInfo *exception)
3208 register const IndexPacket
3209 *restrict nexus_indexes;
3211 register const PixelPacket
3214 register IndexPacket
3221 register PixelPacket
3227 if (image->debug != MagickFalse)
3228 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3229 cache_info=(CacheInfo *) image->cache;
3230 if (cache_info->type == UndefinedCache)
3231 return((const PixelPacket *) NULL);
3234 region.width=columns;
3236 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3237 if (pixels == (PixelPacket *) NULL)
3238 return((const PixelPacket *) NULL);
3239 offset=(MagickOffsetType) region.y*cache_info->columns+region.x;
3240 length=(MagickSizeType) (region.height-1L)*cache_info->columns+
3242 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3243 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3244 if ((x >= 0) && ((long) (x+columns) <= (long) cache_info->columns) &&
3245 (y >= 0) && ((long) (y+rows) <= (long) cache_info->rows))
3251 Pixel request is inside cache extents.
3253 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
3255 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3256 if (status == MagickFalse)
3257 return((const PixelPacket *) NULL);
3258 if ((cache_info->storage_class == PseudoClass) ||
3259 (cache_info->colorspace == CMYKColorspace))
3261 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3262 if (status == MagickFalse)
3263 return((const PixelPacket *) NULL);
3268 Pixel request is outside cache extents.
3271 indexes=GetPixelCacheNexusIndexes(cache_info,nexus_info);
3272 virtual_nexus=AcquirePixelCacheNexus(1);
3273 if (virtual_nexus == (NexusInfo **) NULL)
3275 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3276 "UnableToGetCacheNexus","`%s'",image->filename);
3277 return((const PixelPacket *) NULL);
3279 switch (virtual_pixel_method)
3281 case BlackVirtualPixelMethod:
3283 SetRedPixelComponent(&virtual_pixel,0);
3284 SetGreenPixelComponent(&virtual_pixel,0);
3285 SetBluePixelComponent(&virtual_pixel,0);
3286 SetOpacityPixelComponent(&virtual_pixel,OpaqueOpacity);
3289 case GrayVirtualPixelMethod:
3291 SetRedPixelComponent(&virtual_pixel,(Quantum) QuantumRange/2);
3292 SetGreenPixelComponent(&virtual_pixel,(Quantum) QuantumRange/2);
3293 SetBluePixelComponent(&virtual_pixel,(Quantum) QuantumRange/2);
3294 SetOpacityPixelComponent(&virtual_pixel,OpaqueOpacity);
3297 case TransparentVirtualPixelMethod:
3299 SetRedPixelComponent(&virtual_pixel,0);
3300 SetGreenPixelComponent(&virtual_pixel,0);
3301 SetBluePixelComponent(&virtual_pixel,0);
3302 SetOpacityPixelComponent(&virtual_pixel,TransparentOpacity);
3305 case MaskVirtualPixelMethod:
3306 case WhiteVirtualPixelMethod:
3308 SetRedPixelComponent(&virtual_pixel,(Quantum) QuantumRange);
3309 SetGreenPixelComponent(&virtual_pixel,(Quantum) QuantumRange);
3310 SetBluePixelComponent(&virtual_pixel,(Quantum) QuantumRange);
3311 SetOpacityPixelComponent(&virtual_pixel,OpaqueOpacity);
3316 virtual_pixel=image->background_color;
3320 for (v=0; v < (long) rows; v++)
3322 for (u=0; u < (long) columns; u+=length)
3324 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3325 if ((((x+u) < 0) || ((x+u) >= (long) cache_info->columns)) ||
3326 (((y+v) < 0) || ((y+v) >= (long) cache_info->rows)) || (length == 0))
3333 Transfer a single pixel.
3335 length=(MagickSizeType) 1;
3336 switch (virtual_pixel_method)
3338 case BackgroundVirtualPixelMethod:
3339 case ConstantVirtualPixelMethod:
3340 case BlackVirtualPixelMethod:
3341 case GrayVirtualPixelMethod:
3342 case TransparentVirtualPixelMethod:
3343 case MaskVirtualPixelMethod:
3344 case WhiteVirtualPixelMethod:
3349 case EdgeVirtualPixelMethod:
3352 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3353 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3354 1UL,1UL,virtual_nexus[0],exception);
3357 case RandomVirtualPixelMethod:
3359 if (cache_info->random_info == (RandomInfo *) NULL)
3360 cache_info->random_info=AcquireRandomInfo();
3361 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3362 RandomX(cache_info->random_info,cache_info->columns),
3363 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3364 virtual_nexus[0],exception);
3367 case DitherVirtualPixelMethod:
3369 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3370 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3371 1UL,1UL,virtual_nexus[0],exception);
3374 case TileVirtualPixelMethod:
3376 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3377 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3378 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3379 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3383 case MirrorVirtualPixelMethod:
3385 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3386 if ((x_modulo.quotient & 0x01) == 1L)
3387 x_modulo.remainder=(long) cache_info->columns-
3388 x_modulo.remainder-1L;
3389 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3390 if ((y_modulo.quotient & 0x01) == 1L)
3391 y_modulo.remainder=(long) cache_info->rows-
3392 y_modulo.remainder-1L;
3393 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3394 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3398 case CheckerTileVirtualPixelMethod:
3400 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3401 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3402 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3407 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3408 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3412 case HorizontalTileVirtualPixelMethod:
3414 if (((y+v) < 0) || ((y+v) >= (long) cache_info->rows))
3419 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3420 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3421 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3422 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3426 case VerticalTileVirtualPixelMethod:
3428 if (((x+u) < 0) || ((x+u) >= (long) cache_info->columns))
3433 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3434 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3435 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3436 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
3440 case HorizontalTileEdgeVirtualPixelMethod:
3442 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3443 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3444 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3445 virtual_nexus[0],exception);
3448 case VerticalTileEdgeVirtualPixelMethod:
3450 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3451 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3452 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3453 virtual_nexus[0],exception);
3457 if (p == (const PixelPacket *) NULL)
3460 if (indexes != (IndexPacket *) NULL)
3462 nexus_indexes=GetVirtualIndexesFromNexus(cache_info,
3464 if (nexus_indexes != (const IndexPacket *) NULL)
3465 *indexes++=(*nexus_indexes);
3470 Transfer a run of pixels.
3472 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,
3473 (unsigned long) length,1UL,virtual_nexus[0],exception);
3474 if (p == (const PixelPacket *) NULL)
3476 (void) CopyMagickMemory(q,p,(size_t) length*sizeof(*p));
3478 if (indexes != (IndexPacket *) NULL)
3480 nexus_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus[0]);
3481 if (nexus_indexes != (const IndexPacket *) NULL)
3483 (void) CopyMagickMemory(indexes,nexus_indexes,(size_t) length*
3484 sizeof(*nexus_indexes));
3490 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3499 + G e t V i r t u a l P i x e l C a c h e %
3503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3505 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3506 % cache as defined by the geometry parameters. A pointer to the pixels
3507 % is returned if the pixels are transferred, otherwise a NULL is returned.
3509 % The format of the GetVirtualPixelCache() method is:
3511 % const PixelPacket *GetVirtualPixelCache(const Image *image,
3512 % const VirtualPixelMethod virtual_pixel_method,const long x,
3513 % const long y,const unsigned long columns,const unsigned long rows,
3514 % ExceptionInfo *exception)
3516 % A description of each parameter follows:
3518 % o image: the image.
3520 % o virtual_pixel_method: the virtual pixel method.
3522 % o x,y,columns,rows: These values define the perimeter of a region of
3525 % o exception: return any errors or warnings in this structure.
3528 static const PixelPacket *GetVirtualPixelCache(const Image *image,
3529 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
3530 const unsigned long columns,const unsigned long rows,ExceptionInfo *exception)
3541 if (image->debug != MagickFalse)
3542 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3543 cache_info=(CacheInfo *) image->cache;
3544 id=GetOpenMPThreadId();
3545 assert(id < (long) cache_info->number_threads);
3546 pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3547 cache_info->nexus_info[id],exception);
3552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3556 % G e t V i r t u a l P i x e l Q u e u e %
3560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3562 % GetVirtualPixelQueue() returns the virtual pixels associated with the
3563 % last call to QueueAuthenticPixels() or GetVirtualPixels().
3565 % The format of the GetVirtualPixelQueue() method is:
3567 % const PixelPacket *GetVirtualPixelQueue(const Image image)
3569 % A description of each parameter follows:
3571 % o image: the image.
3574 MagickExport const PixelPacket *GetVirtualPixelQueue(const Image *image)
3579 assert(image != (const Image *) NULL);
3580 assert(image->signature == MagickSignature);
3581 if (image->debug != MagickFalse)
3582 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3583 assert(image->cache != (Cache) NULL);
3584 cache_info=(CacheInfo *) image->cache;
3585 assert(cache_info->signature == MagickSignature);
3586 if (cache_info->methods.get_virtual_pixels_handler ==
3587 (GetVirtualPixelsHandler) NULL)
3588 return((PixelPacket *) NULL);
3589 return(cache_info->methods.get_virtual_pixels_handler(image));
3593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3597 % G e t V i r t u a l P i x e l s %
3601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3603 % GetVirtualPixels() returns an immutable pixel region. If the
3604 % region is successfully accessed, a pointer to it is returned, otherwise
3605 % NULL is returned. The returned pointer may point to a temporary working
3606 % copy of the pixels or it may point to the original pixels in memory.
3607 % Performance is maximized if the selected region is part of one row, or one
3608 % or more full rows, since there is opportunity to access the pixels in-place
3609 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3610 % returned pointer must *never* be deallocated by the user.
3612 % Pixels accessed via the returned pointer represent a simple array of type
3613 % PixelPacket. If the image type is CMYK or the storage class is PseudoClass,
3614 % call GetAuthenticIndexQueue() after invoking GetAuthenticPixels() to access
3615 % the black color component or to obtain the colormap indexes (of type
3616 % IndexPacket) corresponding to the region.
3618 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3620 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3621 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3622 % GetCacheViewAuthenticPixels() instead.
3624 % The format of the GetVirtualPixels() method is:
3626 % const PixelPacket *GetVirtualPixels(const Image *image,const long x,
3627 % const long y,const unsigned long columns,const unsigned long rows,
3628 % ExceptionInfo *exception)
3630 % A description of each parameter follows:
3632 % o image: the image.
3634 % o x,y,columns,rows: These values define the perimeter of a region of
3637 % o exception: return any errors or warnings in this structure.
3640 MagickExport const PixelPacket *GetVirtualPixels(const Image *image,
3641 const long x,const long y,const unsigned long columns,
3642 const unsigned long rows,ExceptionInfo *exception)
3650 assert(image != (const Image *) NULL);
3651 assert(image->signature == MagickSignature);
3652 if (image->debug != MagickFalse)
3653 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3654 assert(image->cache != (Cache) NULL);
3655 cache_info=(CacheInfo *) image->cache;
3656 assert(cache_info->signature == MagickSignature);
3657 if (cache_info->methods.get_virtual_pixel_handler ==
3658 (GetVirtualPixelHandler) NULL)
3659 return((const PixelPacket *) NULL);
3660 pixels=cache_info->methods.get_virtual_pixel_handler(image,
3661 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception);
3666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3670 + 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 %
3674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3676 % GetVirtualPixelsCache() returns the pixels associated with the last call
3677 % to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3679 % The format of the GetVirtualPixelsCache() method is:
3681 % PixelPacket *GetVirtualPixelsCache(const Image *image)
3683 % A description of each parameter follows:
3685 % o image: the image.
3688 static const PixelPacket *GetVirtualPixelsCache(const Image *image)
3699 if (image->debug != MagickFalse)
3700 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3701 cache_info=(CacheInfo *) image->cache;
3702 id=GetOpenMPThreadId();
3703 assert(id < (long) cache_info->number_threads);
3704 pixels=GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]);
3709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3713 + G e t V i r t u a l P i x e l s N e x u s %
3717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3719 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3722 % The format of the GetVirtualPixelsNexus() method is:
3724 % const IndexPacket *GetVirtualPixelsNexus(const Cache cache,
3725 % NexusInfo *nexus_info)
3727 % A description of each parameter follows:
3729 % o cache: the pixel cache.
3731 % o nexus_info: the cache nexus to return the colormap pixels.
3734 MagickExport const PixelPacket *GetVirtualPixelsNexus(const Cache cache,
3735 NexusInfo *nexus_info)
3740 if (cache == (Cache) NULL)
3741 return((PixelPacket *) NULL);
3742 cache_info=(CacheInfo *) cache;
3743 assert(cache_info->signature == MagickSignature);
3744 if (cache_info->storage_class == UndefinedClass)
3745 return((PixelPacket *) NULL);
3746 return((const PixelPacket *) nexus_info->pixels);
3750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3754 + M a s k P i x e l C a c h e N e x u s %
3758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3760 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3761 % The method returns MagickTrue if the pixel region is masked, otherwise
3764 % The format of the MaskPixelCacheNexus() method is:
3766 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3767 % NexusInfo *nexus_info,ExceptionInfo *exception)
3769 % A description of each parameter follows:
3771 % o image: the image.
3773 % o nexus_info: the cache nexus to clip.
3775 % o exception: return any errors or warnings in this structure.
3779 static inline void MagickPixelCompositeMask(const MagickPixelPacket *p,
3780 const MagickRealType alpha,const MagickPixelPacket *q,
3781 const MagickRealType beta,MagickPixelPacket *composite)
3786 if (alpha == TransparentOpacity)
3791 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3792 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3793 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3794 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3795 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3796 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3797 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3800 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3801 ExceptionInfo *exception)
3817 register const PixelPacket
3820 register IndexPacket
3821 *restrict nexus_indexes,
3827 register PixelPacket
3834 if (image->debug != MagickFalse)
3835 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3836 if (image->mask == (Image *) NULL)
3837 return(MagickFalse);
3838 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
3839 if (cache_info == (Cache) NULL)
3840 return(MagickFalse);
3841 image_nexus=AcquirePixelCacheNexus(1);
3842 clip_nexus=AcquirePixelCacheNexus(1);
3843 if ((image_nexus == (NexusInfo **) NULL) ||
3844 (clip_nexus == (NexusInfo **) NULL))
3845 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3846 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3847 nexus_info->region.width,nexus_info->region.height,image_nexus[0],
3849 indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
3850 q=nexus_info->pixels;
3851 nexus_indexes=nexus_info->indexes;
3852 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3853 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3854 nexus_info->region.height,clip_nexus[0],&image->exception);
3855 GetMagickPixelPacket(image,&alpha);
3856 GetMagickPixelPacket(image,&beta);
3857 number_pixels=(MagickSizeType) nexus_info->region.width*
3858 nexus_info->region.height;
3859 for (i=0; i < (long) number_pixels; i++)
3861 if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
3863 SetMagickPixelPacket(image,p,indexes+i,&alpha);
3864 SetMagickPixelPacket(image,q,nexus_indexes+i,&beta);
3865 MagickPixelCompositeMask(&beta,(MagickRealType) PixelIntensityToQuantum(r),
3866 &alpha,alpha.opacity,&beta);
3867 q->red=ClampToQuantum(beta.red);
3868 q->green=ClampToQuantum(beta.green);
3869 q->blue=ClampToQuantum(beta.blue);
3870 q->opacity=ClampToQuantum(beta.opacity);
3871 if (cache_info->active_index_channel != MagickFalse)
3872 nexus_indexes[i]=indexes[i];
3877 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3878 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3879 if (i < (long) number_pixels)
3880 return(MagickFalse);
3885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3889 + O p e n P i x e l C a c h e %
3893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3895 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3896 % dimensions, allocating space for the image pixels and optionally the
3897 % colormap indexes, and memory mapping the cache if it is disk based. The
3898 % cache nexus array is initialized as well.
3900 % The format of the OpenPixelCache() method is:
3902 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3903 % ExceptionInfo *exception)
3905 % A description of each parameter follows:
3907 % o image: the image.
3909 % o mode: ReadMode, WriteMode, or IOMode.
3911 % o exception: return any errors or warnings in this structure.
3915 static inline void AcquirePixelCachePixels(CacheInfo *cache_info)
3917 cache_info->mapped=MagickFalse;
3918 cache_info->pixels=(PixelPacket *) AcquireMagickMemory((size_t)
3919 cache_info->length);
3920 if (cache_info->pixels == (PixelPacket *) NULL)
3922 cache_info->mapped=MagickTrue;
3923 cache_info->pixels=(PixelPacket *) MapBlob(-1,IOMode,0,(size_t)
3924 cache_info->length);
3928 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3938 cache_info=(CacheInfo *) image->cache;
3939 if (image->debug != MagickFalse)
3942 format[MaxTextExtent],
3943 message[MaxTextExtent];
3945 (void) FormatMagickSize(length,MagickFalse,format);
3946 (void) FormatMagickString(message,MaxTextExtent,
3947 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3948 cache_info->cache_filename,cache_info->file,format);
3949 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3951 if (length != (MagickSizeType) ((MagickOffsetType) length))
3952 return(MagickFalse);
3953 extent=(MagickOffsetType) MagickSeek(cache_info->file,0,SEEK_END);
3955 return(MagickFalse);
3956 if ((MagickSizeType) extent >= length)
3958 offset=(MagickOffsetType) length-1;
3959 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3960 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3963 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3964 ExceptionInfo *exception)
3967 format[MaxTextExtent],
3968 message[MaxTextExtent];
3987 if (image->debug != MagickFalse)
3988 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3989 if ((image->columns == 0) || (image->rows == 0))
3990 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3991 cache_info=(CacheInfo *) image->cache;
3992 source_info=(*cache_info);
3993 source_info.file=(-1);
3994 (void) FormatMagickString(cache_info->filename,MaxTextExtent,"%s[%ld]",
3995 image->filename,GetImageIndexInList(image));
3996 cache_info->mode=mode;
3997 cache_info->rows=image->rows;
3998 cache_info->columns=image->columns;
3999 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
4000 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
4001 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4002 packet_size=sizeof(PixelPacket);
4003 if (cache_info->active_index_channel != MagickFalse)
4004 packet_size+=sizeof(IndexPacket);
4005 length=number_pixels*packet_size;
4006 columns=(unsigned long) (length/cache_info->rows/packet_size);
4007 if (cache_info->columns != columns)
4008 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4010 cache_info->length=length;
4011 status=AcquireMagickResource(AreaResource,cache_info->length);
4012 length=number_pixels*(sizeof(PixelPacket)+sizeof(IndexPacket));
4013 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4015 status=AcquireMagickResource(MemoryResource,cache_info->length);
4016 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4017 (cache_info->type == MemoryCache))
4019 AcquirePixelCachePixels(cache_info);
4020 if (cache_info->pixels == (PixelPacket *) NULL)
4021 cache_info->pixels=source_info.pixels;
4025 Create memory pixel cache.
4027 if (image->debug != MagickFalse)
4029 (void) FormatMagickSize(cache_info->length,MagickTrue,
4031 (void) FormatMagickString(message,MaxTextExtent,
4032 "open %s (%s memory, %lux%lu %s)",cache_info->filename,
4033 cache_info->mapped != MagickFalse ? "anonymous" : "heap",
4034 cache_info->columns,cache_info->rows,format);
4035 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4038 cache_info->storage_class=image->storage_class;
4039 cache_info->colorspace=image->colorspace;
4040 cache_info->type=MemoryCache;
4041 cache_info->indexes=(IndexPacket *) NULL;
4042 if (cache_info->active_index_channel != MagickFalse)
4043 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4045 if (source_info.storage_class != UndefinedClass)
4047 status|=ClonePixelCachePixels(cache_info,&source_info,
4049 RelinquishPixelCachePixels(&source_info);
4054 RelinquishMagickResource(MemoryResource,cache_info->length);
4057 Create pixel cache on disk.
4059 status=AcquireMagickResource(DiskResource,cache_info->length);
4060 if (status == MagickFalse)
4062 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4063 "CacheResourcesExhausted","`%s'",image->filename);
4064 return(MagickFalse);
4066 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4068 RelinquishMagickResource(DiskResource,cache_info->length);
4069 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4071 return(MagickFalse);
4073 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4074 cache_info->length);
4075 if (status == MagickFalse)
4077 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4079 return(MagickFalse);
4081 cache_info->storage_class=image->storage_class;
4082 cache_info->colorspace=image->colorspace;
4083 length=number_pixels*(sizeof(PixelPacket)+sizeof(IndexPacket));
4084 status=AcquireMagickResource(AreaResource,cache_info->length);
4085 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
4086 cache_info->type=DiskCache;
4089 status=AcquireMagickResource(MapResource,cache_info->length);
4090 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4091 (cache_info->type != MemoryCache))
4092 cache_info->type=DiskCache;
4095 cache_info->pixels=(PixelPacket *) MapBlob(cache_info->file,mode,
4096 cache_info->offset,(size_t) cache_info->length);
4097 if (cache_info->pixels == (PixelPacket *) NULL)
4099 cache_info->pixels=source_info.pixels;
4100 cache_info->type=DiskCache;
4105 Create file-backed memory-mapped pixel cache.
4107 (void) ClosePixelCacheOnDisk(cache_info);
4108 cache_info->type=MapCache;
4109 cache_info->mapped=MagickTrue;
4110 cache_info->indexes=(IndexPacket *) NULL;
4111 if (cache_info->active_index_channel != MagickFalse)
4112 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4114 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4116 status=ClonePixelCachePixels(cache_info,&source_info,
4118 RelinquishPixelCachePixels(&source_info);
4120 if (image->debug != MagickFalse)
4122 (void) FormatMagickSize(cache_info->length,MagickTrue,
4124 (void) FormatMagickString(message,MaxTextExtent,
4125 "open %s (%s[%d], memory-mapped, %lux%lu %s)",
4126 cache_info->filename,cache_info->cache_filename,
4127 cache_info->file,cache_info->columns,cache_info->rows,
4129 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4135 RelinquishMagickResource(MapResource,cache_info->length);
4137 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4139 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4140 RelinquishPixelCachePixels(&source_info);
4142 if (image->debug != MagickFalse)
4144 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4145 (void) FormatMagickString(message,MaxTextExtent,
4146 "open %s (%s[%d], disk, %lux%lu %s)",cache_info->filename,
4147 cache_info->cache_filename,cache_info->file,cache_info->columns,
4148 cache_info->rows,format);
4149 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4159 + P e r s i s t P i x e l C a c h e %
4163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4165 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4166 % persistent pixel cache is one that resides on disk and is not destroyed
4167 % when the program exits.
4169 % The format of the PersistPixelCache() method is:
4171 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4172 % const MagickBooleanType attach,MagickOffsetType *offset,
4173 % ExceptionInfo *exception)
4175 % A description of each parameter follows:
4177 % o image: the image.
4179 % o filename: the persistent pixel cache filename.
4181 % o attach: A value other than zero initializes the persistent pixel
4184 % o initialize: A value other than zero initializes the persistent pixel
4187 % o offset: the offset in the persistent cache to store pixels.
4189 % o exception: return any errors or warnings in this structure.
4192 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4193 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4194 ExceptionInfo *exception)
4209 assert(image != (Image *) NULL);
4210 assert(image->signature == MagickSignature);
4211 if (image->debug != MagickFalse)
4212 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4213 assert(image->cache != (void *) NULL);
4214 assert(filename != (const char *) NULL);
4215 assert(offset != (MagickOffsetType *) NULL);
4216 page_size=GetMagickPageSize();
4217 cache_info=(CacheInfo *) image->cache;
4218 assert(cache_info->signature == MagickSignature);
4219 if (attach != MagickFalse)
4222 Attach existing persistent pixel cache.
4224 if (image->debug != MagickFalse)
4225 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4226 "attach persistent cache");
4227 (void) CopyMagickString(cache_info->cache_filename,filename,
4229 cache_info->type=DiskCache;
4230 cache_info->offset=(*offset);
4231 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4232 return(MagickFalse);
4233 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4236 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4237 (cache_info->reference_count == 1))
4239 LockSemaphoreInfo(cache_info->semaphore);
4240 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4241 (cache_info->reference_count == 1))
4247 Usurp existing persistent pixel cache.
4249 status=rename(cache_info->cache_filename,filename);
4252 (void) CopyMagickString(cache_info->cache_filename,filename,
4254 *offset+=cache_info->length+page_size-(cache_info->length %
4256 UnlockSemaphoreInfo(cache_info->semaphore);
4257 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4258 if (image->debug != MagickFalse)
4259 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4260 "Usurp resident persistent cache");
4264 UnlockSemaphoreInfo(cache_info->semaphore);
4267 Clone persistent pixel cache.
4269 clone_image=(*image);
4270 clone_info=(CacheInfo *) clone_image.cache;
4271 image->cache=ClonePixelCache(cache_info);
4272 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4273 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4274 cache_info->type=DiskCache;
4275 cache_info->offset=(*offset);
4276 cache_info=(CacheInfo *) image->cache;
4277 status=ClonePixelCacheNexus(cache_info,clone_info,exception);
4278 if (status != MagickFalse)
4280 status=OpenPixelCache(image,IOMode,exception);
4281 if (status != MagickFalse)
4282 status=ClonePixelCachePixels(cache_info,clone_info,&image->exception);
4284 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4285 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4294 + Q u e u e A u t h e n t i c N e x u s %
4298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4300 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4301 % by the region rectangle and returns a pointer to the region. This region is
4302 % subsequently transferred from the pixel cache with
4303 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4304 % pixels are transferred, otherwise a NULL is returned.
4306 % The format of the QueueAuthenticNexus() method is:
4308 % PixelPacket *QueueAuthenticNexus(Image *image,const long x,const long y,
4309 % const unsigned long columns,const unsigned long rows,
4310 % NexusInfo *nexus_info,ExceptionInfo *exception)
4312 % A description of each parameter follows:
4314 % o image: the image.
4316 % o x,y,columns,rows: These values define the perimeter of a region of
4319 % o nexus_info: the cache nexus to set.
4321 % o exception: return any errors or warnings in this structure.
4324 MagickExport PixelPacket *QueueAuthenticNexus(Image *image,const long x,
4325 const long y,const unsigned long columns,const unsigned long rows,
4326 NexusInfo *nexus_info,ExceptionInfo *exception)
4341 Validate pixel cache geometry.
4343 cache_info=(CacheInfo *) image->cache;
4344 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4346 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4347 "NoPixelsDefinedInCache","`%s'",image->filename);
4348 return((PixelPacket *) NULL);
4350 if ((x < 0) || (y < 0) || (x >= (long) cache_info->columns) ||
4351 (y >= (long) cache_info->rows))
4353 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4354 "PixelsAreNotAuthentic","`%s'",image->filename);
4355 return((PixelPacket *) NULL);
4357 offset=(MagickOffsetType) y*cache_info->columns+x;
4359 return((PixelPacket *) NULL);
4360 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4361 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4362 if ((MagickSizeType) offset >= number_pixels)
4363 return((PixelPacket *) NULL);
4369 region.width=columns;
4371 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4379 + Q u e u e A u t h e n t i c P i x e l s C a c h e %
4383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4385 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4386 % defined by the region rectangle and returns a pointer to the region. This
4387 % region is subsequently transferred from the pixel cache with
4388 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4389 % pixels are transferred, otherwise a NULL is returned.
4391 % The format of the QueueAuthenticPixelsCache() method is:
4393 % PixelPacket *QueueAuthenticPixelsCache(Image *image,const long x,
4394 % const long y,const unsigned long columns,const unsigned long rows,
4395 % ExceptionInfo *exception)
4397 % A description of each parameter follows:
4399 % o image: the image.
4401 % o x,y,columns,rows: These values define the perimeter of a region of
4404 % o exception: return any errors or warnings in this structure.
4407 static PixelPacket *QueueAuthenticPixelsCache(Image *image,const long x,
4408 const long y,const unsigned long columns,const unsigned long rows,
4409 ExceptionInfo *exception)
4420 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickFalse,exception);
4421 if (cache_info == (Cache) NULL)
4422 return((PixelPacket *) NULL);
4423 id=GetOpenMPThreadId();
4424 assert(id < (long) cache_info->number_threads);
4425 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4435 % Q u e u e A u t h e n t i c P i x e l s %
4439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4441 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4442 % successfully intialized a pointer to a PixelPacket array representing the
4443 % region is returned, otherwise NULL is returned. The returned pointer may
4444 % point to a temporary working buffer for the pixels or it may point to the
4445 % final location of the pixels in memory.
4447 % Write-only access means that any existing pixel values corresponding to
4448 % the region are ignored. This is useful if the initial image is being
4449 % created from scratch, or if the existing pixel values are to be
4450 % completely replaced without need to refer to their pre-existing values.
4451 % The application is free to read and write the pixel buffer returned by
4452 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4453 % initialize the pixel array values. Initializing pixel array values is the
4454 % application's responsibility.
4456 % Performance is maximized if the selected region is part of one row, or
4457 % one or more full rows, since then there is opportunity to access the
4458 % pixels in-place (without a copy) if the image is in memory, or in a
4459 % memory-mapped file. The returned pointer must *never* be deallocated
4462 % Pixels accessed via the returned pointer represent a simple array of type
4463 % PixelPacket. If the image type is CMYK or the storage class is PseudoClass,
4464 % call GetAuthenticIndexQueue() after invoking GetAuthenticPixels() to obtain
4465 % the black color component or the colormap indexes (of type IndexPacket)
4466 % corresponding to the region. Once the PixelPacket (and/or IndexPacket)
4467 % array has been updated, the changes must be saved back to the underlying
4468 % image using SyncAuthenticPixels() or they may be lost.
4470 % The format of the QueueAuthenticPixels() method is:
4472 % PixelPacket *QueueAuthenticPixels(Image *image,const long x,const long y,
4473 % const unsigned long columns,const unsigned long rows,
4474 % ExceptionInfo *exception)
4476 % A description of each parameter follows:
4478 % o image: the image.
4480 % o x,y,columns,rows: These values define the perimeter of a region of
4483 % o exception: return any errors or warnings in this structure.
4486 MagickExport PixelPacket *QueueAuthenticPixels(Image *image,const long x,
4487 const long y,const unsigned long columns,const unsigned long rows,
4488 ExceptionInfo *exception)
4496 assert(image != (Image *) NULL);
4497 assert(image->signature == MagickSignature);
4498 if (image->debug != MagickFalse)
4499 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4500 assert(image->cache != (Cache) NULL);
4501 cache_info=(CacheInfo *) image->cache;
4502 assert(cache_info->signature == MagickSignature);
4503 if (cache_info->methods.queue_authentic_pixels_handler ==
4504 (QueueAuthenticPixelsHandler) NULL)
4505 return((PixelPacket *) NULL);
4506 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4516 + R e a d P i x e l C a c h e I n d e x e s %
4520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4522 % ReadPixelCacheIndexes() reads colormap indexes from the specified region of
4525 % The format of the ReadPixelCacheIndexes() method is:
4527 % MagickBooleanType ReadPixelCacheIndexes(CacheInfo *cache_info,
4528 % NexusInfo *nexus_info,ExceptionInfo *exception)
4530 % A description of each parameter follows:
4532 % o cache_info: the pixel cache.
4534 % o nexus_info: the cache nexus to read the colormap indexes.
4536 % o exception: return any errors or warnings in this structure.
4539 static MagickBooleanType ReadPixelCacheIndexes(CacheInfo *cache_info,
4540 NexusInfo *nexus_info,ExceptionInfo *exception)
4550 register IndexPacket
4559 if (cache_info->debug != MagickFalse)
4560 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4561 cache_info->filename);
4562 if (cache_info->active_index_channel == MagickFalse)
4563 return(MagickFalse);
4564 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
4566 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4567 nexus_info->region.x;
4568 length=(MagickSizeType) nexus_info->region.width*sizeof(IndexPacket);
4569 rows=nexus_info->region.height;
4570 number_pixels=length*rows;
4571 if ((cache_info->columns == nexus_info->region.width) &&
4572 (number_pixels == (MagickSizeType) ((size_t) number_pixels)))
4574 length=number_pixels;
4577 q=nexus_info->indexes;
4578 switch (cache_info->type)
4583 register IndexPacket
4587 Read indexes from memory.
4589 p=cache_info->indexes+offset;
4590 for (y=0; y < (long) rows; y++)
4592 (void) CopyMagickMemory(q,p,(size_t) length);
4593 p+=cache_info->columns;
4594 q+=nexus_info->region.width;
4601 Read indexes from disk.
4603 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4605 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4606 cache_info->cache_filename);
4607 return(MagickFalse);
4609 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4610 for (y=0; y < (long) rows; y++)
4612 count=ReadPixelCacheRegion(cache_info,cache_info->offset+number_pixels*
4613 sizeof(PixelPacket)+offset*sizeof(*q),length,(unsigned char *) q);
4614 if ((MagickSizeType) count < length)
4616 offset+=cache_info->columns;
4617 q+=nexus_info->region.width;
4619 if (y < (long) rows)
4621 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4622 cache_info->cache_filename);
4623 return(MagickFalse);
4630 if ((cache_info->debug != MagickFalse) &&
4631 (QuantumTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4632 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s[%lux%lu%+ld%+ld]",
4633 cache_info->filename,nexus_info->region.width,nexus_info->region.height,
4634 nexus_info->region.x,nexus_info->region.y);
4639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4643 + R e a d P i x e l C a c h e P i x e l s %
4647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4649 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4652 % The format of the ReadPixelCachePixels() method is:
4654 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4655 % NexusInfo *nexus_info,ExceptionInfo *exception)
4657 % A description of each parameter follows:
4659 % o cache_info: the pixel cache.
4661 % o nexus_info: the cache nexus to read the pixels.
4663 % o exception: return any errors or warnings in this structure.
4666 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4667 NexusInfo *nexus_info,ExceptionInfo *exception)
4680 register PixelPacket
4686 if (cache_info->debug != MagickFalse)
4687 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4688 cache_info->filename);
4689 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
4691 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4692 nexus_info->region.x;
4693 length=(MagickSizeType) nexus_info->region.width*sizeof(PixelPacket);
4694 rows=nexus_info->region.height;
4695 number_pixels=length*rows;
4696 if ((cache_info->columns == nexus_info->region.width) &&
4697 (number_pixels == (MagickSizeType) ((size_t) number_pixels)))
4699 length=number_pixels;
4702 q=nexus_info->pixels;
4703 switch (cache_info->type)
4708 register PixelPacket
4712 Read pixels from memory.
4714 p=cache_info->pixels+offset;
4715 for (y=0; y < (long) rows; y++)
4717 (void) CopyMagickMemory(q,p,(size_t) length);
4718 p+=cache_info->columns;
4719 q+=nexus_info->region.width;
4726 Read pixels from disk.
4728 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4730 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4731 cache_info->cache_filename);
4732 return(MagickFalse);
4734 for (y=0; y < (long) rows; y++)
4736 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4737 sizeof(*q),length,(unsigned char *) q);
4738 if ((MagickSizeType) count < length)
4740 offset+=cache_info->columns;
4741 q+=nexus_info->region.width;
4743 if (y < (long) rows)
4745 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4746 cache_info->cache_filename);
4747 return(MagickFalse);
4754 if ((cache_info->debug != MagickFalse) &&
4755 (QuantumTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4756 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s[%lux%lu%+ld%+ld]",
4757 cache_info->filename,nexus_info->region.width,nexus_info->region.height,
4758 nexus_info->region.x,nexus_info->region.y);
4763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4767 + R e f e r e n c e P i x e l C a c h e %
4771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4773 % ReferencePixelCache() increments the reference count associated with the
4774 % pixel cache returning a pointer to the cache.
4776 % The format of the ReferencePixelCache method is:
4778 % Cache ReferencePixelCache(Cache cache_info)
4780 % A description of each parameter follows:
4782 % o cache_info: the pixel cache.
4785 MagickExport Cache ReferencePixelCache(Cache cache)
4790 assert(cache != (Cache *) NULL);
4791 cache_info=(CacheInfo *) cache;
4792 assert(cache_info->signature == MagickSignature);
4793 if (cache_info->debug != MagickFalse)
4794 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4795 cache_info->filename);
4796 LockSemaphoreInfo(cache_info->semaphore);
4797 cache_info->reference_count++;
4798 UnlockSemaphoreInfo(cache_info->semaphore);
4803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4807 + S e t P i x e l C a c h e M e t h o d s %
4811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4813 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4815 % The format of the SetPixelCacheMethods() method is:
4817 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4819 % A description of each parameter follows:
4821 % o cache: the pixel cache.
4823 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4826 MagickExport void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4831 GetOneAuthenticPixelFromHandler
4832 get_one_authentic_pixel_from_handler;
4834 GetOneVirtualPixelFromHandler
4835 get_one_virtual_pixel_from_handler;
4838 Set cache pixel methods.
4840 assert(cache != (Cache) NULL);
4841 assert(cache_methods != (CacheMethods *) NULL);
4842 cache_info=(CacheInfo *) cache;
4843 assert(cache_info->signature == MagickSignature);
4844 if (cache_info->debug != MagickFalse)
4845 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4846 cache_info->filename);
4847 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4848 cache_info->methods.get_virtual_pixel_handler=
4849 cache_methods->get_virtual_pixel_handler;
4850 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4851 cache_info->methods.destroy_pixel_handler=
4852 cache_methods->destroy_pixel_handler;
4853 if (cache_methods->get_virtual_indexes_from_handler !=
4854 (GetVirtualIndexesFromHandler) NULL)
4855 cache_info->methods.get_virtual_indexes_from_handler=
4856 cache_methods->get_virtual_indexes_from_handler;
4857 if (cache_methods->get_authentic_pixels_handler !=
4858 (GetAuthenticPixelsHandler) NULL)
4859 cache_info->methods.get_authentic_pixels_handler=
4860 cache_methods->get_authentic_pixels_handler;
4861 if (cache_methods->queue_authentic_pixels_handler !=
4862 (QueueAuthenticPixelsHandler) NULL)
4863 cache_info->methods.queue_authentic_pixels_handler=
4864 cache_methods->queue_authentic_pixels_handler;
4865 if (cache_methods->sync_authentic_pixels_handler !=
4866 (SyncAuthenticPixelsHandler) NULL)
4867 cache_info->methods.sync_authentic_pixels_handler=
4868 cache_methods->sync_authentic_pixels_handler;
4869 if (cache_methods->get_authentic_pixels_from_handler !=
4870 (GetAuthenticPixelsFromHandler) NULL)
4871 cache_info->methods.get_authentic_pixels_from_handler=
4872 cache_methods->get_authentic_pixels_from_handler;
4873 if (cache_methods->get_authentic_indexes_from_handler !=
4874 (GetAuthenticIndexesFromHandler) NULL)
4875 cache_info->methods.get_authentic_indexes_from_handler=
4876 cache_methods->get_authentic_indexes_from_handler;
4877 get_one_virtual_pixel_from_handler=
4878 cache_info->methods.get_one_virtual_pixel_from_handler;
4879 if (get_one_virtual_pixel_from_handler !=
4880 (GetOneVirtualPixelFromHandler) NULL)
4881 cache_info->methods.get_one_virtual_pixel_from_handler=
4882 cache_methods->get_one_virtual_pixel_from_handler;
4883 get_one_authentic_pixel_from_handler=
4884 cache_methods->get_one_authentic_pixel_from_handler;
4885 if (get_one_authentic_pixel_from_handler !=
4886 (GetOneAuthenticPixelFromHandler) NULL)
4887 cache_info->methods.get_one_authentic_pixel_from_handler=
4888 cache_methods->get_one_authentic_pixel_from_handler;
4892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4896 + S e t P i x e l C a c h e N e x u s P i x e l s %
4900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4902 % SetPixelCacheNexusPixels() defines the region of the cache for the
4903 % specified cache nexus.
4905 % The format of the SetPixelCacheNexusPixels() method is:
4907 % PixelPacket SetPixelCacheNexusPixels(const Image *image,
4908 % const RectangleInfo *region,NexusInfo *nexus_info,
4909 % ExceptionInfo *exception)
4911 % A description of each parameter follows:
4913 % o image: the image.
4915 % o region: A pointer to the RectangleInfo structure that defines the
4916 % region of this particular cache nexus.
4918 % o nexus_info: the cache nexus to set.
4920 % o exception: return any errors or warnings in this structure.
4923 static PixelPacket *SetPixelCacheNexusPixels(const Image *image,
4924 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
4939 if (image->debug != MagickFalse)
4940 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4941 cache_info=(CacheInfo *) image->cache;
4942 assert(cache_info->signature == MagickSignature);
4943 if (cache_info->type == UndefinedCache)
4944 return((PixelPacket *) NULL);
4945 nexus_info->region.width=region->width == 0UL ? 1UL : region->width;
4946 nexus_info->region.height=region->height == 0UL ? 1UL : region->height;
4947 nexus_info->region.x=region->x;
4948 nexus_info->region.y=region->y;
4949 if ((cache_info->type != DiskCache) && (image->clip_mask == (Image *) NULL) &&
4950 (image->mask == (Image *) NULL))
4952 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4953 nexus_info->region.x;
4954 length=(MagickSizeType) (nexus_info->region.height-1)*cache_info->columns+
4955 nexus_info->region.width-1;
4956 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4957 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
4963 x=nexus_info->region.x+nexus_info->region.width;
4964 y=nexus_info->region.y+nexus_info->region.height;
4965 if ((nexus_info->region.x >= 0) &&
4966 (x <= (long) cache_info->columns) &&
4967 (nexus_info->region.y >= 0) && (y <= (long) cache_info->rows))
4968 if ((nexus_info->region.height == 1UL) ||
4969 ((nexus_info->region.x == 0) &&
4970 ((nexus_info->region.width % cache_info->columns) == 0)))
4973 Pixels are accessed directly from memory.
4975 nexus_info->pixels=cache_info->pixels+offset;
4976 nexus_info->indexes=(IndexPacket *) NULL;
4977 if (cache_info->active_index_channel != MagickFalse)
4978 nexus_info->indexes=cache_info->indexes+offset;
4979 return(nexus_info->pixels);
4984 Pixels are stored in a cache region until they are synced to the cache.
4986 number_pixels=(MagickSizeType) nexus_info->region.width*
4987 nexus_info->region.height;
4988 length=number_pixels*sizeof(PixelPacket);
4989 if (cache_info->active_index_channel != MagickFalse)
4990 length+=number_pixels*sizeof(IndexPacket);
4991 if (nexus_info->cache == (PixelPacket *) NULL)
4993 nexus_info->length=length;
4994 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4995 if (status == MagickFalse)
4996 return((PixelPacket *) NULL);
4999 if (nexus_info->length != length)
5001 RelinquishCacheNexusPixels(nexus_info);
5002 nexus_info->length=length;
5003 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5004 if (status == MagickFalse)
5005 return((PixelPacket *) NULL);
5007 nexus_info->pixels=nexus_info->cache;
5008 nexus_info->indexes=(IndexPacket *) NULL;
5009 if (cache_info->active_index_channel != MagickFalse)
5010 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5011 return(nexus_info->pixels);
5015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5019 % S e t P i x e l C a c h e V i r t u a l M e t h o d %
5023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5025 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5026 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5027 % access that is outside the boundaries of the image cache.
5029 % The format of the SetPixelCacheVirtualMethod() method is:
5031 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5032 % const VirtualPixelMethod virtual_pixel_method)
5034 % A description of each parameter follows:
5036 % o image: the image.
5038 % o virtual_pixel_method: choose the type of virtual pixel.
5041 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5042 const VirtualPixelMethod virtual_pixel_method)
5050 assert(image != (Image *) NULL);
5051 assert(image->signature == MagickSignature);
5052 if (image->debug != MagickFalse)
5053 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5054 assert(image->cache != (Cache) NULL);
5055 cache_info=(CacheInfo *) image->cache;
5056 assert(cache_info->signature == MagickSignature);
5057 method=cache_info->virtual_pixel_method;
5058 cache_info->virtual_pixel_method=virtual_pixel_method;
5063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5067 + S y n c A u t h e n t i c P i x e l C a c h e N e x u s %
5071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5073 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5074 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5075 % is synced, otherwise MagickFalse.
5077 % The format of the SyncAuthenticPixelCacheNexus() method is:
5079 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5080 % NexusInfo *nexus_info,ExceptionInfo *exception)
5082 % A description of each parameter follows:
5084 % o image: the image.
5086 % o nexus_info: the cache nexus to sync.
5088 % o exception: return any errors or warnings in this structure.
5091 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5092 NexusInfo *nexus_info,ExceptionInfo *exception)
5101 Transfer pixels to the cache.
5103 assert(image != (Image *) NULL);
5104 assert(image->signature == MagickSignature);
5105 if (image->debug != MagickFalse)
5106 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5107 if (image->cache == (Cache) NULL)
5108 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5109 cache_info=(CacheInfo *) image->cache;
5110 if (cache_info->type == UndefinedCache)
5111 return(MagickFalse);
5112 if ((image->clip_mask != (Image *) NULL) &&
5113 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5114 return(MagickFalse);
5115 if ((image->mask != (Image *) NULL) &&
5116 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5117 return(MagickFalse);
5118 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
5120 assert(cache_info->signature == MagickSignature);
5121 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5122 if ((cache_info->active_index_channel != MagickFalse) &&
5123 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5124 return(MagickFalse);
5129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5133 + S y n c A u t h e n t i c P i x e l C a c h e %
5137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5139 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5140 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5141 % otherwise MagickFalse.
5143 % The format of the SyncAuthenticPixelsCache() method is:
5145 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5146 % ExceptionInfo *exception)
5148 % A description of each parameter follows:
5150 % o image: the image.
5152 % o exception: return any errors or warnings in this structure.
5155 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5156 ExceptionInfo *exception)
5167 cache_info=(CacheInfo *) image->cache;
5168 id=GetOpenMPThreadId();
5169 assert(id < (long) cache_info->number_threads);
5170 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5180 % S y n c A u t h e n t i c P i x e l s %
5184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5186 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5187 % The method returns MagickTrue if the pixel region is flushed, otherwise
5190 % The format of the SyncAuthenticPixels() method is:
5192 % MagickBooleanType SyncAuthenticPixels(Image *image,
5193 % ExceptionInfo *exception)
5195 % A description of each parameter follows:
5197 % o image: the image.
5199 % o exception: return any errors or warnings in this structure.
5202 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5203 ExceptionInfo *exception)
5208 assert(image != (Image *) NULL);
5209 assert(image->signature == MagickSignature);
5210 if (image->debug != MagickFalse)
5211 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5212 assert(image->cache != (Cache) NULL);
5213 cache_info=(CacheInfo *) image->cache;
5214 assert(cache_info->signature == MagickSignature);
5215 if (cache_info->methods.sync_authentic_pixels_handler ==
5216 (SyncAuthenticPixelsHandler) NULL)
5217 return(MagickFalse);
5218 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5226 + W r i t e P i x e l C a c h e I n d e x e s %
5230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5232 % WritePixelCacheIndexes() writes the colormap indexes to the specified
5233 % region of the pixel cache.
5235 % The format of the WritePixelCacheIndexes() method is:
5237 % MagickBooleanType WritePixelCacheIndexes(CacheInfo *cache_info,
5238 % NexusInfo *nexus_info,ExceptionInfo *exception)
5240 % A description of each parameter follows:
5242 % o cache_info: the pixel cache.
5244 % o nexus_info: the cache nexus to write the colormap indexes.
5246 % o exception: return any errors or warnings in this structure.
5249 static MagickBooleanType WritePixelCacheIndexes(CacheInfo *cache_info,
5250 NexusInfo *nexus_info,ExceptionInfo *exception)
5260 register const IndexPacket
5269 if (cache_info->debug != MagickFalse)
5270 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
5271 cache_info->filename);
5272 if (cache_info->active_index_channel == MagickFalse)
5273 return(MagickFalse);
5274 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
5276 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5277 nexus_info->region.x;
5278 length=(MagickSizeType) nexus_info->region.width*sizeof(IndexPacket);
5279 rows=nexus_info->region.height;
5280 number_pixels=(MagickSizeType) length*rows;
5281 if ((cache_info->columns == nexus_info->region.width) &&
5282 (number_pixels == (MagickSizeType) ((size_t) number_pixels)))
5284 length=number_pixels;
5287 p=nexus_info->indexes;
5288 switch (cache_info->type)
5293 register IndexPacket
5297 Write indexes to memory.
5299 q=cache_info->indexes+offset;
5300 for (y=0; y < (long) rows; y++)
5302 (void) CopyMagickMemory(q,p,(size_t) length);
5303 p+=nexus_info->region.width;
5304 q+=cache_info->columns;
5311 Write indexes to disk.
5313 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5315 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5316 cache_info->cache_filename);
5317 return(MagickFalse);
5319 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
5320 for (y=0; y < (long) rows; y++)
5322 count=WritePixelCacheRegion(cache_info,cache_info->offset+number_pixels*
5323 sizeof(PixelPacket)+offset*sizeof(*p),length,
5324 (const unsigned char *) p);
5325 if ((MagickSizeType) count < length)
5327 p+=nexus_info->region.width;
5328 offset+=cache_info->columns;
5330 if (y < (long) rows)
5332 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5333 cache_info->cache_filename);
5334 return(MagickFalse);
5341 if ((cache_info->debug != MagickFalse) &&
5342 (QuantumTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5343 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s[%lux%lu%+ld%+ld]",
5344 cache_info->filename,nexus_info->region.width,nexus_info->region.height,
5345 nexus_info->region.x,nexus_info->region.y);
5350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5354 + W r i t e C a c h e P i x e l s %
5358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5360 % WritePixelCachePixels() writes image pixels to the specified region of the
5363 % The format of the WritePixelCachePixels() method is:
5365 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5366 % NexusInfo *nexus_info,ExceptionInfo *exception)
5368 % A description of each parameter follows:
5370 % o cache_info: the pixel cache.
5372 % o nexus_info: the cache nexus to write the pixels.
5374 % o exception: return any errors or warnings in this structure.
5377 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5378 NexusInfo *nexus_info,ExceptionInfo *exception)
5388 register const PixelPacket
5397 if (cache_info->debug != MagickFalse)
5398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
5399 cache_info->filename);
5400 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
5402 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5403 nexus_info->region.x;
5404 length=(MagickSizeType) nexus_info->region.width*sizeof(PixelPacket);
5405 rows=nexus_info->region.height;
5406 number_pixels=length*rows;
5407 if ((cache_info->columns == nexus_info->region.width) &&
5408 (number_pixels == (MagickSizeType) ((size_t) number_pixels)))
5410 length=number_pixels;
5413 p=nexus_info->pixels;
5414 switch (cache_info->type)
5419 register PixelPacket
5423 Write pixels to memory.
5425 q=cache_info->pixels+offset;
5426 for (y=0; y < (long) rows; y++)
5428 (void) CopyMagickMemory(q,p,(size_t) length);
5429 p+=nexus_info->region.width;
5430 q+=cache_info->columns;
5437 Write pixels to disk.
5439 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5441 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5442 cache_info->cache_filename);
5443 return(MagickFalse);
5445 for (y=0; y < (long) rows; y++)
5447 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5448 sizeof(*p),length,(const unsigned char *) p);
5449 if ((MagickSizeType) count < length)
5451 p+=nexus_info->region.width;
5452 offset+=cache_info->columns;
5454 if (y < (long) rows)
5456 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5457 cache_info->cache_filename);
5458 return(MagickFalse);
5465 if ((cache_info->debug != MagickFalse) &&
5466 (QuantumTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5467 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s[%lux%lu%+ld%+ld]",
5468 cache_info->filename,nexus_info->region.width,nexus_info->region.height,
5469 nexus_info->region.x,nexus_info->region.y);