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-2012 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 "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/composite-private.h"
50 #include "MagickCore/exception.h"
51 #include "MagickCore/exception-private.h"
52 #include "MagickCore/geometry.h"
53 #include "MagickCore/list.h"
54 #include "MagickCore/log.h"
55 #include "MagickCore/magick.h"
56 #include "MagickCore/memory_.h"
57 #include "MagickCore/pixel.h"
58 #include "MagickCore/pixel-accessor.h"
59 #include "MagickCore/policy.h"
60 #include "MagickCore/quantum.h"
61 #include "MagickCore/random_.h"
62 #include "MagickCore/resource_.h"
63 #include "MagickCore/semaphore.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/string-private.h"
67 #include "MagickCore/thread-private.h"
68 #include "MagickCore/utility.h"
69 #include "MagickCore/utility-private.h"
70 #if defined(MAGICKCORE_ZLIB_DELEGATE)
77 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
78 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
79 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
84 typedef struct _MagickModulo
114 Forward declarations.
116 #if defined(__cplusplus) || defined(c_plusplus)
121 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
122 const ssize_t,const size_t,const size_t,ExceptionInfo *),
123 *GetVirtualPixelsCache(const Image *);
126 *GetVirtualMetacontentFromCache(const Image *);
128 static MagickBooleanType
129 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,
130 Quantum *,ExceptionInfo *),
131 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
132 const ssize_t,const ssize_t,Quantum *,ExceptionInfo *),
133 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
134 ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
135 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
136 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
137 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
138 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
141 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
142 const size_t,ExceptionInfo *),
143 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
144 const size_t,ExceptionInfo *),
145 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *,
148 #if defined(__cplusplus) || defined(c_plusplus)
155 static volatile MagickBooleanType
156 instantiate_cache = MagickFalse;
159 *cache_semaphore = (SemaphoreInfo *) NULL;
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 + A c q u i r e P i x e l C a c h e %
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % AcquirePixelCache() acquires a pixel cache.
174 % The format of the AcquirePixelCache() method is:
176 % Cache AcquirePixelCache(const size_t number_threads)
178 % A description of each parameter follows:
180 % o number_threads: the number of nexus threads.
183 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
188 cache_info=(CacheInfo *) AcquireQuantumMemory(1,sizeof(*cache_info));
189 if (cache_info == (CacheInfo *) NULL)
190 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
191 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
192 cache_info->type=UndefinedCache;
193 cache_info->mode=IOMode;
194 cache_info->colorspace=RGBColorspace;
195 cache_info->file=(-1);
196 cache_info->id=GetMagickThreadId();
197 cache_info->number_threads=number_threads;
198 if (number_threads == 0)
199 cache_info->number_threads=GetOpenMPMaximumThreads();
200 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
201 if (cache_info->nexus_info == (NexusInfo **) NULL)
202 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
203 cache_info->semaphore=AllocateSemaphoreInfo();
204 cache_info->reference_count=1;
205 cache_info->disk_semaphore=AllocateSemaphoreInfo();
206 cache_info->debug=IsEventLogging();
207 cache_info->signature=MagickSignature;
208 return((Cache ) cache_info);
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216 % A c q u i r e P i x e l C a c h e N e x u s %
220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 % AcquirePixelCacheNexus() allocates the NexusInfo structure.
224 % The format of the AcquirePixelCacheNexus method is:
226 % NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
228 % A description of each parameter follows:
230 % o number_threads: the number of nexus threads.
233 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
241 nexus_info=(NexusInfo **) AcquireQuantumMemory(number_threads,
242 sizeof(*nexus_info));
243 if (nexus_info == (NexusInfo **) NULL)
244 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
245 for (i=0; i < (ssize_t) number_threads; i++)
247 nexus_info[i]=(NexusInfo *) AcquireQuantumMemory(1,sizeof(**nexus_info));
248 if (nexus_info[i] == (NexusInfo *) NULL)
249 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
250 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
251 nexus_info[i]->signature=MagickSignature;
257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 + A c q u i r e P i x e l C a c h e P i x e l s %
265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 % AcquirePixelCachePixels() returns the pixels associated with the specified
270 % The format of the AcquirePixelCachePixels() method is:
272 % const void *AcquirePixelCachePixels(const Image *image,
273 % MagickSizeType *length,ExceptionInfo *exception)
275 % A description of each parameter follows:
277 % o image: the image.
279 % o length: the pixel cache length.
281 % o exception: return any errors or warnings in this structure.
284 MagickPrivate const void *AcquirePixelCachePixels(const Image *image,
285 MagickSizeType *length,ExceptionInfo *exception)
290 assert(image != (const Image *) NULL);
291 assert(image->signature == MagickSignature);
292 assert(exception != (ExceptionInfo *) NULL);
293 assert(exception->signature == MagickSignature);
294 assert(image->cache != (Cache) NULL);
295 cache_info=(CacheInfo *) image->cache;
296 assert(cache_info->signature == MagickSignature);
298 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
299 return((const void *) NULL);
300 *length=cache_info->length;
301 return((const void *) cache_info->pixels);
305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309 + C a c h e C o m p o n e n t G e n e s i s %
313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 % CacheComponentGenesis() instantiates the cache component.
317 % The format of the CacheComponentGenesis method is:
319 % MagickBooleanType CacheComponentGenesis(void)
322 MagickPrivate MagickBooleanType CacheComponentGenesis(void)
324 AcquireSemaphoreInfo(&cache_semaphore);
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 + C a c h e C o m p o n e n t T e r m i n u s %
337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339 % CacheComponentTerminus() destroys the cache component.
341 % The format of the CacheComponentTerminus() method is:
343 % CacheComponentTerminus(void)
346 MagickPrivate void CacheComponentTerminus(void)
348 if (cache_semaphore == (SemaphoreInfo *) NULL)
349 AcquireSemaphoreInfo(&cache_semaphore);
350 LockSemaphoreInfo(cache_semaphore);
351 instantiate_cache=MagickFalse;
352 UnlockSemaphoreInfo(cache_semaphore);
353 DestroySemaphoreInfo(&cache_semaphore);
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 + C l i p P i x e l C a c h e N e x u s %
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 % ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
368 % mask. It returns MagickTrue if the pixel region is clipped, otherwise
371 % The format of the ClipPixelCacheNexus() method is:
373 % MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
374 % ExceptionInfo *exception)
376 % A description of each parameter follows:
378 % o image: the image.
380 % o nexus_info: the cache nexus to clip.
382 % o exception: return any errors or warnings in this structure.
385 static MagickBooleanType ClipPixelCacheNexus(Image *image,
386 NexusInfo *nexus_info,ExceptionInfo *exception)
398 register const Quantum
409 Clip the image as defined by the clipping mask.
411 if (image->debug != MagickFalse)
412 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
413 if (image->clip_mask == (Image *) NULL)
415 cache_info=(CacheInfo *) image->cache;
416 if (cache_info == (Cache) NULL)
418 image_nexus=AcquirePixelCacheNexus(1);
419 clip_nexus=AcquirePixelCacheNexus(1);
420 if ((image_nexus == (NexusInfo **) NULL) ||
421 (clip_nexus == (NexusInfo **) NULL))
422 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
423 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,nexus_info->region.x,
424 nexus_info->region.y,nexus_info->region.width,nexus_info->region.height,
425 image_nexus[0],exception);
426 q=nexus_info->pixels;
427 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
428 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
429 nexus_info->region.height,clip_nexus[0],exception);
430 number_pixels=(MagickSizeType) nexus_info->region.width*
431 nexus_info->region.height;
432 for (x=0; x < (ssize_t) number_pixels; x++)
437 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
439 if (GetPixelIntensity(image->clip_mask,r) > ((Quantum) QuantumRange/2))
440 for (i=0; i < (ssize_t) image->number_channels; i++)
448 channel=GetPixelChannelMapChannel(image,i);
449 traits=GetPixelChannelMapTraits(image,channel);
450 if (traits == UndefinedPixelTrait)
454 p+=GetPixelChannels(image);
455 q+=GetPixelChannels(image);
456 r+=GetPixelChannels(image->clip_mask);
458 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
459 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
460 if (x < (ssize_t) number_pixels)
466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470 + C l o n e P i x e l C a c h e %
474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
476 % ClonePixelCache() clones a pixel cache.
478 % The format of the ClonePixelCache() method is:
480 % Cache ClonePixelCache(const Cache cache)
482 % A description of each parameter follows:
484 % o cache: the pixel cache.
487 MagickPrivate Cache ClonePixelCache(const Cache cache)
495 assert(cache != NULL);
496 cache_info=(const CacheInfo *) cache;
497 assert(cache_info->signature == MagickSignature);
498 if (cache_info->debug != MagickFalse)
499 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
500 cache_info->filename);
501 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
502 if (clone_info == (Cache) NULL)
503 return((Cache) NULL);
504 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
505 return((Cache ) clone_info);
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 + C l o n e P i x e l C a c h e P i x e l s %
517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
518 % ClonePixelCachePixels() clones the source pixel cache to the destination
521 % The format of the ClonePixelCachePixels() method is:
523 % MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
524 % CacheInfo *source_info,ExceptionInfo *exception)
526 % A description of each parameter follows:
528 % o cache_info: the pixel cache.
530 % o source_info: the source pixel cache.
532 % o exception: return any errors or warnings in this structure.
536 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
542 LockSemaphoreInfo(cache_info->disk_semaphore);
543 if (cache_info->file != -1)
545 status=close(cache_info->file);
546 cache_info->file=(-1);
547 RelinquishMagickResource(FileResource,1);
549 UnlockSemaphoreInfo(cache_info->disk_semaphore);
550 return(status == -1 ? MagickFalse : MagickTrue);
553 static inline MagickSizeType MagickMax(const MagickSizeType x,
554 const MagickSizeType y)
561 static inline MagickSizeType MagickMin(const MagickSizeType x,
562 const MagickSizeType y)
569 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
576 Open pixel cache on disk.
578 LockSemaphoreInfo(cache_info->disk_semaphore);
579 if (cache_info->file != -1)
581 UnlockSemaphoreInfo(cache_info->disk_semaphore);
582 return(MagickTrue); /* cache already open */
584 if (*cache_info->cache_filename == '\0')
585 file=AcquireUniqueFileResource(cache_info->cache_filename);
591 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
596 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
597 O_BINARY | O_EXCL,S_MODE);
599 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
605 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
608 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
614 UnlockSemaphoreInfo(cache_info->disk_semaphore);
617 (void) AcquireMagickResource(FileResource,1);
618 cache_info->file=file;
619 cache_info->mode=mode;
620 cache_info->timestamp=time(0);
621 UnlockSemaphoreInfo(cache_info->disk_semaphore);
625 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
626 const MagickOffsetType offset,const MagickSizeType length,
627 unsigned char *restrict buffer)
629 register MagickOffsetType
635 cache_info->timestamp=time(0);
636 #if !defined(MAGICKCORE_HAVE_PREAD)
637 LockSemaphoreInfo(cache_info->disk_semaphore);
638 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
640 UnlockSemaphoreInfo(cache_info->disk_semaphore);
641 return((MagickOffsetType) -1);
645 for (i=0; i < (MagickOffsetType) length; i+=count)
647 #if !defined(MAGICKCORE_HAVE_PREAD)
648 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
649 (MagickSizeType) SSIZE_MAX));
651 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
652 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
663 #if !defined(MAGICKCORE_HAVE_PREAD)
664 UnlockSemaphoreInfo(cache_info->disk_semaphore);
669 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
670 const MagickOffsetType offset,const MagickSizeType length,
671 const unsigned char *restrict buffer)
673 register MagickOffsetType
679 cache_info->timestamp=time(0);
680 #if !defined(MAGICKCORE_HAVE_PWRITE)
681 LockSemaphoreInfo(cache_info->disk_semaphore);
682 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
684 UnlockSemaphoreInfo(cache_info->disk_semaphore);
685 return((MagickOffsetType) -1);
689 for (i=0; i < (MagickOffsetType) length; i+=count)
691 #if !defined(MAGICKCORE_HAVE_PWRITE)
692 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
693 (MagickSizeType) SSIZE_MAX));
695 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
696 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
707 #if !defined(MAGICKCORE_HAVE_PWRITE)
708 UnlockSemaphoreInfo(cache_info->disk_semaphore);
713 static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info,
714 CacheInfo *cache_info,ExceptionInfo *exception)
719 register MagickOffsetType
729 Clone pixel cache (both caches on disk).
731 if (cache_info->debug != MagickFalse)
732 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
733 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
735 if (blob == (unsigned char *) NULL)
737 (void) ThrowMagickException(exception,GetMagickModule(),
738 ResourceLimitError,"MemoryAllocationFailed","`%s'",
739 cache_info->filename);
742 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
744 blob=(unsigned char *) RelinquishMagickMemory(blob);
745 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
746 cache_info->cache_filename);
749 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
751 (void) ClosePixelCacheOnDisk(cache_info);
752 blob=(unsigned char *) RelinquishMagickMemory(blob);
753 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
754 clone_info->cache_filename);
758 for (i=0; i < (MagickOffsetType) cache_info->length; i+=count)
760 count=ReadPixelCacheRegion(cache_info,cache_info->offset+i,
761 MagickMin(cache_info->length-i,(MagickSizeType) MagickMaxBufferExtent),
765 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
766 cache_info->cache_filename);
769 length=(size_t) count;
770 count=WritePixelCacheRegion(clone_info,clone_info->offset+i,length,blob);
771 if ((MagickSizeType) count != length)
773 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
774 clone_info->cache_filename);
778 (void) ClosePixelCacheOnDisk(clone_info);
779 (void) ClosePixelCacheOnDisk(cache_info);
780 blob=(unsigned char *) RelinquishMagickMemory(blob);
781 if (i < (MagickOffsetType) cache_info->length)
786 static MagickBooleanType PixelCacheCloneOptimized(CacheInfo *clone_info,
787 CacheInfo *cache_info,ExceptionInfo *exception)
792 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
795 Clone pixel cache (both caches in memory).
797 if (cache_info->debug != MagickFalse)
798 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
799 (void) memcpy(clone_info->pixels,cache_info->pixels,(size_t)
803 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
806 Clone pixel cache (one cache on disk, one in memory).
808 if (cache_info->debug != MagickFalse)
809 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
810 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
812 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
813 cache_info->cache_filename);
816 count=ReadPixelCacheRegion(cache_info,cache_info->offset,
817 cache_info->length,(unsigned char *) clone_info->pixels);
818 (void) ClosePixelCacheOnDisk(cache_info);
819 if ((MagickSizeType) count != cache_info->length)
821 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
822 cache_info->cache_filename);
827 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
830 Clone pixel cache (one cache on disk, one in memory).
832 if (clone_info->debug != MagickFalse)
833 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
834 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
836 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
837 clone_info->cache_filename);
840 count=WritePixelCacheRegion(clone_info,clone_info->offset,
841 clone_info->length,(unsigned char *) cache_info->pixels);
842 (void) ClosePixelCacheOnDisk(clone_info);
843 if ((MagickSizeType) count != clone_info->length)
845 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
846 clone_info->cache_filename);
852 Clone pixel cache (both caches on disk).
854 return(DiskToDiskPixelCacheClone(clone_info,cache_info,exception));
857 static MagickBooleanType PixelCacheCloneUnoptimized(CacheInfo *clone_info,
858 CacheInfo *cache_info,ExceptionInfo *exception)
871 register unsigned char
884 Clone pixel cache (unoptimized).
886 if (cache_info->debug != MagickFalse)
888 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
889 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
891 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
892 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
894 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
895 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
897 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
899 length=(size_t) MagickMax(MagickMax(cache_info->number_channels,
900 clone_info->number_channels)*sizeof(Quantum),MagickMax(
901 cache_info->metacontent_extent,clone_info->metacontent_extent));
902 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blob));
903 if (blob == (unsigned char *) NULL)
905 (void) ThrowMagickException(exception,GetMagickModule(),
906 ResourceLimitError,"MemoryAllocationFailed","`%s'",
907 cache_info->filename);
910 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
913 if (cache_info->type == DiskCache)
915 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
917 blob=(unsigned char *) RelinquishMagickMemory(blob);
918 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
919 cache_info->cache_filename);
922 cache_offset=cache_info->offset;
924 if (clone_info->type == DiskCache)
926 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
928 blob=(unsigned char *) RelinquishMagickMemory(blob);
929 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
930 clone_info->cache_filename);
933 clone_offset=clone_info->offset;
936 Clone pixel channels.
940 for (y=0; y < (ssize_t) cache_info->rows; y++)
942 for (x=0; x < (ssize_t) cache_info->columns; x++)
948 Read a set of pixel channels.
950 length=cache_info->number_channels*sizeof(Quantum);
951 if (cache_info->type != DiskCache)
952 p=(unsigned char *) cache_info->pixels+cache_offset;
955 count=ReadPixelCacheRegion(cache_info,cache_offset,length,p);
956 if ((MagickSizeType) count != length)
962 cache_offset+=length;
963 if ((y < (ssize_t) clone_info->rows) &&
964 (x < (ssize_t) clone_info->columns))
965 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
977 Write a set of pixel channels.
979 channel=clone_info->channel_map[i].channel;
980 traits=cache_info->channel_map[channel].traits;
981 if (traits == UndefinedPixelTrait)
983 clone_offset+=sizeof(Quantum);
986 offset=cache_info->channel_map[channel].offset;
987 if (clone_info->type != DiskCache)
988 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,p+
989 offset*sizeof(Quantum),sizeof(Quantum));
992 count=WritePixelCacheRegion(clone_info,clone_offset,
993 sizeof(Quantum),p+offset*sizeof(Quantum));
994 if ((MagickSizeType) count != sizeof(Quantum))
1000 clone_offset+=sizeof(Quantum);
1003 length=clone_info->number_channels*sizeof(Quantum);
1004 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1005 for ( ; x < (ssize_t) clone_info->columns; x++)
1008 Set remaining columns as undefined.
1010 if (clone_info->type != DiskCache)
1011 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1015 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1016 if ((MagickSizeType) count != length)
1022 clone_offset+=length;
1025 length=clone_info->number_channels*sizeof(Quantum);
1026 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1027 for ( ; y < (ssize_t) clone_info->rows; y++)
1030 Set remaining rows as undefined.
1032 for (x=0; x < (ssize_t) clone_info->columns; x++)
1034 if (clone_info->type != DiskCache)
1035 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1039 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1040 if ((MagickSizeType) count != length)
1046 clone_offset+=length;
1049 if ((cache_info->metacontent_extent != 0) ||
1050 (clone_info->metacontent_extent != 0))
1055 for (y=0; y < (ssize_t) cache_info->rows; y++)
1057 for (x=0; x < (ssize_t) cache_info->columns; x++)
1060 Read a set of metacontent.
1062 length=cache_info->metacontent_extent;
1063 if (cache_info->type != DiskCache)
1064 p=(unsigned char *) cache_info->pixels+cache_offset;
1067 count=ReadPixelCacheRegion(cache_info,cache_offset,length,p);
1068 if ((MagickSizeType) count != length)
1074 cache_offset+=length;
1075 if ((y < (ssize_t) clone_info->rows) &&
1076 (x < (ssize_t) clone_info->columns))
1079 Write a set of metacontent.
1081 length=clone_info->metacontent_extent;
1082 if (clone_info->type != DiskCache)
1083 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1087 count=WritePixelCacheRegion(clone_info,clone_offset,length,p);
1088 if ((MagickSizeType) count != length)
1094 clone_offset+=length;
1097 length=clone_info->metacontent_extent;
1098 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1099 for ( ; x < (ssize_t) clone_info->columns; x++)
1102 Set remaining columns as undefined.
1104 if (clone_info->type != DiskCache)
1105 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1109 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1110 if ((MagickSizeType) count != length)
1116 clone_offset+=length;
1119 length=clone_info->metacontent_extent;
1120 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1121 for ( ; y < (ssize_t) clone_info->rows; y++)
1124 Set remaining rows as undefined.
1126 for (x=0; x < (ssize_t) clone_info->columns; x++)
1128 if (clone_info->type != DiskCache)
1129 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1133 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1134 if ((MagickSizeType) count != length)
1140 clone_offset+=length;
1144 if (clone_info->type == DiskCache)
1145 (void) ClosePixelCacheOnDisk(clone_info);
1146 if (cache_info->type == DiskCache)
1147 (void) ClosePixelCacheOnDisk(cache_info);
1148 blob=(unsigned char *) RelinquishMagickMemory(blob);
1152 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1153 CacheInfo *cache_info,ExceptionInfo *exception)
1159 if (cache_info->type == PingCache)
1161 p=cache_info->channel_map;
1162 q=clone_info->channel_map;
1163 if ((cache_info->columns == clone_info->columns) &&
1164 (cache_info->rows == clone_info->rows) &&
1165 (cache_info->number_channels == clone_info->number_channels) &&
1166 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) &&
1167 (cache_info->metacontent_extent == clone_info->metacontent_extent))
1168 return(PixelCacheCloneOptimized(clone_info,cache_info,exception));
1169 return(PixelCacheCloneUnoptimized(clone_info,cache_info,exception));
1173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1177 + C l o n e P i x e l C a c h e M e t h o d s %
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1186 % The format of the ClonePixelCacheMethods() method is:
1188 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
1190 % A description of each parameter follows:
1192 % o clone: Specifies a pointer to a Cache structure.
1194 % o cache: the pixel cache.
1197 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
1203 assert(clone != (Cache) NULL);
1204 source_info=(CacheInfo *) clone;
1205 assert(source_info->signature == MagickSignature);
1206 if (source_info->debug != MagickFalse)
1207 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1208 source_info->filename);
1209 assert(cache != (Cache) NULL);
1210 cache_info=(CacheInfo *) cache;
1211 assert(cache_info->signature == MagickSignature);
1212 source_info->methods=cache_info->methods;
1216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220 + D e s t r o y I m a g e P i x e l C a c h e %
1224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1226 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1228 % The format of the DestroyImagePixelCache() method is:
1230 % void DestroyImagePixelCache(Image *image)
1232 % A description of each parameter follows:
1234 % o image: the image.
1237 static void DestroyImagePixelCache(Image *image)
1239 assert(image != (Image *) NULL);
1240 assert(image->signature == MagickSignature);
1241 if (image->debug != MagickFalse)
1242 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1243 if (image->cache == (void *) NULL)
1245 image->cache=DestroyPixelCache(image->cache);
1249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1253 + D e s t r o y I m a g e P i x e l s %
1257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259 % DestroyImagePixels() deallocates memory associated with the pixel cache.
1261 % The format of the DestroyImagePixels() method is:
1263 % void DestroyImagePixels(Image *image)
1265 % A description of each parameter follows:
1267 % o image: the image.
1270 MagickExport void DestroyImagePixels(Image *image)
1275 assert(image != (const Image *) NULL);
1276 assert(image->signature == MagickSignature);
1277 if (image->debug != MagickFalse)
1278 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1279 assert(image->cache != (Cache) NULL);
1280 cache_info=(CacheInfo *) image->cache;
1281 assert(cache_info->signature == MagickSignature);
1282 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1284 cache_info->methods.destroy_pixel_handler(image);
1287 image->cache=DestroyPixelCache(image->cache);
1291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1295 + D e s t r o y P i x e l C a c h e %
1299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1301 % DestroyPixelCache() deallocates memory associated with the pixel cache.
1303 % The format of the DestroyPixelCache() method is:
1305 % Cache DestroyPixelCache(Cache cache)
1307 % A description of each parameter follows:
1309 % o cache: the pixel cache.
1313 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1315 switch (cache_info->type)
1319 if (cache_info->mapped == MagickFalse)
1320 cache_info->pixels=(Quantum *) RelinquishMagickMemory(
1321 cache_info->pixels);
1323 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,
1324 (size_t) cache_info->length);
1325 RelinquishMagickResource(MemoryResource,cache_info->length);
1330 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t)
1331 cache_info->length);
1332 RelinquishMagickResource(MapResource,cache_info->length);
1336 if (cache_info->file != -1)
1337 (void) ClosePixelCacheOnDisk(cache_info);
1338 RelinquishMagickResource(DiskResource,cache_info->length);
1344 cache_info->type=UndefinedCache;
1345 cache_info->mapped=MagickFalse;
1346 cache_info->metacontent=(void *) NULL;
1349 MagickPrivate Cache DestroyPixelCache(Cache cache)
1354 assert(cache != (Cache) NULL);
1355 cache_info=(CacheInfo *) cache;
1356 assert(cache_info->signature == MagickSignature);
1357 if (cache_info->debug != MagickFalse)
1358 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1359 cache_info->filename);
1360 LockSemaphoreInfo(cache_info->semaphore);
1361 cache_info->reference_count--;
1362 if (cache_info->reference_count != 0)
1364 UnlockSemaphoreInfo(cache_info->semaphore);
1365 return((Cache) NULL);
1367 UnlockSemaphoreInfo(cache_info->semaphore);
1368 if (cache_info->debug != MagickFalse)
1371 message[MaxTextExtent];
1373 (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
1374 cache_info->filename);
1375 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1377 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1378 (cache_info->type != DiskCache)))
1379 RelinquishPixelCachePixels(cache_info);
1382 RelinquishPixelCachePixels(cache_info);
1383 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1385 *cache_info->cache_filename='\0';
1386 if (cache_info->nexus_info != (NexusInfo **) NULL)
1387 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1388 cache_info->number_threads);
1389 if (cache_info->random_info != (RandomInfo *) NULL)
1390 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1391 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1392 DestroySemaphoreInfo(&cache_info->disk_semaphore);
1393 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1394 DestroySemaphoreInfo(&cache_info->semaphore);
1395 cache_info->signature=(~MagickSignature);
1396 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
1402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1406 + D e s t r o y P i x e l C a c h e N e x u s %
1410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1412 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1414 % The format of the DestroyPixelCacheNexus() method is:
1416 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1417 % const size_t number_threads)
1419 % A description of each parameter follows:
1421 % o nexus_info: the nexus to destroy.
1423 % o number_threads: the number of nexus threads.
1427 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1429 if (nexus_info->mapped == MagickFalse)
1430 (void) RelinquishAlignedMemory(nexus_info->cache);
1432 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1433 nexus_info->cache=(Quantum *) NULL;
1434 nexus_info->pixels=(Quantum *) NULL;
1435 nexus_info->metacontent=(void *) NULL;
1436 nexus_info->length=0;
1437 nexus_info->mapped=MagickFalse;
1440 MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1441 const size_t number_threads)
1446 assert(nexus_info != (NexusInfo **) NULL);
1447 for (i=0; i < (ssize_t) number_threads; i++)
1449 if (nexus_info[i]->cache != (Quantum *) NULL)
1450 RelinquishCacheNexusPixels(nexus_info[i]);
1451 nexus_info[i]->signature=(~MagickSignature);
1452 nexus_info[i]=(NexusInfo *) RelinquishMagickMemory(nexus_info[i]);
1454 nexus_info=(NexusInfo **) RelinquishMagickMemory(nexus_info);
1459 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1463 % G e t A u t h e n t i c M e t a c o n t e n t %
1467 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1469 % GetAuthenticMetacontent() returns the authentic metacontent corresponding
1470 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
1471 % returned if the associated pixels are not available.
1473 % The format of the GetAuthenticMetacontent() method is:
1475 % void *GetAuthenticMetacontent(const Image *image)
1477 % A description of each parameter follows:
1479 % o image: the image.
1482 MagickExport void *GetAuthenticMetacontent(const Image *image)
1488 id = GetOpenMPThreadId();
1493 assert(image != (const Image *) NULL);
1494 assert(image->signature == MagickSignature);
1495 assert(image->cache != (Cache) NULL);
1496 cache_info=(CacheInfo *) image->cache;
1497 assert(cache_info->signature == MagickSignature);
1498 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1499 (GetAuthenticMetacontentFromHandler) NULL)
1501 metacontent=cache_info->methods.
1502 get_authentic_metacontent_from_handler(image);
1503 return(metacontent);
1505 assert(id < (int) cache_info->number_threads);
1506 metacontent=GetPixelCacheNexusMetacontent(cache_info,
1507 cache_info->nexus_info[id]);
1508 return(metacontent);
1512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1516 + G e t A u t h e n t i c M e t a c o n t e n t F r o m C a c h e %
1520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1522 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding
1523 % with the last call to QueueAuthenticPixelsCache() or
1524 % GetAuthenticPixelsCache().
1526 % The format of the GetAuthenticMetacontentFromCache() method is:
1528 % void *GetAuthenticMetacontentFromCache(const Image *image)
1530 % A description of each parameter follows:
1532 % o image: the image.
1535 static void *GetAuthenticMetacontentFromCache(const Image *image)
1541 id = GetOpenMPThreadId();
1546 assert(image != (const Image *) NULL);
1547 assert(image->signature == MagickSignature);
1548 assert(image->cache != (Cache) NULL);
1549 cache_info=(CacheInfo *) image->cache;
1550 assert(cache_info->signature == MagickSignature);
1551 assert(id < (int) cache_info->number_threads);
1552 metacontent=GetPixelCacheNexusMetacontent(image->cache,
1553 cache_info->nexus_info[id]);
1554 return(metacontent);
1558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562 + 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 %
1566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1568 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1569 % disk pixel cache as defined by the geometry parameters. A pointer to the
1570 % pixels is returned if the pixels are transferred, otherwise a NULL is
1573 % The format of the GetAuthenticPixelCacheNexus() method is:
1575 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
1576 % const ssize_t y,const size_t columns,const size_t rows,
1577 % NexusInfo *nexus_info,ExceptionInfo *exception)
1579 % A description of each parameter follows:
1581 % o image: the image.
1583 % o x,y,columns,rows: These values define the perimeter of a region of
1586 % o nexus_info: the cache nexus to return.
1588 % o exception: return any errors or warnings in this structure.
1592 static inline MagickBooleanType IsPixelAuthentic(const CacheInfo *cache_info,
1593 NexusInfo *nexus_info)
1601 if (cache_info->type == PingCache)
1603 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1604 nexus_info->region.x;
1605 status=nexus_info->pixels == (cache_info->pixels+offset*
1606 cache_info->number_channels) ? MagickTrue : MagickFalse;
1610 MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
1611 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
1612 NexusInfo *nexus_info,ExceptionInfo *exception)
1621 Transfer pixels from the cache.
1623 assert(image != (Image *) NULL);
1624 assert(image->signature == MagickSignature);
1625 q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,nexus_info,
1627 if (q == (Quantum *) NULL)
1628 return((Quantum *) NULL);
1629 cache_info=(CacheInfo *) image->cache;
1630 assert(cache_info->signature == MagickSignature);
1631 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
1633 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1634 return((Quantum *) NULL);
1635 if (cache_info->metacontent_extent != 0)
1636 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1637 return((Quantum *) NULL);
1642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1646 + 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 %
1650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1652 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1653 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1655 % The format of the GetAuthenticPixelsFromCache() method is:
1657 % Quantum *GetAuthenticPixelsFromCache(const Image image)
1659 % A description of each parameter follows:
1661 % o image: the image.
1664 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
1670 id = GetOpenMPThreadId();
1672 assert(image != (const Image *) NULL);
1673 assert(image->signature == MagickSignature);
1674 assert(image->cache != (Cache) NULL);
1675 cache_info=(CacheInfo *) image->cache;
1676 assert(cache_info->signature == MagickSignature);
1677 assert(id < (int) cache_info->number_threads);
1678 return(GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]));
1682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1686 % G e t A u t h e n t i c P i x e l Q u e u e %
1690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1692 % GetAuthenticPixelQueue() returns the authentic pixels associated
1693 % corresponding with the last call to QueueAuthenticPixels() or
1694 % GetAuthenticPixels().
1696 % The format of the GetAuthenticPixelQueue() method is:
1698 % Quantum *GetAuthenticPixelQueue(const Image image)
1700 % A description of each parameter follows:
1702 % o image: the image.
1705 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
1711 id = GetOpenMPThreadId();
1713 assert(image != (const Image *) NULL);
1714 assert(image->signature == MagickSignature);
1715 assert(image->cache != (Cache) NULL);
1716 cache_info=(CacheInfo *) image->cache;
1717 assert(cache_info->signature == MagickSignature);
1718 if (cache_info->methods.get_authentic_pixels_from_handler !=
1719 (GetAuthenticPixelsFromHandler) NULL)
1720 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1721 assert(id < (int) cache_info->number_threads);
1722 return(GetPixelCacheNexusPixels(cache_info,cache_info->nexus_info[id]));
1726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1730 % G e t A u t h e n t i c P i x e l s %
1733 % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1735 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1736 % region is successfully accessed, a pointer to a Quantum array
1737 % representing the region is returned, otherwise NULL is returned.
1739 % The returned pointer may point to a temporary working copy of the pixels
1740 % or it may point to the original pixels in memory. Performance is maximized
1741 % if the selected region is part of one row, or one or more full rows, since
1742 % then there is opportunity to access the pixels in-place (without a copy)
1743 % if the image is in memory, or in a memory-mapped file. The returned pointer
1744 % must *never* be deallocated by the user.
1746 % Pixels accessed via the returned pointer represent a simple array of type
1747 % Quantum. If the image has corresponding metacontent,call
1748 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
1749 % meta-content corresponding to the region. Once the Quantum array has
1750 % been updated, the changes must be saved back to the underlying image using
1751 % SyncAuthenticPixels() or they may be lost.
1753 % The format of the GetAuthenticPixels() method is:
1755 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1756 % const ssize_t y,const size_t columns,const size_t rows,
1757 % ExceptionInfo *exception)
1759 % A description of each parameter follows:
1761 % o image: the image.
1763 % o x,y,columns,rows: These values define the perimeter of a region of
1766 % o exception: return any errors or warnings in this structure.
1769 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1770 const ssize_t y,const size_t columns,const size_t rows,
1771 ExceptionInfo *exception)
1777 id = GetOpenMPThreadId();
1782 assert(image != (Image *) NULL);
1783 assert(image->signature == MagickSignature);
1784 assert(image->cache != (Cache) NULL);
1785 cache_info=(CacheInfo *) image->cache;
1786 assert(cache_info->signature == MagickSignature);
1787 if (cache_info->methods.get_authentic_pixels_handler !=
1788 (GetAuthenticPixelsHandler) NULL)
1790 q=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,rows,
1794 assert(id < (int) cache_info->number_threads);
1795 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1796 cache_info->nexus_info[id],exception);
1801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1805 + G e t A u t h e n t i c P i x e l s C a c h e %
1809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1811 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1812 % as defined by the geometry parameters. A pointer to the pixels is returned
1813 % if the pixels are transferred, otherwise a NULL is returned.
1815 % The format of the GetAuthenticPixelsCache() method is:
1817 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1818 % const ssize_t y,const size_t columns,const size_t rows,
1819 % ExceptionInfo *exception)
1821 % A description of each parameter follows:
1823 % o image: the image.
1825 % o x,y,columns,rows: These values define the perimeter of a region of
1828 % o exception: return any errors or warnings in this structure.
1831 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1832 const ssize_t y,const size_t columns,const size_t rows,
1833 ExceptionInfo *exception)
1839 id = GetOpenMPThreadId();
1844 assert(image != (const Image *) NULL);
1845 assert(image->signature == MagickSignature);
1846 assert(image->cache != (Cache) NULL);
1847 cache_info=(CacheInfo *) image->cache;
1848 if (cache_info == (Cache) NULL)
1849 return((Quantum *) NULL);
1850 assert(cache_info->signature == MagickSignature);
1851 assert(id < (int) cache_info->number_threads);
1852 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1853 cache_info->nexus_info[id],exception);
1858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1862 + G e t I m a g e E x t e n t %
1866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1868 % GetImageExtent() returns the extent of the pixels associated corresponding
1869 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
1871 % The format of the GetImageExtent() method is:
1873 % MagickSizeType GetImageExtent(const Image *image)
1875 % A description of each parameter follows:
1877 % o image: the image.
1880 MagickExport MagickSizeType GetImageExtent(const Image *image)
1886 id = GetOpenMPThreadId();
1888 assert(image != (Image *) NULL);
1889 assert(image->signature == MagickSignature);
1890 if (image->debug != MagickFalse)
1891 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1892 assert(image->cache != (Cache) NULL);
1893 cache_info=(CacheInfo *) image->cache;
1894 assert(cache_info->signature == MagickSignature);
1895 assert(id < (int) cache_info->number_threads);
1896 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
1900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1904 + G e t I m a g e P i x e l C a c h e %
1908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1910 % GetImagePixelCache() ensures that there is only a single reference to the
1911 % pixel cache to be modified, updating the provided cache pointer to point to
1912 % a clone of the original pixel cache if necessary.
1914 % The format of the GetImagePixelCache method is:
1916 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1917 % ExceptionInfo *exception)
1919 % A description of each parameter follows:
1921 % o image: the image.
1923 % o clone: any value other than MagickFalse clones the cache pixels.
1925 % o exception: return any errors or warnings in this structure.
1929 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
1939 Does the image match the pixel cache morphology?
1941 cache_info=(CacheInfo *) image->cache;
1942 p=image->channel_map;
1943 q=cache_info->channel_map;
1944 if ((image->storage_class != cache_info->storage_class) ||
1945 (image->colorspace != cache_info->colorspace) ||
1946 (image->matte != cache_info->matte) ||
1947 (image->columns != cache_info->columns) ||
1948 (image->rows != cache_info->rows) ||
1949 (image->number_channels != cache_info->number_channels) ||
1950 (memcmp(p,q,image->number_channels*sizeof(*p)) != 0) ||
1951 (image->metacontent_extent != cache_info->metacontent_extent) ||
1952 (cache_info->nexus_info == (NexusInfo **) NULL) ||
1953 (cache_info->number_threads < GetOpenMPMaximumThreads()))
1954 return(MagickFalse);
1958 static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1959 ExceptionInfo *exception)
1968 static MagickSizeType
1974 cache_timestamp = 0;
1977 LockSemaphoreInfo(image->semaphore);
1978 if (cpu_throttle == 0)
1984 Set CPU throttle in milleseconds.
1986 cpu_throttle=MagickResourceInfinity;
1987 limit=GetEnvironmentValue("MAGICK_THROTTLE");
1988 if (limit == (char *) NULL)
1989 limit=GetPolicyValue("throttle");
1990 if (limit != (char *) NULL)
1992 cpu_throttle=(MagickSizeType) StringToInteger(limit);
1993 limit=DestroyString(limit);
1996 if ((cpu_throttle != MagickResourceInfinity) && ((cycles++ % 32) == 0))
1997 MagickDelay(cpu_throttle);
1998 if (time_limit == 0)
2001 Set the exire time in seconds.
2003 time_limit=GetMagickResourceLimit(TimeResource);
2004 cache_timestamp=time((time_t *) NULL);
2006 if ((time_limit != MagickResourceInfinity) &&
2007 ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
2008 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
2009 assert(image->cache != (Cache) NULL);
2010 cache_info=(CacheInfo *) image->cache;
2011 destroy=MagickFalse;
2012 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2014 LockSemaphoreInfo(cache_info->semaphore);
2015 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2026 clone_image=(*image);
2027 clone_image.semaphore=AllocateSemaphoreInfo();
2028 clone_image.reference_count=1;
2029 clone_image.cache=ClonePixelCache(cache_info);
2030 clone_info=(CacheInfo *) clone_image.cache;
2031 status=OpenPixelCache(&clone_image,IOMode,exception);
2032 if (status != MagickFalse)
2034 if (clone != MagickFalse)
2035 status=ClonePixelCachePixels(clone_info,cache_info,exception);
2036 if (status != MagickFalse)
2038 if (cache_info->mode == ReadMode)
2039 cache_info->nexus_info=(NexusInfo **) NULL;
2041 image->cache=clone_image.cache;
2044 DestroySemaphoreInfo(&clone_image.semaphore);
2046 UnlockSemaphoreInfo(cache_info->semaphore);
2048 if (destroy != MagickFalse)
2049 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
2050 if (status != MagickFalse)
2053 Ensure the image matches the pixel cache morphology.
2055 image->taint=MagickTrue;
2056 image->type=UndefinedType;
2057 if (ValidatePixelCacheMorphology(image) == MagickFalse)
2059 status=OpenPixelCache(image,IOMode,exception);
2060 cache_info=(CacheInfo *) image->cache;
2061 if (cache_info->type == DiskCache)
2062 (void) ClosePixelCacheOnDisk(cache_info);
2065 UnlockSemaphoreInfo(image->semaphore);
2066 if (status == MagickFalse)
2067 return((Cache) NULL);
2068 return(image->cache);
2072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2076 % G e t O n e A u t h e n t i c P i x e l %
2080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2082 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2083 % location. The image background color is returned if an error occurs.
2085 % The format of the GetOneAuthenticPixel() method is:
2087 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
2088 % const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2090 % A description of each parameter follows:
2092 % o image: the image.
2094 % o x,y: These values define the location of the pixel to return.
2096 % o pixel: return a pixel at the specified (x,y) location.
2098 % o exception: return any errors or warnings in this structure.
2101 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2102 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2113 assert(image != (Image *) NULL);
2114 assert(image->signature == MagickSignature);
2115 assert(image->cache != (Cache) NULL);
2116 cache_info=(CacheInfo *) image->cache;
2117 assert(cache_info->signature == MagickSignature);
2118 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2119 if (cache_info->methods.get_one_authentic_pixel_from_handler !=
2120 (GetOneAuthenticPixelFromHandler) NULL)
2121 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2123 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2124 if (q == (Quantum *) NULL)
2126 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2127 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2128 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2129 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2130 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2131 return(MagickFalse);
2133 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2138 channel=GetPixelChannelMapChannel(image,i);
2139 pixel[channel]=q[i];
2145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2149 + 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 %
2153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2155 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2156 % location. The image background color is returned if an error occurs.
2158 % The format of the GetOneAuthenticPixelFromCache() method is:
2160 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2161 % const ssize_t x,const ssize_t y,Quantum *pixel,
2162 % ExceptionInfo *exception)
2164 % A description of each parameter follows:
2166 % o image: the image.
2168 % o x,y: These values define the location of the pixel to return.
2170 % o pixel: return a pixel at the specified (x,y) location.
2172 % o exception: return any errors or warnings in this structure.
2175 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2176 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2182 id = GetOpenMPThreadId();
2190 assert(image != (const Image *) NULL);
2191 assert(image->signature == MagickSignature);
2192 assert(image->cache != (Cache) NULL);
2193 cache_info=(CacheInfo *) image->cache;
2194 assert(cache_info->signature == MagickSignature);
2195 assert(id < (int) cache_info->number_threads);
2196 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2197 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
2199 if (q == (Quantum *) NULL)
2201 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2202 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2203 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2204 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2205 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2206 return(MagickFalse);
2208 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2213 channel=GetPixelChannelMapChannel(image,i);
2214 pixel[channel]=q[i];
2220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2224 % G e t O n e V i r t u a l P i x e l %
2228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2230 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2231 % (x,y) location. The image background color is returned if an error occurs.
2232 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2234 % The format of the GetOneVirtualPixel() method is:
2236 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
2237 % const ssize_t y,Quantum *pixel,ExceptionInfo exception)
2239 % A description of each parameter follows:
2241 % o image: the image.
2243 % o x,y: These values define the location of the pixel to return.
2245 % o pixel: return a pixel at the specified (x,y) location.
2247 % o exception: return any errors or warnings in this structure.
2250 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2251 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2257 id = GetOpenMPThreadId();
2265 assert(image != (const Image *) NULL);
2266 assert(image->signature == MagickSignature);
2267 assert(image->cache != (Cache) NULL);
2268 cache_info=(CacheInfo *) image->cache;
2269 assert(cache_info->signature == MagickSignature);
2270 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2271 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2272 (GetOneVirtualPixelFromHandler) NULL)
2273 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2274 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2275 assert(id < (int) cache_info->number_threads);
2276 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2277 1UL,1UL,cache_info->nexus_info[id],exception);
2278 if (p == (const Quantum *) NULL)
2280 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2281 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2282 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2283 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2284 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2285 return(MagickFalse);
2287 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2292 channel=GetPixelChannelMapChannel(image,i);
2293 pixel[channel]=p[i];
2299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2303 + 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 %
2307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2309 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2310 % specified (x,y) location. The image background color is returned if an
2313 % The format of the GetOneVirtualPixelFromCache() method is:
2315 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2316 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2317 % Quantum *pixel,ExceptionInfo *exception)
2319 % A description of each parameter follows:
2321 % o image: the image.
2323 % o virtual_pixel_method: the virtual pixel method.
2325 % o x,y: These values define the location of the pixel to return.
2327 % o pixel: return a pixel at the specified (x,y) location.
2329 % o exception: return any errors or warnings in this structure.
2332 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2333 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2334 Quantum *pixel,ExceptionInfo *exception)
2340 id = GetOpenMPThreadId();
2348 assert(image != (const Image *) NULL);
2349 assert(image->signature == MagickSignature);
2350 assert(image->cache != (Cache) NULL);
2351 cache_info=(CacheInfo *) image->cache;
2352 assert(cache_info->signature == MagickSignature);
2353 assert(id < (int) cache_info->number_threads);
2354 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2355 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2356 cache_info->nexus_info[id],exception);
2357 if (p == (const Quantum *) NULL)
2359 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2360 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2361 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2362 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2363 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2364 return(MagickFalse);
2366 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2371 channel=GetPixelChannelMapChannel(image,i);
2372 pixel[channel]=p[i];
2378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2382 % G e t O n e V i r t u a l P i x e l I n f o %
2386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2388 % GetOneVirtualPixelInfo() returns a single pixel at the specified (x,y)
2389 % location. The image background color is returned if an error occurs. If
2390 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2392 % The format of the GetOneVirtualPixelInfo() method is:
2394 % MagickBooleanType GetOneVirtualPixelInfo(const Image image,
2395 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2396 % const ssize_t y,PixelInfo *pixel,ExceptionInfo exception)
2398 % A description of each parameter follows:
2400 % o image: the image.
2402 % o virtual_pixel_method: the virtual pixel method.
2404 % o x,y: these values define the location of the pixel to return.
2406 % o pixel: return a pixel at the specified (x,y) location.
2408 % o exception: return any errors or warnings in this structure.
2411 MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
2412 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2413 PixelInfo *pixel,ExceptionInfo *exception)
2419 id = GetOpenMPThreadId();
2421 register const Quantum
2424 assert(image != (const Image *) NULL);
2425 assert(image->signature == MagickSignature);
2426 assert(image->cache != (Cache) NULL);
2427 cache_info=(CacheInfo *) image->cache;
2428 assert(cache_info->signature == MagickSignature);
2429 assert(id < (int) cache_info->number_threads);
2430 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2431 cache_info->nexus_info[id],exception);
2432 GetPixelInfo(image,pixel);
2433 if (p == (const Quantum *) NULL)
2434 return(MagickFalse);
2435 GetPixelInfoPixel(image,p,pixel);
2440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2444 + G e t P i x e l C a c h e C o l o r s p a c e %
2448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2450 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2452 % The format of the GetPixelCacheColorspace() method is:
2454 % Colorspace GetPixelCacheColorspace(Cache cache)
2456 % A description of each parameter follows:
2458 % o cache: the pixel cache.
2461 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
2466 assert(cache != (Cache) NULL);
2467 cache_info=(CacheInfo *) cache;
2468 assert(cache_info->signature == MagickSignature);
2469 if (cache_info->debug != MagickFalse)
2470 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2471 cache_info->filename);
2472 return(cache_info->colorspace);
2476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2480 + G e t P i x e l C a c h e M e t h o d s %
2484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2486 % GetPixelCacheMethods() initializes the CacheMethods structure.
2488 % The format of the GetPixelCacheMethods() method is:
2490 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2492 % A description of each parameter follows:
2494 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2497 MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
2499 assert(cache_methods != (CacheMethods *) NULL);
2500 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2501 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2502 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2503 cache_methods->get_virtual_metacontent_from_handler=
2504 GetVirtualMetacontentFromCache;
2505 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2506 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2507 cache_methods->get_authentic_metacontent_from_handler=
2508 GetAuthenticMetacontentFromCache;
2509 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2510 cache_methods->get_one_authentic_pixel_from_handler=
2511 GetOneAuthenticPixelFromCache;
2512 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2513 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2514 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2522 + G e t P i x e l C a c h e N e x u s E x t e n t %
2526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2528 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2529 % corresponding with the last call to SetPixelCacheNexusPixels() or
2530 % GetPixelCacheNexusPixels().
2532 % The format of the GetPixelCacheNexusExtent() method is:
2534 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2535 % NexusInfo *nexus_info)
2537 % A description of each parameter follows:
2539 % o nexus_info: the nexus info.
2542 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2543 NexusInfo *nexus_info)
2551 assert(cache != NULL);
2552 cache_info=(CacheInfo *) cache;
2553 assert(cache_info->signature == MagickSignature);
2554 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2556 return((MagickSizeType) cache_info->columns*cache_info->rows);
2561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2565 + G e t P i x e l C a c h e N e x u s M e t a c o n t e n t %
2569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2571 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2574 % The format of the GetPixelCacheNexusMetacontent() method is:
2576 % void *GetPixelCacheNexusMetacontent(const Cache cache,
2577 % NexusInfo *nexus_info)
2579 % A description of each parameter follows:
2581 % o cache: the pixel cache.
2583 % o nexus_info: the cache nexus to return the meta-content.
2586 MagickPrivate void *GetPixelCacheNexusMetacontent(const Cache cache,
2587 NexusInfo *nexus_info)
2592 assert(cache != NULL);
2593 cache_info=(CacheInfo *) cache;
2594 assert(cache_info->signature == MagickSignature);
2595 if (cache_info->storage_class == UndefinedClass)
2596 return((void *) NULL);
2597 return(nexus_info->metacontent);
2601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2605 + G e t P i x e l C a c h e N e x u s P i x e l s %
2609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2611 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2614 % The format of the GetPixelCacheNexusPixels() method is:
2616 % Quantum *GetPixelCacheNexusPixels(const Cache cache,
2617 % NexusInfo *nexus_info)
2619 % A description of each parameter follows:
2621 % o cache: the pixel cache.
2623 % o nexus_info: the cache nexus to return the pixels.
2626 MagickPrivate Quantum *GetPixelCacheNexusPixels(const Cache cache,
2627 NexusInfo *nexus_info)
2632 assert(cache != NULL);
2633 cache_info=(CacheInfo *) cache;
2634 assert(cache_info->signature == MagickSignature);
2635 if (cache_info->storage_class == UndefinedClass)
2636 return((Quantum *) NULL);
2637 return(nexus_info->pixels);
2641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2645 + G e t P i x e l C a c h e P i x e l s %
2649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2651 % GetPixelCachePixels() returns the pixels associated with the specified image.
2653 % The format of the GetPixelCachePixels() method is:
2655 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2656 % ExceptionInfo *exception)
2658 % A description of each parameter follows:
2660 % o image: the image.
2662 % o length: the pixel cache length.
2664 % o exception: return any errors or warnings in this structure.
2667 MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2668 ExceptionInfo *exception)
2673 assert(image != (const Image *) NULL);
2674 assert(image->signature == MagickSignature);
2675 assert(image->cache != (Cache) NULL);
2676 assert(length != (MagickSizeType *) NULL);
2677 assert(exception != (ExceptionInfo *) NULL);
2678 assert(exception->signature == MagickSignature);
2679 cache_info=(CacheInfo *) image->cache;
2680 assert(cache_info->signature == MagickSignature);
2682 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2683 return((void *) NULL);
2684 *length=cache_info->length;
2685 return((void *) cache_info->pixels);
2689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2693 + 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 %
2697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2699 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2701 % The format of the GetPixelCacheStorageClass() method is:
2703 % ClassType GetPixelCacheStorageClass(Cache cache)
2705 % A description of each parameter follows:
2707 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2709 % o cache: the pixel cache.
2712 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
2717 assert(cache != (Cache) NULL);
2718 cache_info=(CacheInfo *) cache;
2719 assert(cache_info->signature == MagickSignature);
2720 if (cache_info->debug != MagickFalse)
2721 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2722 cache_info->filename);
2723 return(cache_info->storage_class);
2727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2731 + G e t P i x e l C a c h e T i l e S i z e %
2735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2737 % GetPixelCacheTileSize() returns the pixel cache tile size.
2739 % The format of the GetPixelCacheTileSize() method is:
2741 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2744 % A description of each parameter follows:
2746 % o image: the image.
2748 % o width: the optimize cache tile width in pixels.
2750 % o height: the optimize cache tile height in pixels.
2753 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
2759 assert(image != (Image *) NULL);
2760 assert(image->signature == MagickSignature);
2761 if (image->debug != MagickFalse)
2762 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2763 cache_info=(CacheInfo *) image->cache;
2764 assert(cache_info->signature == MagickSignature);
2765 *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2766 if (GetPixelCacheType(image) == DiskCache)
2767 *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2776 + G e t P i x e l C a c h e T y p e %
2780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2782 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2784 % The format of the GetPixelCacheType() method is:
2786 % CacheType GetPixelCacheType(const Image *image)
2788 % A description of each parameter follows:
2790 % o image: the image.
2793 MagickPrivate CacheType GetPixelCacheType(const Image *image)
2798 assert(image != (Image *) NULL);
2799 assert(image->signature == MagickSignature);
2800 assert(image->cache != (Cache) NULL);
2801 cache_info=(CacheInfo *) image->cache;
2802 assert(cache_info->signature == MagickSignature);
2803 return(cache_info->type);
2807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2811 + 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 %
2815 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2817 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2818 % pixel cache. A virtual pixel is any pixel access that is outside the
2819 % boundaries of the image cache.
2821 % The format of the GetPixelCacheVirtualMethod() method is:
2823 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2825 % A description of each parameter follows:
2827 % o image: the image.
2830 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2835 assert(image != (Image *) NULL);
2836 assert(image->signature == MagickSignature);
2837 assert(image->cache != (Cache) NULL);
2838 cache_info=(CacheInfo *) image->cache;
2839 assert(cache_info->signature == MagickSignature);
2840 return(cache_info->virtual_pixel_method);
2844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2848 + G e t V i r t u a l M e t a c o n t e n t F r o m C a c h e %
2852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2854 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2855 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2857 % The format of the GetVirtualMetacontentFromCache() method is:
2859 % void *GetVirtualMetacontentFromCache(const Image *image)
2861 % A description of each parameter follows:
2863 % o image: the image.
2866 static const void *GetVirtualMetacontentFromCache(const Image *image)
2872 id = GetOpenMPThreadId();
2877 assert(image != (const Image *) NULL);
2878 assert(image->signature == MagickSignature);
2879 assert(image->cache != (Cache) NULL);
2880 cache_info=(CacheInfo *) image->cache;
2881 assert(cache_info->signature == MagickSignature);
2882 assert(id < (int) cache_info->number_threads);
2883 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2884 cache_info->nexus_info[id]);
2885 return(metacontent);
2889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2893 + G e t V i r t u a l M e t a c o n t e n t F r o m N e x u s %
2897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2899 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2902 % The format of the GetVirtualMetacontentFromNexus() method is:
2904 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2905 % NexusInfo *nexus_info)
2907 % A description of each parameter follows:
2909 % o cache: the pixel cache.
2911 % o nexus_info: the cache nexus to return the meta-content.
2914 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
2915 NexusInfo *nexus_info)
2920 assert(cache != (Cache) NULL);
2921 cache_info=(CacheInfo *) cache;
2922 assert(cache_info->signature == MagickSignature);
2923 if (cache_info->storage_class == UndefinedClass)
2924 return((void *) NULL);
2925 return(nexus_info->metacontent);
2929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2933 % G e t V i r t u a l M e t a c o n t e n t %
2937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2939 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
2940 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
2941 % returned if the meta-content are not available.
2943 % The format of the GetVirtualMetacontent() method is:
2945 % const void *GetVirtualMetacontent(const Image *image)
2947 % A description of each parameter follows:
2949 % o image: the image.
2952 MagickExport const void *GetVirtualMetacontent(const Image *image)
2958 id = GetOpenMPThreadId();
2963 assert(image != (const Image *) NULL);
2964 assert(image->signature == MagickSignature);
2965 assert(image->cache != (Cache) NULL);
2966 cache_info=(CacheInfo *) image->cache;
2967 assert(cache_info->signature == MagickSignature);
2968 if (cache_info->methods.get_virtual_metacontent_from_handler !=
2969 (GetVirtualMetacontentFromHandler) NULL)
2971 metacontent=cache_info->methods.
2972 get_virtual_metacontent_from_handler(image);
2973 return(metacontent);
2975 assert(id < (int) cache_info->number_threads);
2976 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2977 cache_info->nexus_info[id]);
2978 return(metacontent);
2982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2986 + 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 %
2990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2992 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
2993 % pixel cache as defined by the geometry parameters. A pointer to the pixels
2994 % is returned if the pixels are transferred, otherwise a NULL is returned.
2996 % The format of the GetVirtualPixelsFromNexus() method is:
2998 % Quantum *GetVirtualPixelsFromNexus(const Image *image,
2999 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
3000 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
3001 % ExceptionInfo *exception)
3003 % A description of each parameter follows:
3005 % o image: the image.
3007 % o virtual_pixel_method: the virtual pixel method.
3009 % o x,y,columns,rows: These values define the perimeter of a region of
3012 % o nexus_info: the cache nexus to acquire.
3014 % o exception: return any errors or warnings in this structure.
3021 0, 48, 12, 60, 3, 51, 15, 63,
3022 32, 16, 44, 28, 35, 19, 47, 31,
3023 8, 56, 4, 52, 11, 59, 7, 55,
3024 40, 24, 36, 20, 43, 27, 39, 23,
3025 2, 50, 14, 62, 1, 49, 13, 61,
3026 34, 18, 46, 30, 33, 17, 45, 29,
3027 10, 58, 6, 54, 9, 57, 5, 53,
3028 42, 26, 38, 22, 41, 25, 37, 21
3031 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
3036 index=x+DitherMatrix[x & 0x07]-32L;
3039 if (index >= (ssize_t) columns)
3040 return((ssize_t) columns-1L);
3044 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
3049 index=y+DitherMatrix[y & 0x07]-32L;
3052 if (index >= (ssize_t) rows)
3053 return((ssize_t) rows-1L);
3057 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
3061 if (x >= (ssize_t) columns)
3062 return((ssize_t) (columns-1));
3066 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
3070 if (y >= (ssize_t) rows)
3071 return((ssize_t) (rows-1));
3075 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
3077 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
3080 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
3082 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
3085 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
3086 const size_t extent)
3092 Compute the remainder of dividing offset by extent. It returns not only
3093 the quotient (tile the offset falls in) but also the positive remainer
3094 within that tile such that 0 <= remainder < extent. This method is
3095 essentially a ldiv() using a floored modulo division rather than the
3096 normal default truncated modulo division.
3098 modulo.quotient=offset/(ssize_t) extent;
3101 modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
3105 MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
3106 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3107 const size_t columns,const size_t rows,NexusInfo *nexus_info,
3108 ExceptionInfo *exception)
3125 virtual_pixel[CompositePixelChannel];
3130 register const Quantum
3143 register unsigned char
3150 *virtual_metacontent;
3155 assert(image != (const Image *) NULL);
3156 assert(image->signature == MagickSignature);
3157 assert(image->cache != (Cache) NULL);
3158 cache_info=(CacheInfo *) image->cache;
3159 assert(cache_info->signature == MagickSignature);
3160 if (cache_info->type == UndefinedCache)
3161 return((const Quantum *) NULL);
3164 region.width=columns;
3166 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3167 if (pixels == (Quantum *) NULL)
3168 return((const Quantum *) NULL);
3170 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3171 nexus_info->region.x;
3172 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3173 nexus_info->region.width-1L;
3174 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3175 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3176 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3177 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3183 Pixel request is inside cache extents.
3185 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3187 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3188 if (status == MagickFalse)
3189 return((const Quantum *) NULL);
3190 if (cache_info->metacontent_extent != 0)
3192 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3193 if (status == MagickFalse)
3194 return((const Quantum *) NULL);
3199 Pixel request is outside cache extents.
3201 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3202 virtual_nexus=AcquirePixelCacheNexus(1);
3203 if (virtual_nexus == (NexusInfo **) NULL)
3205 if (virtual_nexus != (NexusInfo **) NULL)
3206 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3207 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3208 "UnableToGetCacheNexus","`%s'",image->filename);
3209 return((const Quantum *) NULL);
3211 (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
3212 sizeof(*virtual_pixel));
3213 virtual_metacontent=(void *) NULL;
3214 switch (virtual_pixel_method)
3216 case BackgroundVirtualPixelMethod:
3217 case BlackVirtualPixelMethod:
3218 case GrayVirtualPixelMethod:
3219 case TransparentVirtualPixelMethod:
3220 case MaskVirtualPixelMethod:
3221 case WhiteVirtualPixelMethod:
3222 case EdgeVirtualPixelMethod:
3223 case CheckerTileVirtualPixelMethod:
3224 case HorizontalTileVirtualPixelMethod:
3225 case VerticalTileVirtualPixelMethod:
3227 if (cache_info->metacontent_extent != 0)
3230 Acquire a metacontent buffer.
3232 virtual_metacontent=(void *) AcquireQuantumMemory(1,
3233 cache_info->metacontent_extent);
3234 if (virtual_metacontent == (void *) NULL)
3236 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3237 (void) ThrowMagickException(exception,GetMagickModule(),
3238 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
3239 return((const Quantum *) NULL);
3241 (void) ResetMagickMemory(virtual_metacontent,0,
3242 cache_info->metacontent_extent);
3244 switch (virtual_pixel_method)
3246 case BlackVirtualPixelMethod:
3248 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3249 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3250 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3253 case GrayVirtualPixelMethod:
3255 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3256 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
3258 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3261 case TransparentVirtualPixelMethod:
3263 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3264 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3265 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3268 case MaskVirtualPixelMethod:
3269 case WhiteVirtualPixelMethod:
3271 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3272 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
3273 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3278 SetPixelRed(image,ClampToQuantum(image->background_color.red),
3280 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
3282 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
3284 if (image->colorspace == CMYKColorspace)
3285 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
3287 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
3297 for (v=0; v < (ssize_t) rows; v++)
3299 for (u=0; u < (ssize_t) columns; u+=length)
3301 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3302 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3303 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3311 Transfer a single pixel.
3313 length=(MagickSizeType) 1;
3314 switch (virtual_pixel_method)
3318 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3319 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3320 1UL,1UL,*virtual_nexus,exception);
3321 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3324 case RandomVirtualPixelMethod:
3326 if (cache_info->random_info == (RandomInfo *) NULL)
3327 cache_info->random_info=AcquireRandomInfo();
3328 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3329 RandomX(cache_info->random_info,cache_info->columns),
3330 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3331 *virtual_nexus,exception);
3332 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3335 case DitherVirtualPixelMethod:
3337 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3338 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3339 1UL,1UL,*virtual_nexus,exception);
3340 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3343 case TileVirtualPixelMethod:
3345 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3346 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3347 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3348 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3350 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3353 case MirrorVirtualPixelMethod:
3355 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3356 if ((x_modulo.quotient & 0x01) == 1L)
3357 x_modulo.remainder=(ssize_t) cache_info->columns-
3358 x_modulo.remainder-1L;
3359 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3360 if ((y_modulo.quotient & 0x01) == 1L)
3361 y_modulo.remainder=(ssize_t) cache_info->rows-
3362 y_modulo.remainder-1L;
3363 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3364 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3366 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3369 case HorizontalTileEdgeVirtualPixelMethod:
3371 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3372 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3373 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3374 *virtual_nexus,exception);
3375 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3378 case VerticalTileEdgeVirtualPixelMethod:
3380 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3381 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3382 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3383 *virtual_nexus,exception);
3384 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3387 case BackgroundVirtualPixelMethod:
3388 case BlackVirtualPixelMethod:
3389 case GrayVirtualPixelMethod:
3390 case TransparentVirtualPixelMethod:
3391 case MaskVirtualPixelMethod:
3392 case WhiteVirtualPixelMethod:
3395 r=virtual_metacontent;
3398 case EdgeVirtualPixelMethod:
3399 case CheckerTileVirtualPixelMethod:
3401 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3402 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3403 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3406 r=virtual_metacontent;
3409 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3410 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3412 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3415 case HorizontalTileVirtualPixelMethod:
3417 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3420 r=virtual_metacontent;
3423 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3424 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3425 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3426 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3428 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3431 case VerticalTileVirtualPixelMethod:
3433 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3436 r=virtual_metacontent;
3439 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3440 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3441 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3442 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3444 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3448 if (p == (const Quantum *) NULL)
3450 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3452 q+=cache_info->number_channels;
3453 if ((s != (void *) NULL) && (r != (const void *) NULL))
3455 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3456 s+=cache_info->metacontent_extent;
3461 Transfer a run of pixels.
3463 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3464 length,1UL,*virtual_nexus,exception);
3465 if (p == (const Quantum *) NULL)
3467 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3468 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3469 q+=length*cache_info->number_channels;
3470 if ((r != (void *) NULL) && (s != (const void *) NULL))
3472 (void) memcpy(s,r,(size_t) length);
3473 s+=length*cache_info->metacontent_extent;
3480 if (virtual_metacontent != (void *) NULL)
3481 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3482 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3491 + G e t V i r t u a l P i x e l C a c h e %
3495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3497 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3498 % cache as defined by the geometry parameters. A pointer to the pixels
3499 % is returned if the pixels are transferred, otherwise a NULL is returned.
3501 % The format of the GetVirtualPixelCache() method is:
3503 % const Quantum *GetVirtualPixelCache(const Image *image,
3504 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3505 % const ssize_t y,const size_t columns,const size_t rows,
3506 % ExceptionInfo *exception)
3508 % A description of each parameter follows:
3510 % o image: the image.
3512 % o virtual_pixel_method: the virtual pixel method.
3514 % o x,y,columns,rows: These values define the perimeter of a region of
3517 % o exception: return any errors or warnings in this structure.
3520 static const Quantum *GetVirtualPixelCache(const Image *image,
3521 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3522 const size_t columns,const size_t rows,ExceptionInfo *exception)
3528 id = GetOpenMPThreadId();
3533 assert(image != (const Image *) NULL);
3534 assert(image->signature == MagickSignature);
3535 assert(image->cache != (Cache) NULL);
3536 cache_info=(CacheInfo *) image->cache;
3537 assert(cache_info->signature == MagickSignature);
3538 assert(id < (int) cache_info->number_threads);
3539 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3540 cache_info->nexus_info[id],exception);
3545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3549 % G e t V i r t u a l P i x e l Q u e u e %
3553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3555 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3556 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3558 % The format of the GetVirtualPixelQueue() method is:
3560 % const Quantum *GetVirtualPixelQueue(const Image image)
3562 % A description of each parameter follows:
3564 % o image: the image.
3567 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3573 id = GetOpenMPThreadId();
3575 assert(image != (const Image *) NULL);
3576 assert(image->signature == MagickSignature);
3577 assert(image->cache != (Cache) NULL);
3578 cache_info=(CacheInfo *) image->cache;
3579 assert(cache_info->signature == MagickSignature);
3580 if (cache_info->methods.get_virtual_pixels_handler !=
3581 (GetVirtualPixelsHandler) NULL)
3582 return(cache_info->methods.get_virtual_pixels_handler(image));
3583 assert(id < (int) cache_info->number_threads);
3584 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3592 % G e t V i r t u a l P i x e l s %
3596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3598 % GetVirtualPixels() returns an immutable pixel region. If the
3599 % region is successfully accessed, a pointer to it is returned, otherwise
3600 % NULL is returned. The returned pointer may point to a temporary working
3601 % copy of the pixels or it may point to the original pixels in memory.
3602 % Performance is maximized if the selected region is part of one row, or one
3603 % or more full rows, since there is opportunity to access the pixels in-place
3604 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3605 % returned pointer must *never* be deallocated by the user.
3607 % Pixels accessed via the returned pointer represent a simple array of type
3608 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3609 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3610 % access the meta-content (of type void) corresponding to the the
3613 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3615 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3616 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3617 % GetCacheViewAuthenticPixels() instead.
3619 % The format of the GetVirtualPixels() method is:
3621 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3622 % const ssize_t y,const size_t columns,const size_t rows,
3623 % ExceptionInfo *exception)
3625 % A description of each parameter follows:
3627 % o image: the image.
3629 % o x,y,columns,rows: These values define the perimeter of a region of
3632 % o exception: return any errors or warnings in this structure.
3635 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3636 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3637 ExceptionInfo *exception)
3643 id = GetOpenMPThreadId();
3648 assert(image != (const Image *) NULL);
3649 assert(image->signature == MagickSignature);
3650 assert(image->cache != (Cache) NULL);
3651 cache_info=(CacheInfo *) image->cache;
3652 assert(cache_info->signature == MagickSignature);
3653 if (cache_info->methods.get_virtual_pixel_handler !=
3654 (GetVirtualPixelHandler) NULL)
3655 return(cache_info->methods.get_virtual_pixel_handler(image,
3656 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3657 assert(id < (int) cache_info->number_threads);
3658 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3659 columns,rows,cache_info->nexus_info[id],exception);
3664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3668 + 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 %
3672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3674 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3675 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3677 % The format of the GetVirtualPixelsCache() method is:
3679 % Quantum *GetVirtualPixelsCache(const Image *image)
3681 % A description of each parameter follows:
3683 % o image: the image.
3686 static const Quantum *GetVirtualPixelsCache(const Image *image)
3692 id = GetOpenMPThreadId();
3694 assert(image != (const Image *) NULL);
3695 assert(image->signature == MagickSignature);
3696 assert(image->cache != (Cache) NULL);
3697 cache_info=(CacheInfo *) image->cache;
3698 assert(cache_info->signature == MagickSignature);
3699 assert(id < (int) cache_info->number_threads);
3700 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3708 + G e t V i r t u a l P i x e l s N e x u s %
3712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3714 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3717 % The format of the GetVirtualPixelsNexus() method is:
3719 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3720 % NexusInfo *nexus_info)
3722 % A description of each parameter follows:
3724 % o cache: the pixel cache.
3726 % o nexus_info: the cache nexus to return the colormap pixels.
3729 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
3730 NexusInfo *nexus_info)
3735 assert(cache != (Cache) NULL);
3736 cache_info=(CacheInfo *) cache;
3737 assert(cache_info->signature == MagickSignature);
3738 if (cache_info->storage_class == UndefinedClass)
3739 return((Quantum *) NULL);
3740 return((const Quantum *) nexus_info->pixels);
3744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3748 + M a s k P i x e l C a c h e N e x u s %
3752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3754 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3755 % The method returns MagickTrue if the pixel region is masked, otherwise
3758 % The format of the MaskPixelCacheNexus() method is:
3760 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3761 % NexusInfo *nexus_info,ExceptionInfo *exception)
3763 % A description of each parameter follows:
3765 % o image: the image.
3767 % o nexus_info: the cache nexus to clip.
3769 % o exception: return any errors or warnings in this structure.
3772 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3773 ExceptionInfo *exception)
3785 register const Quantum
3796 Prevent updates to image pixels specified by the mask.
3798 if (image->debug != MagickFalse)
3799 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3800 if (image->mask == (Image *) NULL)
3801 return(MagickFalse);
3802 cache_info=(CacheInfo *) image->cache;
3803 if (cache_info == (Cache) NULL)
3804 return(MagickFalse);
3805 image_nexus=AcquirePixelCacheNexus(1);
3806 clip_nexus=AcquirePixelCacheNexus(1);
3807 if ((image_nexus == (NexusInfo **) NULL) ||
3808 (clip_nexus == (NexusInfo **) NULL))
3809 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3810 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3811 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3812 nexus_info->region.height,image_nexus[0],exception);
3813 q=nexus_info->pixels;
3814 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3815 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3816 nexus_info->region.height,clip_nexus[0],exception);
3817 number_pixels=(MagickSizeType) nexus_info->region.width*
3818 nexus_info->region.height;
3819 for (x=0; x < (ssize_t) number_pixels; x++)
3830 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3832 Sa=QuantumScale*GetPixelIntensity(image->mask,r);
3833 Da=QuantumScale*GetPixelAlpha(image,q);
3834 alpha=Sa*(-Da)+Sa+Da;
3835 gamma=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
3836 for (i=0; i < (ssize_t) image->number_channels; i++)
3849 channel=GetPixelChannelMapChannel(image,i);
3850 traits=GetPixelChannelMapTraits(image,channel);
3851 if (traits == UndefinedPixelTrait)
3853 Sc=(MagickRealType) p[i];
3854 Dc=(MagickRealType) q[i];
3855 pixel=gamma*(Sa*Sc-Sa*Da*Dc+Da*Dc);
3856 q[i]=ClampToQuantum(pixel);
3858 p+=GetPixelChannels(image);
3859 q+=GetPixelChannels(image);
3860 r+=GetPixelChannels(image->mask);
3862 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3863 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3864 if (x < (ssize_t) number_pixels)
3865 return(MagickFalse);
3870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3874 + O p e n P i x e l C a c h e %
3878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3880 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3881 % dimensions, allocating space for the image pixels and optionally the
3882 % metacontent, and memory mapping the cache if it is disk based. The cache
3883 % nexus array is initialized as well.
3885 % The format of the OpenPixelCache() method is:
3887 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3888 % ExceptionInfo *exception)
3890 % A description of each parameter follows:
3892 % o image: the image.
3894 % o mode: ReadMode, WriteMode, or IOMode.
3896 % o exception: return any errors or warnings in this structure.
3900 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3902 cache_info->mapped=MagickFalse;
3903 cache_info->pixels=(Quantum *) AcquireQuantumMemory(1,(size_t)
3904 cache_info->length);
3905 if (cache_info->pixels == (Quantum *) NULL)
3907 cache_info->mapped=MagickTrue;
3908 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3909 cache_info->length);
3913 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3923 cache_info=(CacheInfo *) image->cache;
3924 if (image->debug != MagickFalse)
3927 format[MaxTextExtent],
3928 message[MaxTextExtent];
3930 (void) FormatMagickSize(length,MagickFalse,format);
3931 (void) FormatLocaleString(message,MaxTextExtent,
3932 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3933 cache_info->cache_filename,cache_info->file,format);
3934 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3936 if (length != (MagickSizeType) ((MagickOffsetType) length))
3937 return(MagickFalse);
3938 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3940 return(MagickFalse);
3941 if ((MagickSizeType) extent >= length)
3943 offset=(MagickOffsetType) length-1;
3944 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3945 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3948 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3949 ExceptionInfo *exception)
3956 format[MaxTextExtent],
3957 message[MaxTextExtent];
3974 assert(image != (const Image *) NULL);
3975 assert(image->signature == MagickSignature);
3976 assert(image->cache != (Cache) NULL);
3977 if (image->debug != MagickFalse)
3978 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3979 if ((image->columns == 0) || (image->rows == 0))
3980 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3981 cache_info=(CacheInfo *) image->cache;
3982 assert(cache_info->signature == MagickSignature);
3983 source_info=(*cache_info);
3984 source_info.file=(-1);
3985 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
3986 image->filename,(double) GetImageIndexInList(image));
3987 cache_info->storage_class=image->storage_class;
3988 cache_info->colorspace=image->colorspace;
3989 cache_info->matte=image->matte;
3990 cache_info->rows=image->rows;
3991 cache_info->columns=image->columns;
3992 InitializePixelChannelMap(image);
3993 cache_info->number_channels=GetPixelChannels(image);
3994 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3995 sizeof(*image->channel_map));
3996 cache_info->metacontent_extent=image->metacontent_extent;
3997 cache_info->mode=mode;
3998 if (image->ping != MagickFalse)
4000 cache_info->type=PingCache;
4001 cache_info->pixels=(Quantum *) NULL;
4002 cache_info->metacontent=(void *) NULL;
4003 cache_info->length=0;
4006 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4007 packet_size=cache_info->number_channels*sizeof(Quantum);
4008 if (image->metacontent_extent != 0)
4009 packet_size+=cache_info->metacontent_extent;
4010 length=number_pixels*packet_size;
4011 columns=(size_t) (length/cache_info->rows/packet_size);
4012 if (cache_info->columns != columns)
4013 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4015 cache_info->length=length;
4016 p=cache_info->channel_map;
4017 q=source_info.channel_map;
4018 if ((cache_info->type != UndefinedCache) &&
4019 (cache_info->columns <= source_info.columns) &&
4020 (cache_info->rows <= source_info.rows) &&
4021 (cache_info->number_channels <= source_info.number_channels) &&
4022 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) &&
4023 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4026 Inline pixel cache clone optimization.
4028 if ((cache_info->columns == source_info.columns) &&
4029 (cache_info->rows == source_info.rows) &&
4030 (cache_info->number_channels == source_info.number_channels) &&
4031 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) &&
4032 (cache_info->metacontent_extent == source_info.metacontent_extent))
4034 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4036 status=AcquireMagickResource(AreaResource,cache_info->length);
4037 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4038 cache_info->metacontent_extent);
4039 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4041 status=AcquireMagickResource(MemoryResource,cache_info->length);
4042 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4043 (cache_info->type == MemoryCache))
4045 AllocatePixelCachePixels(cache_info);
4046 if (cache_info->pixels == (Quantum *) NULL)
4047 cache_info->pixels=source_info.pixels;
4051 Create memory pixel cache.
4054 if (image->debug != MagickFalse)
4056 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4057 (void) FormatLocaleString(message,MaxTextExtent,
4058 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4059 cache_info->filename,cache_info->mapped != MagickFalse ?
4060 "anonymous" : "heap",(double) cache_info->columns,(double)
4061 cache_info->rows,(double) cache_info->number_channels,
4063 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4066 cache_info->type=MemoryCache;
4067 cache_info->metacontent=(void *) NULL;
4068 if (cache_info->metacontent_extent != 0)
4069 cache_info->metacontent=(void *) (cache_info->pixels+
4070 number_pixels*cache_info->number_channels);
4071 if ((source_info.storage_class != UndefinedClass) &&
4074 status=ClonePixelCachePixels(cache_info,&source_info,
4076 RelinquishPixelCachePixels(&source_info);
4081 RelinquishMagickResource(MemoryResource,cache_info->length);
4084 Create pixel cache on disk.
4086 status=AcquireMagickResource(DiskResource,cache_info->length);
4087 if (status == MagickFalse)
4089 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4090 "CacheResourcesExhausted","`%s'",image->filename);
4091 return(MagickFalse);
4093 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4095 (void) ClosePixelCacheOnDisk(cache_info);
4096 *cache_info->cache_filename='\0';
4098 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4100 RelinquishMagickResource(DiskResource,cache_info->length);
4101 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4103 return(MagickFalse);
4105 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4106 cache_info->length);
4107 if (status == MagickFalse)
4109 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4111 return(MagickFalse);
4113 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4114 cache_info->metacontent_extent);
4115 if (length != (MagickSizeType) ((size_t) length))
4116 cache_info->type=DiskCache;
4119 status=AcquireMagickResource(MapResource,cache_info->length);
4120 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4121 (cache_info->type != MemoryCache))
4122 cache_info->type=DiskCache;
4125 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4126 cache_info->offset,(size_t) cache_info->length);
4127 if (cache_info->pixels == (Quantum *) NULL)
4129 cache_info->type=DiskCache;
4130 cache_info->pixels=source_info.pixels;
4135 Create file-backed memory-mapped pixel cache.
4138 (void) ClosePixelCacheOnDisk(cache_info);
4139 cache_info->type=MapCache;
4140 cache_info->mapped=MagickTrue;
4141 cache_info->metacontent=(void *) NULL;
4142 if (cache_info->metacontent_extent != 0)
4143 cache_info->metacontent=(void *) (cache_info->pixels+
4144 number_pixels*cache_info->number_channels);
4145 if ((source_info.storage_class != UndefinedClass) &&
4148 status=ClonePixelCachePixels(cache_info,&source_info,
4150 RelinquishPixelCachePixels(&source_info);
4152 if (image->debug != MagickFalse)
4154 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4155 (void) FormatLocaleString(message,MaxTextExtent,
4156 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4157 cache_info->filename,cache_info->cache_filename,
4158 cache_info->file,(double) cache_info->columns,(double)
4159 cache_info->rows,(double) cache_info->number_channels,
4161 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4167 RelinquishMagickResource(MapResource,cache_info->length);
4170 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4172 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4173 RelinquishPixelCachePixels(&source_info);
4175 if (image->debug != MagickFalse)
4177 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4178 (void) FormatLocaleString(message,MaxTextExtent,
4179 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4180 cache_info->cache_filename,cache_info->file,(double)
4181 cache_info->columns,(double) cache_info->rows,(double)
4182 cache_info->number_channels,format);
4183 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4193 + P e r s i s t P i x e l C a c h e %
4197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4199 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4200 % persistent pixel cache is one that resides on disk and is not destroyed
4201 % when the program exits.
4203 % The format of the PersistPixelCache() method is:
4205 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4206 % const MagickBooleanType attach,MagickOffsetType *offset,
4207 % ExceptionInfo *exception)
4209 % A description of each parameter follows:
4211 % o image: the image.
4213 % o filename: the persistent pixel cache filename.
4215 % o attach: A value other than zero initializes the persistent pixel cache.
4217 % o initialize: A value other than zero initializes the persistent pixel
4220 % o offset: the offset in the persistent cache to store pixels.
4222 % o exception: return any errors or warnings in this structure.
4225 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4226 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4227 ExceptionInfo *exception)
4242 assert(image != (Image *) NULL);
4243 assert(image->signature == MagickSignature);
4244 if (image->debug != MagickFalse)
4245 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4246 assert(image->cache != (void *) NULL);
4247 assert(filename != (const char *) NULL);
4248 assert(offset != (MagickOffsetType *) NULL);
4249 page_size=GetMagickPageSize();
4250 cache_info=(CacheInfo *) image->cache;
4251 assert(cache_info->signature == MagickSignature);
4252 if (attach != MagickFalse)
4255 Attach existing persistent pixel cache.
4257 if (image->debug != MagickFalse)
4258 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4259 "attach persistent cache");
4260 (void) CopyMagickString(cache_info->cache_filename,filename,
4262 cache_info->type=DiskCache;
4263 cache_info->offset=(*offset);
4264 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4265 return(MagickFalse);
4266 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4269 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4270 (cache_info->reference_count == 1))
4272 LockSemaphoreInfo(cache_info->semaphore);
4273 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4274 (cache_info->reference_count == 1))
4280 Usurp existing persistent pixel cache.
4282 status=rename_utf8(cache_info->cache_filename,filename);
4285 (void) CopyMagickString(cache_info->cache_filename,filename,
4287 *offset+=cache_info->length+page_size-(cache_info->length %
4289 UnlockSemaphoreInfo(cache_info->semaphore);
4290 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4291 if (image->debug != MagickFalse)
4292 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4293 "Usurp resident persistent cache");
4297 UnlockSemaphoreInfo(cache_info->semaphore);
4300 Clone persistent pixel cache.
4302 clone_image=(*image);
4303 clone_info=(CacheInfo *) clone_image.cache;
4304 image->cache=ClonePixelCache(cache_info);
4305 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4306 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4307 cache_info->type=DiskCache;
4308 cache_info->offset=(*offset);
4309 cache_info=(CacheInfo *) image->cache;
4310 status=OpenPixelCache(image,IOMode,exception);
4311 if (status != MagickFalse)
4312 status=ClonePixelCachePixels(cache_info,clone_info,exception);
4313 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4314 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4323 + Q u e u e A u t h e n t i c P i x e l C a c h e N e x u s %
4327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4329 % QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
4330 % defined by the region rectangle and returns a pointer to the region. This
4331 % region is subsequently transferred from the pixel cache with
4332 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4333 % pixels are transferred, otherwise a NULL is returned.
4335 % The format of the QueueAuthenticPixelCacheNexus() method is:
4337 % Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
4338 % const ssize_t y,const size_t columns,const size_t rows,
4339 % const MagickBooleanType clone,NexusInfo *nexus_info,
4340 % ExceptionInfo *exception)
4342 % A description of each parameter follows:
4344 % o image: the image.
4346 % o x,y,columns,rows: These values define the perimeter of a region of
4349 % o nexus_info: the cache nexus to set.
4351 % o clone: clone the pixel cache.
4353 % o exception: return any errors or warnings in this structure.
4356 MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4357 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
4358 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4373 Validate pixel cache geometry.
4375 assert(image != (const Image *) NULL);
4376 assert(image->signature == MagickSignature);
4377 assert(image->cache != (Cache) NULL);
4378 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4379 if (cache_info == (Cache) NULL)
4380 return((Quantum *) NULL);
4381 assert(cache_info->signature == MagickSignature);
4382 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4384 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4385 "NoPixelsDefinedInCache","`%s'",image->filename);
4386 return((Quantum *) NULL);
4388 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4389 (y >= (ssize_t) cache_info->rows))
4391 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4392 "PixelsAreNotAuthentic","`%s'",image->filename);
4393 return((Quantum *) NULL);
4395 offset=(MagickOffsetType) y*cache_info->columns+x;
4397 return((Quantum *) NULL);
4398 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4399 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4400 if ((MagickSizeType) offset >= number_pixels)
4401 return((Quantum *) NULL);
4407 region.width=columns;
4409 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4417 + 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 %
4421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4423 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4424 % defined by the region rectangle and returns a pointer to the region. This
4425 % region is subsequently transferred from the pixel cache with
4426 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4427 % pixels are transferred, otherwise a NULL is returned.
4429 % The format of the QueueAuthenticPixelsCache() method is:
4431 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4432 % const ssize_t y,const size_t columns,const size_t rows,
4433 % ExceptionInfo *exception)
4435 % A description of each parameter follows:
4437 % o image: the image.
4439 % o x,y,columns,rows: These values define the perimeter of a region of
4442 % o exception: return any errors or warnings in this structure.
4445 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4446 const ssize_t y,const size_t columns,const size_t rows,
4447 ExceptionInfo *exception)
4453 id = GetOpenMPThreadId();
4458 assert(image != (const Image *) NULL);
4459 assert(image->signature == MagickSignature);
4460 assert(image->cache != (Cache) NULL);
4461 cache_info=(CacheInfo *) image->cache;
4462 assert(cache_info->signature == MagickSignature);
4463 assert(id < (int) cache_info->number_threads);
4464 q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4465 cache_info->nexus_info[id],exception);
4470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4474 % Q u e u e A u t h e n t i c P i x e l s %
4478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4480 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4481 % successfully initialized a pointer to a Quantum array representing the
4482 % region is returned, otherwise NULL is returned. The returned pointer may
4483 % point to a temporary working buffer for the pixels or it may point to the
4484 % final location of the pixels in memory.
4486 % Write-only access means that any existing pixel values corresponding to
4487 % the region are ignored. This is useful if the initial image is being
4488 % created from scratch, or if the existing pixel values are to be
4489 % completely replaced without need to refer to their pre-existing values.
4490 % The application is free to read and write the pixel buffer returned by
4491 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4492 % initialize the pixel array values. Initializing pixel array values is the
4493 % application's responsibility.
4495 % Performance is maximized if the selected region is part of one row, or
4496 % one or more full rows, since then there is opportunity to access the
4497 % pixels in-place (without a copy) if the image is in memory, or in a
4498 % memory-mapped file. The returned pointer must *never* be deallocated
4501 % Pixels accessed via the returned pointer represent a simple array of type
4502 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4503 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4504 % obtain the meta-content (of type void) corresponding to the region.
4505 % Once the Quantum (and/or Quantum) array has been updated, the
4506 % changes must be saved back to the underlying image using
4507 % SyncAuthenticPixels() or they may be lost.
4509 % The format of the QueueAuthenticPixels() method is:
4511 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4512 % const ssize_t y,const size_t columns,const size_t rows,
4513 % ExceptionInfo *exception)
4515 % A description of each parameter follows:
4517 % o image: the image.
4519 % o x,y,columns,rows: These values define the perimeter of a region of
4522 % o exception: return any errors or warnings in this structure.
4525 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4526 const ssize_t y,const size_t columns,const size_t rows,
4527 ExceptionInfo *exception)
4533 id = GetOpenMPThreadId();
4538 assert(image != (Image *) NULL);
4539 assert(image->signature == MagickSignature);
4540 assert(image->cache != (Cache) NULL);
4541 cache_info=(CacheInfo *) image->cache;
4542 assert(cache_info->signature == MagickSignature);
4543 if (cache_info->methods.queue_authentic_pixels_handler !=
4544 (QueueAuthenticPixelsHandler) NULL)
4546 q=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4547 columns,rows,exception);
4550 assert(id < (int) cache_info->number_threads);
4551 q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4552 cache_info->nexus_info[id],exception);
4557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4561 + R e a d P i x e l C a c h e M e t a c o n t e n t %
4565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4567 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4570 % The format of the ReadPixelCacheMetacontent() method is:
4572 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4573 % NexusInfo *nexus_info,ExceptionInfo *exception)
4575 % A description of each parameter follows:
4577 % o cache_info: the pixel cache.
4579 % o nexus_info: the cache nexus to read the metacontent.
4581 % o exception: return any errors or warnings in this structure.
4584 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4585 NexusInfo *nexus_info,ExceptionInfo *exception)
4598 register unsigned char
4604 if (cache_info->metacontent_extent == 0)
4605 return(MagickFalse);
4606 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4608 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4609 nexus_info->region.x;
4610 length=(MagickSizeType) nexus_info->region.width*
4611 cache_info->metacontent_extent;
4612 rows=nexus_info->region.height;
4614 q=(unsigned char *) nexus_info->metacontent;
4615 switch (cache_info->type)
4620 register unsigned char
4624 Read meta-content from memory.
4626 if ((cache_info->columns == nexus_info->region.width) &&
4627 (extent == (MagickSizeType) ((size_t) extent)))
4632 p=(unsigned char *) cache_info->metacontent+offset*
4633 cache_info->metacontent_extent;
4634 for (y=0; y < (ssize_t) rows; y++)
4636 (void) memcpy(q,p,(size_t) length);
4637 p+=cache_info->metacontent_extent*cache_info->columns;
4638 q+=cache_info->metacontent_extent*nexus_info->region.width;
4645 Read meta content from disk.
4647 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4649 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4650 cache_info->cache_filename);
4651 return(MagickFalse);
4653 if ((cache_info->columns == nexus_info->region.width) &&
4654 (extent <= MagickMaxBufferExtent))
4659 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4660 for (y=0; y < (ssize_t) rows; y++)
4662 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4663 cache_info->number_channels*sizeof(Quantum)+offset*
4664 cache_info->metacontent_extent,length,(unsigned char *) q);
4665 if ((MagickSizeType) count != length)
4667 offset+=cache_info->columns;
4668 q+=cache_info->metacontent_extent*nexus_info->region.width;
4670 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4671 (void) ClosePixelCacheOnDisk(cache_info);
4672 if (y < (ssize_t) rows)
4674 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4675 cache_info->cache_filename);
4676 return(MagickFalse);
4683 if ((cache_info->debug != MagickFalse) &&
4684 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4685 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4686 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4687 nexus_info->region.width,(double) nexus_info->region.height,(double)
4688 nexus_info->region.x,(double) nexus_info->region.y);
4693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4697 + R e a d P i x e l C a c h e P i x e l s %
4701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4703 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4706 % The format of the ReadPixelCachePixels() method is:
4708 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4709 % NexusInfo *nexus_info,ExceptionInfo *exception)
4711 % A description of each parameter follows:
4713 % o cache_info: the pixel cache.
4715 % o nexus_info: the cache nexus to read the pixels.
4717 % o exception: return any errors or warnings in this structure.
4720 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4721 NexusInfo *nexus_info,ExceptionInfo *exception)
4740 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4742 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4743 nexus_info->region.x;
4744 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4746 rows=nexus_info->region.height;
4748 q=nexus_info->pixels;
4749 switch (cache_info->type)
4758 Read pixels from memory.
4760 if ((cache_info->columns == nexus_info->region.width) &&
4761 (extent == (MagickSizeType) ((size_t) extent)))
4766 p=cache_info->pixels+offset*cache_info->number_channels;
4767 for (y=0; y < (ssize_t) rows; y++)
4769 (void) memcpy(q,p,(size_t) length);
4770 p+=cache_info->number_channels*cache_info->columns;
4771 q+=cache_info->number_channels*nexus_info->region.width;
4778 Read pixels from disk.
4780 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4782 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4783 cache_info->cache_filename);
4784 return(MagickFalse);
4786 if ((cache_info->columns == nexus_info->region.width) &&
4787 (extent <= MagickMaxBufferExtent))
4792 for (y=0; y < (ssize_t) rows; y++)
4794 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4795 cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4796 if ((MagickSizeType) count != length)
4798 offset+=cache_info->columns;
4799 q+=cache_info->number_channels*nexus_info->region.width;
4801 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4802 (void) ClosePixelCacheOnDisk(cache_info);
4803 if (y < (ssize_t) rows)
4805 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4806 cache_info->cache_filename);
4807 return(MagickFalse);
4814 if ((cache_info->debug != MagickFalse) &&
4815 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4816 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4817 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4818 nexus_info->region.width,(double) nexus_info->region.height,(double)
4819 nexus_info->region.x,(double) nexus_info->region.y);
4824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4828 + R e f e r e n c e P i x e l C a c h e %
4832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4834 % ReferencePixelCache() increments the reference count associated with the
4835 % pixel cache returning a pointer to the cache.
4837 % The format of the ReferencePixelCache method is:
4839 % Cache ReferencePixelCache(Cache cache_info)
4841 % A description of each parameter follows:
4843 % o cache_info: the pixel cache.
4846 MagickPrivate Cache ReferencePixelCache(Cache cache)
4851 assert(cache != (Cache *) NULL);
4852 cache_info=(CacheInfo *) cache;
4853 assert(cache_info->signature == MagickSignature);
4854 LockSemaphoreInfo(cache_info->semaphore);
4855 cache_info->reference_count++;
4856 UnlockSemaphoreInfo(cache_info->semaphore);
4861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4865 + S e t P i x e l C a c h e M e t h o d s %
4869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4871 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4873 % The format of the SetPixelCacheMethods() method is:
4875 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4877 % A description of each parameter follows:
4879 % o cache: the pixel cache.
4881 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4884 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4889 GetOneAuthenticPixelFromHandler
4890 get_one_authentic_pixel_from_handler;
4892 GetOneVirtualPixelFromHandler
4893 get_one_virtual_pixel_from_handler;
4896 Set cache pixel methods.
4898 assert(cache != (Cache) NULL);
4899 assert(cache_methods != (CacheMethods *) NULL);
4900 cache_info=(CacheInfo *) cache;
4901 assert(cache_info->signature == MagickSignature);
4902 if (cache_info->debug != MagickFalse)
4903 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4904 cache_info->filename);
4905 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4906 cache_info->methods.get_virtual_pixel_handler=
4907 cache_methods->get_virtual_pixel_handler;
4908 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4909 cache_info->methods.destroy_pixel_handler=
4910 cache_methods->destroy_pixel_handler;
4911 if (cache_methods->get_virtual_metacontent_from_handler !=
4912 (GetVirtualMetacontentFromHandler) NULL)
4913 cache_info->methods.get_virtual_metacontent_from_handler=
4914 cache_methods->get_virtual_metacontent_from_handler;
4915 if (cache_methods->get_authentic_pixels_handler !=
4916 (GetAuthenticPixelsHandler) NULL)
4917 cache_info->methods.get_authentic_pixels_handler=
4918 cache_methods->get_authentic_pixels_handler;
4919 if (cache_methods->queue_authentic_pixels_handler !=
4920 (QueueAuthenticPixelsHandler) NULL)
4921 cache_info->methods.queue_authentic_pixels_handler=
4922 cache_methods->queue_authentic_pixels_handler;
4923 if (cache_methods->sync_authentic_pixels_handler !=
4924 (SyncAuthenticPixelsHandler) NULL)
4925 cache_info->methods.sync_authentic_pixels_handler=
4926 cache_methods->sync_authentic_pixels_handler;
4927 if (cache_methods->get_authentic_pixels_from_handler !=
4928 (GetAuthenticPixelsFromHandler) NULL)
4929 cache_info->methods.get_authentic_pixels_from_handler=
4930 cache_methods->get_authentic_pixels_from_handler;
4931 if (cache_methods->get_authentic_metacontent_from_handler !=
4932 (GetAuthenticMetacontentFromHandler) NULL)
4933 cache_info->methods.get_authentic_metacontent_from_handler=
4934 cache_methods->get_authentic_metacontent_from_handler;
4935 get_one_virtual_pixel_from_handler=
4936 cache_info->methods.get_one_virtual_pixel_from_handler;
4937 if (get_one_virtual_pixel_from_handler !=
4938 (GetOneVirtualPixelFromHandler) NULL)
4939 cache_info->methods.get_one_virtual_pixel_from_handler=
4940 cache_methods->get_one_virtual_pixel_from_handler;
4941 get_one_authentic_pixel_from_handler=
4942 cache_methods->get_one_authentic_pixel_from_handler;
4943 if (get_one_authentic_pixel_from_handler !=
4944 (GetOneAuthenticPixelFromHandler) NULL)
4945 cache_info->methods.get_one_authentic_pixel_from_handler=
4946 cache_methods->get_one_authentic_pixel_from_handler;
4950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4954 + S e t P i x e l C a c h e N e x u s P i x e l s %
4958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4960 % SetPixelCacheNexusPixels() defines the region of the cache for the
4961 % specified cache nexus.
4963 % The format of the SetPixelCacheNexusPixels() method is:
4965 % Quantum SetPixelCacheNexusPixels(const Image *image,
4966 % const RectangleInfo *region,NexusInfo *nexus_info,
4967 % ExceptionInfo *exception)
4969 % A description of each parameter follows:
4971 % o image: the image.
4973 % o region: A pointer to the RectangleInfo structure that defines the
4974 % region of this particular cache nexus.
4976 % o nexus_info: the cache nexus to set.
4978 % o exception: return any errors or warnings in this structure.
4982 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
4983 NexusInfo *nexus_info,ExceptionInfo *exception)
4985 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4986 return(MagickFalse);
4987 nexus_info->mapped=MagickFalse;
4988 nexus_info->cache=(Quantum *) AcquireAlignedMemory(1,(size_t)
4989 nexus_info->length);
4990 if (nexus_info->cache == (Quantum *) NULL)
4992 nexus_info->mapped=MagickTrue;
4993 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4994 nexus_info->length);
4996 if (nexus_info->cache == (Quantum *) NULL)
4998 (void) ThrowMagickException(exception,GetMagickModule(),
4999 ResourceLimitError,"MemoryAllocationFailed","`%s'",
5000 cache_info->filename);
5001 return(MagickFalse);
5006 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5007 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5019 cache_info=(CacheInfo *) image->cache;
5020 assert(cache_info->signature == MagickSignature);
5021 if (cache_info->type == UndefinedCache)
5022 return((Quantum *) NULL);
5023 nexus_info->region=(*region);
5024 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5025 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5031 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5032 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5033 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5034 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5035 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5036 ((nexus_info->region.width == cache_info->columns) ||
5037 ((nexus_info->region.width % cache_info->columns) == 0)))))
5043 Pixels are accessed directly from memory.
5045 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5046 nexus_info->region.x;
5047 nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5049 nexus_info->metacontent=(void *) NULL;
5050 if (cache_info->metacontent_extent != 0)
5051 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5052 offset*cache_info->metacontent_extent;
5053 return(nexus_info->pixels);
5057 Pixels are stored in a cache region until they are synced to the cache.
5059 number_pixels=(MagickSizeType) nexus_info->region.width*
5060 nexus_info->region.height;
5061 length=number_pixels*cache_info->number_channels*sizeof(Quantum);
5062 if (cache_info->metacontent_extent != 0)
5063 length+=number_pixels*cache_info->metacontent_extent;
5064 if (nexus_info->cache == (Quantum *) NULL)
5066 nexus_info->length=length;
5067 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5068 if (status == MagickFalse)
5070 nexus_info->length=0;
5071 return((Quantum *) NULL);
5075 if (nexus_info->length != length)
5077 RelinquishCacheNexusPixels(nexus_info);
5078 nexus_info->length=length;
5079 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5080 if (status == MagickFalse)
5082 nexus_info->length=0;
5083 return((Quantum *) NULL);
5086 nexus_info->pixels=nexus_info->cache;
5087 nexus_info->metacontent=(void *) NULL;
5088 if (cache_info->metacontent_extent != 0)
5089 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5090 cache_info->number_channels);
5091 return(nexus_info->pixels);
5095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5099 % 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 %
5103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5105 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5106 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5107 % access that is outside the boundaries of the image cache.
5109 % The format of the SetPixelCacheVirtualMethod() method is:
5111 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5112 % const VirtualPixelMethod virtual_pixel_method)
5114 % A description of each parameter follows:
5116 % o image: the image.
5118 % o virtual_pixel_method: choose the type of virtual pixel.
5121 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5122 const VirtualPixelMethod virtual_pixel_method)
5130 assert(image != (Image *) NULL);
5131 assert(image->signature == MagickSignature);
5132 if (image->debug != MagickFalse)
5133 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5134 assert(image->cache != (Cache) NULL);
5135 cache_info=(CacheInfo *) image->cache;
5136 assert(cache_info->signature == MagickSignature);
5137 method=cache_info->virtual_pixel_method;
5138 cache_info->virtual_pixel_method=virtual_pixel_method;
5143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5147 + 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 %
5151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5153 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5154 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5155 % is synced, otherwise MagickFalse.
5157 % The format of the SyncAuthenticPixelCacheNexus() method is:
5159 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5160 % NexusInfo *nexus_info,ExceptionInfo *exception)
5162 % A description of each parameter follows:
5164 % o image: the image.
5166 % o nexus_info: the cache nexus to sync.
5168 % o exception: return any errors or warnings in this structure.
5171 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5172 NexusInfo *nexus_info,ExceptionInfo *exception)
5181 Transfer pixels to the cache.
5183 assert(image != (Image *) NULL);
5184 assert(image->signature == MagickSignature);
5185 if (image->cache == (Cache) NULL)
5186 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5187 cache_info=(CacheInfo *) image->cache;
5188 assert(cache_info->signature == MagickSignature);
5189 if (cache_info->type == UndefinedCache)
5190 return(MagickFalse);
5191 if ((image->clip_mask != (Image *) NULL) &&
5192 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5193 return(MagickFalse);
5194 if ((image->mask != (Image *) NULL) &&
5195 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5196 return(MagickFalse);
5197 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5199 assert(cache_info->signature == MagickSignature);
5200 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5201 if ((cache_info->metacontent_extent != 0) &&
5202 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5203 return(MagickFalse);
5208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5212 + S y n c A u t h e n t i c P i x e l C a c h e %
5216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5218 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5219 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5220 % otherwise MagickFalse.
5222 % The format of the SyncAuthenticPixelsCache() method is:
5224 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5225 % ExceptionInfo *exception)
5227 % A description of each parameter follows:
5229 % o image: the image.
5231 % o exception: return any errors or warnings in this structure.
5234 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5235 ExceptionInfo *exception)
5241 id = GetOpenMPThreadId();
5246 assert(image != (Image *) NULL);
5247 assert(image->signature == MagickSignature);
5248 assert(image->cache != (Cache) NULL);
5249 cache_info=(CacheInfo *) image->cache;
5250 assert(cache_info->signature == MagickSignature);
5251 assert(id < (int) cache_info->number_threads);
5252 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5262 % S y n c A u t h e n t i c P i x e l s %
5266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5268 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5269 % The method returns MagickTrue if the pixel region is flushed, otherwise
5272 % The format of the SyncAuthenticPixels() method is:
5274 % MagickBooleanType SyncAuthenticPixels(Image *image,
5275 % ExceptionInfo *exception)
5277 % A description of each parameter follows:
5279 % o image: the image.
5281 % o exception: return any errors or warnings in this structure.
5284 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5285 ExceptionInfo *exception)
5291 id = GetOpenMPThreadId();
5296 assert(image != (Image *) NULL);
5297 assert(image->signature == MagickSignature);
5298 assert(image->cache != (Cache) NULL);
5299 cache_info=(CacheInfo *) image->cache;
5300 assert(cache_info->signature == MagickSignature);
5301 if (cache_info->methods.sync_authentic_pixels_handler !=
5302 (SyncAuthenticPixelsHandler) NULL)
5304 status=cache_info->methods.sync_authentic_pixels_handler(image,
5308 assert(id < (int) cache_info->number_threads);
5309 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5319 + S y n c I m a g e P i x e l C a c h e %
5323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5325 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5326 % The method returns MagickTrue if the pixel region is flushed, otherwise
5329 % The format of the SyncImagePixelCache() method is:
5331 % MagickBooleanType SyncImagePixelCache(Image *image,
5332 % ExceptionInfo *exception)
5334 % A description of each parameter follows:
5336 % o image: the image.
5338 % o exception: return any errors or warnings in this structure.
5341 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5342 ExceptionInfo *exception)
5347 assert(image != (Image *) NULL);
5348 assert(exception != (ExceptionInfo *) NULL);
5349 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5350 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5358 + W r i t e P i x e l C a c h e M e t a c o n t e n t %
5362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5364 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5365 % of the pixel cache.
5367 % The format of the WritePixelCacheMetacontent() method is:
5369 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5370 % NexusInfo *nexus_info,ExceptionInfo *exception)
5372 % A description of each parameter follows:
5374 % o cache_info: the pixel cache.
5376 % o nexus_info: the cache nexus to write the meta-content.
5378 % o exception: return any errors or warnings in this structure.
5381 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5382 NexusInfo *nexus_info,ExceptionInfo *exception)
5392 register const unsigned char
5401 if (cache_info->metacontent_extent == 0)
5402 return(MagickFalse);
5403 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5405 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5406 nexus_info->region.x;
5407 length=(MagickSizeType) nexus_info->region.width*
5408 cache_info->metacontent_extent;
5409 rows=nexus_info->region.height;
5410 extent=(MagickSizeType) length*rows;
5411 p=(unsigned char *) nexus_info->metacontent;
5412 switch (cache_info->type)
5417 register unsigned char
5421 Write associated pixels to memory.
5423 if ((cache_info->columns == nexus_info->region.width) &&
5424 (extent == (MagickSizeType) ((size_t) extent)))
5429 q=(unsigned char *) cache_info->metacontent+offset*
5430 cache_info->metacontent_extent;
5431 for (y=0; y < (ssize_t) rows; y++)
5433 (void) memcpy(q,p,(size_t) length);
5434 p+=nexus_info->region.width*cache_info->metacontent_extent;
5435 q+=cache_info->columns*cache_info->metacontent_extent;
5442 Write associated pixels to disk.
5444 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5446 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5447 cache_info->cache_filename);
5448 return(MagickFalse);
5450 if ((cache_info->columns == nexus_info->region.width) &&
5451 (extent <= MagickMaxBufferExtent))
5456 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5457 for (y=0; y < (ssize_t) rows; y++)
5459 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5460 cache_info->number_channels*sizeof(Quantum)+offset*
5461 cache_info->metacontent_extent,length,(const unsigned char *) p);
5462 if ((MagickSizeType) count != length)
5464 p+=nexus_info->region.width*cache_info->metacontent_extent;
5465 offset+=cache_info->columns;
5467 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5468 (void) ClosePixelCacheOnDisk(cache_info);
5469 if (y < (ssize_t) rows)
5471 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5472 cache_info->cache_filename);
5473 return(MagickFalse);
5480 if ((cache_info->debug != MagickFalse) &&
5481 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5482 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5483 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5484 nexus_info->region.width,(double) nexus_info->region.height,(double)
5485 nexus_info->region.x,(double) nexus_info->region.y);
5490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5494 + W r i t e C a c h e P i x e l s %
5498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5500 % WritePixelCachePixels() writes image pixels to the specified region of the
5503 % The format of the WritePixelCachePixels() method is:
5505 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5506 % NexusInfo *nexus_info,ExceptionInfo *exception)
5508 % A description of each parameter follows:
5510 % o cache_info: the pixel cache.
5512 % o nexus_info: the cache nexus to write the pixels.
5514 % o exception: return any errors or warnings in this structure.
5517 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5518 NexusInfo *nexus_info,ExceptionInfo *exception)
5528 register const Quantum
5537 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5539 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5540 nexus_info->region.x;
5541 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5543 rows=nexus_info->region.height;
5545 p=nexus_info->pixels;
5546 switch (cache_info->type)
5555 Write pixels to memory.
5557 if ((cache_info->columns == nexus_info->region.width) &&
5558 (extent == (MagickSizeType) ((size_t) extent)))
5563 q=cache_info->pixels+offset*cache_info->number_channels;
5564 for (y=0; y < (ssize_t) rows; y++)
5566 (void) memcpy(q,p,(size_t) length);
5567 p+=nexus_info->region.width*cache_info->number_channels;
5568 q+=cache_info->columns*cache_info->number_channels;
5575 Write pixels to disk.
5577 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5579 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5580 cache_info->cache_filename);
5581 return(MagickFalse);
5583 if ((cache_info->columns == nexus_info->region.width) &&
5584 (extent <= MagickMaxBufferExtent))
5589 for (y=0; y < (ssize_t) rows; y++)
5591 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5592 cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5594 if ((MagickSizeType) count != length)
5596 p+=nexus_info->region.width*cache_info->number_channels;
5597 offset+=cache_info->columns;
5599 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5600 (void) ClosePixelCacheOnDisk(cache_info);
5601 if (y < (ssize_t) rows)
5603 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5604 cache_info->cache_filename);
5605 return(MagickFalse);
5612 if ((cache_info->debug != MagickFalse) &&
5613 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5614 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5615 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5616 nexus_info->region.width,(double) nexus_info->region.height,(double)
5617 nexus_info->region.x,(double) nexus_info->region.y);