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-2011 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)
82 typedef struct _MagickModulo
112 Forward declarations.
114 #if defined(__cplusplus) || defined(c_plusplus)
119 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
120 const ssize_t,const size_t,const size_t,ExceptionInfo *),
121 *GetVirtualPixelsCache(const Image *);
124 *GetVirtualMetacontentFromCache(const Image *);
126 static MagickBooleanType
127 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,
128 PixelPacket *,ExceptionInfo *),
129 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
130 const ssize_t,const ssize_t,PixelPacket *,ExceptionInfo *),
131 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
132 ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
133 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
134 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
135 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
136 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
139 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
140 const size_t,ExceptionInfo *),
141 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
142 const size_t,ExceptionInfo *),
143 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *,
146 #if defined(__cplusplus) || defined(c_plusplus)
153 static volatile MagickBooleanType
154 instantiate_cache = MagickFalse;
157 *cache_semaphore = (SemaphoreInfo *) NULL;
160 *cache_resources = (SplayTreeInfo *) NULL;
163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167 + A c q u i r e P i x e l C a c h e %
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 % AcquirePixelCache() acquires a pixel cache.
175 % The format of the AcquirePixelCache() method is:
177 % Cache AcquirePixelCache(const size_t number_threads)
179 % A description of each parameter follows:
181 % o number_threads: the number of nexus threads.
184 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
189 cache_info=(CacheInfo *) AcquireAlignedMemory(1,sizeof(*cache_info));
190 if (cache_info == (CacheInfo *) NULL)
191 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
192 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
193 cache_info->type=UndefinedCache;
194 cache_info->mode=IOMode;
195 cache_info->colorspace=RGBColorspace;
196 cache_info->file=(-1);
197 cache_info->id=GetMagickThreadId();
198 cache_info->number_threads=number_threads;
199 if (number_threads == 0)
200 cache_info->number_threads=GetOpenMPMaximumThreads();
201 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
202 if (cache_info->nexus_info == (NexusInfo **) NULL)
203 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
204 cache_info->semaphore=AllocateSemaphoreInfo();
205 cache_info->reference_count=1;
206 cache_info->disk_semaphore=AllocateSemaphoreInfo();
207 cache_info->debug=IsEventLogging();
208 cache_info->signature=MagickSignature;
209 if ((cache_resources == (SplayTreeInfo *) NULL) &&
210 (instantiate_cache == MagickFalse))
212 if (cache_semaphore == (SemaphoreInfo *) NULL)
213 AcquireSemaphoreInfo(&cache_semaphore);
214 LockSemaphoreInfo(cache_semaphore);
215 if ((cache_resources == (SplayTreeInfo *) NULL) &&
216 (instantiate_cache == MagickFalse))
218 cache_resources=NewSplayTree((int (*)(const void *,const void *))
219 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
220 instantiate_cache=MagickTrue;
222 UnlockSemaphoreInfo(cache_semaphore);
224 (void) AddValueToSplayTree(cache_resources,cache_info,cache_info);
225 return((Cache ) cache_info);
229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233 % A c q u i r e P i x e l C a c h e N e x u s %
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 % AcquirePixelCacheNexus() allocates the NexusInfo structure.
241 % The format of the AcquirePixelCacheNexus method is:
243 % NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
245 % A description of each parameter follows:
247 % o number_threads: the number of nexus threads.
250 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
258 nexus_info=(NexusInfo **) AcquireAlignedMemory(number_threads,
259 sizeof(*nexus_info));
260 if (nexus_info == (NexusInfo **) NULL)
261 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
262 for (i=0; i < (ssize_t) number_threads; i++)
264 nexus_info[i]=(NexusInfo *) AcquireAlignedMemory(1,sizeof(**nexus_info));
265 if (nexus_info[i] == (NexusInfo *) NULL)
266 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
267 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
268 nexus_info[i]->signature=MagickSignature;
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 + A c q u i r e P i x e l C a c h e P i x e l s %
282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284 % AcquirePixelCachePixels() returns the pixels associated with the specified
287 % The format of the AcquirePixelCachePixels() method is:
289 % const void *AcquirePixelCachePixels(const Image *image,
290 % MagickSizeType *length,ExceptionInfo *exception)
292 % A description of each parameter follows:
294 % o image: the image.
296 % o length: the pixel cache length.
298 % o exception: return any errors or warnings in this structure.
301 MagickPrivate const void *AcquirePixelCachePixels(const Image *image,
302 MagickSizeType *length,ExceptionInfo *exception)
307 assert(image != (const Image *) NULL);
308 assert(image->signature == MagickSignature);
309 assert(exception != (ExceptionInfo *) NULL);
310 assert(exception->signature == MagickSignature);
311 assert(image->cache != (Cache) NULL);
312 cache_info=(CacheInfo *) image->cache;
313 assert(cache_info->signature == MagickSignature);
315 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
316 return((const void *) NULL);
317 *length=cache_info->length;
318 return((const void *) cache_info->pixels);
322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 + C a c h e C o m p o n e n t G e n e s i s %
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332 % CacheComponentGenesis() instantiates the cache component.
334 % The format of the CacheComponentGenesis method is:
336 % MagickBooleanType CacheComponentGenesis(void)
339 MagickPrivate MagickBooleanType CacheComponentGenesis(void)
341 AcquireSemaphoreInfo(&cache_semaphore);
346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 + C a c h e C o m p o n e n t T e r m i n u s %
354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356 % CacheComponentTerminus() destroys the cache component.
358 % The format of the CacheComponentTerminus() method is:
360 % CacheComponentTerminus(void)
363 MagickPrivate void CacheComponentTerminus(void)
365 if (cache_semaphore == (SemaphoreInfo *) NULL)
366 AcquireSemaphoreInfo(&cache_semaphore);
367 LockSemaphoreInfo(cache_semaphore);
368 if (cache_resources != (SplayTreeInfo *) NULL)
369 cache_resources=DestroySplayTree(cache_resources);
370 instantiate_cache=MagickFalse;
371 UnlockSemaphoreInfo(cache_semaphore);
372 DestroySemaphoreInfo(&cache_semaphore);
376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
380 + C l i p P i x e l C a c h e N e x u s %
384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386 % ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
387 % mask. It returns MagickTrue if the pixel region is clipped, otherwise
390 % The format of the ClipPixelCacheNexus() method is:
392 % MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
393 % ExceptionInfo *exception)
395 % A description of each parameter follows:
397 % o image: the image.
399 % o nexus_info: the cache nexus to clip.
401 % o exception: return any errors or warnings in this structure.
404 static MagickBooleanType ClipPixelCacheNexus(Image *image,
405 NexusInfo *nexus_info,ExceptionInfo *exception)
417 register const Quantum
430 if (image->debug != MagickFalse)
431 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
432 if (image->clip_mask == (Image *) NULL)
434 cache_info=(CacheInfo *) image->cache;
435 if (cache_info == (Cache) NULL)
437 image_nexus=AcquirePixelCacheNexus(1);
438 clip_nexus=AcquirePixelCacheNexus(1);
439 if ((image_nexus == (NexusInfo **) NULL) ||
440 (clip_nexus == (NexusInfo **) NULL))
441 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
442 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
443 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
444 nexus_info->region.height,image_nexus[0],exception);
445 q=nexus_info->pixels;
446 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
447 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
448 nexus_info->region.height,clip_nexus[0],exception);
449 number_pixels=(MagickSizeType) nexus_info->region.width*
450 nexus_info->region.height;
451 for (i=0; i < (ssize_t) number_pixels; i++)
453 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
455 if (GetPixelIntensity(image,r) > ((Quantum) QuantumRange/2))
457 SetPixelRed(image,GetPixelRed(image,p),q);
458 SetPixelGreen(image,GetPixelGreen(image,p),q);
459 SetPixelBlue(image,GetPixelBlue(image,p),q);
460 if (cache_info->colorspace == CMYKColorspace)
461 SetPixelBlack(image,GetPixelBlack(image,p),q);
462 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
464 p+=GetPixelChannels(image);
465 q+=GetPixelChannels(image);
466 r+=GetPixelChannels(image->clip_mask);
468 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
469 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
470 if (i < (ssize_t) number_pixels)
476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480 + C l o n e P i x e l C a c h e %
484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486 % ClonePixelCache() clones a pixel cache.
488 % The format of the ClonePixelCache() method is:
490 % Cache ClonePixelCache(const Cache cache)
492 % A description of each parameter follows:
494 % o cache: the pixel cache.
497 MagickPrivate Cache ClonePixelCache(const Cache cache)
505 assert(cache != (const Cache) NULL);
506 cache_info=(const CacheInfo *) cache;
507 assert(cache_info->signature == MagickSignature);
508 if (cache_info->debug != MagickFalse)
509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
510 cache_info->filename);
511 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
512 if (clone_info == (Cache) NULL)
513 return((Cache) NULL);
514 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
515 return((Cache ) clone_info);
519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
523 + C l o n e P i x e l C a c h e P i x e l s %
527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
528 % ClonePixelCachePixels() clones the source pixel cache to the destination
531 % The format of the ClonePixelCachePixels() method is:
533 % MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
534 % CacheInfo *source_info,ExceptionInfo *exception)
536 % A description of each parameter follows:
538 % o cache_info: the pixel cache.
540 % o source_info: the source pixel cache.
542 % o exception: return any errors or warnings in this structure.
546 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
552 LockSemaphoreInfo(cache_info->disk_semaphore);
553 if (cache_info->file != -1)
555 status=close(cache_info->file);
556 cache_info->file=(-1);
557 RelinquishMagickResource(FileResource,1);
559 UnlockSemaphoreInfo(cache_info->disk_semaphore);
560 return(status == -1 ? MagickFalse : MagickTrue);
563 static void LimitPixelCacheDescriptors(void)
570 Limit # of open file descriptors.
572 if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
574 LockSemaphoreInfo(cache_semaphore);
575 if (cache_resources == (SplayTreeInfo *) NULL)
577 UnlockSemaphoreInfo(cache_semaphore);
580 ResetSplayTreeIterator(cache_resources);
581 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
582 while (p != (CacheInfo *) NULL)
584 if ((p->type == DiskCache) && (p->file != -1))
586 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
588 for (q=p; p != (CacheInfo *) NULL; )
590 if ((p->type == DiskCache) && (p->file != -1) &&
591 (p->timestamp < q->timestamp))
593 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
595 if (q != (CacheInfo *) NULL)
598 Close least recently used cache.
600 (void) close(q->file);
603 UnlockSemaphoreInfo(cache_semaphore);
606 static inline MagickSizeType MagickMax(const MagickSizeType x,
607 const MagickSizeType y)
614 static inline MagickSizeType MagickMin(const MagickSizeType x,
615 const MagickSizeType y)
622 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
629 Open pixel cache on disk.
631 LockSemaphoreInfo(cache_info->disk_semaphore);
632 if (cache_info->file != -1)
634 UnlockSemaphoreInfo(cache_info->disk_semaphore);
635 return(MagickTrue); /* cache already open */
637 LimitPixelCacheDescriptors();
638 if (*cache_info->cache_filename == '\0')
639 file=AcquireUniqueFileResource(cache_info->cache_filename);
645 file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
650 file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
653 file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
659 file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
662 file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
668 UnlockSemaphoreInfo(cache_info->disk_semaphore);
671 (void) AcquireMagickResource(FileResource,1);
672 cache_info->file=file;
673 cache_info->timestamp=time(0);
674 UnlockSemaphoreInfo(cache_info->disk_semaphore);
678 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
679 const MagickOffsetType offset,const MagickSizeType length,
680 unsigned char *restrict buffer)
682 register MagickOffsetType
688 cache_info->timestamp=time(0);
689 #if !defined(MAGICKCORE_HAVE_PREAD)
690 LockSemaphoreInfo(cache_info->disk_semaphore);
691 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
693 UnlockSemaphoreInfo(cache_info->disk_semaphore);
694 return((MagickOffsetType) -1);
698 for (i=0; i < (MagickOffsetType) length; i+=count)
700 #if !defined(MAGICKCORE_HAVE_PREAD)
701 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
702 (MagickSizeType) SSIZE_MAX));
704 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
705 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
716 #if !defined(MAGICKCORE_HAVE_PREAD)
717 UnlockSemaphoreInfo(cache_info->disk_semaphore);
722 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
723 const MagickOffsetType offset,const MagickSizeType length,
724 const unsigned char *restrict buffer)
726 register MagickOffsetType
732 cache_info->timestamp=time(0);
733 #if !defined(MAGICKCORE_HAVE_PWRITE)
734 LockSemaphoreInfo(cache_info->disk_semaphore);
735 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
737 UnlockSemaphoreInfo(cache_info->disk_semaphore);
738 return((MagickOffsetType) -1);
742 for (i=0; i < (MagickOffsetType) length; i+=count)
744 #if !defined(MAGICKCORE_HAVE_PWRITE)
745 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
746 (MagickSizeType) SSIZE_MAX));
748 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
749 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
760 #if !defined(MAGICKCORE_HAVE_PWRITE)
761 UnlockSemaphoreInfo(cache_info->disk_semaphore);
766 static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info,
767 CacheInfo *cache_info,ExceptionInfo *exception)
772 register MagickOffsetType
782 Clone pixel cache (both caches on disk).
784 if (cache_info->debug != MagickFalse)
785 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
786 blob=(unsigned char *) AcquireAlignedMemory(MagickMaxBufferExtent,
788 if (blob == (unsigned char *) NULL)
790 (void) ThrowMagickException(exception,GetMagickModule(),
791 ResourceLimitError,"MemoryAllocationFailed","`%s'",
792 cache_info->filename);
795 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
797 blob=(unsigned char *) RelinquishMagickMemory(blob);
798 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
799 cache_info->cache_filename);
802 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
804 (void) ClosePixelCacheOnDisk(cache_info);
805 blob=(unsigned char *) RelinquishMagickMemory(blob);
806 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
807 clone_info->cache_filename);
811 for (i=0; i < (MagickOffsetType) cache_info->length; i+=count)
813 count=ReadPixelCacheRegion(cache_info,cache_info->offset+i,
814 MagickMin(cache_info->length-i,(MagickSizeType) MagickMaxBufferExtent),
818 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
819 cache_info->cache_filename);
822 length=(size_t) count;
823 count=WritePixelCacheRegion(clone_info,clone_info->offset+i,length,blob);
824 if ((MagickSizeType) count != length)
826 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
827 clone_info->cache_filename);
831 (void) ClosePixelCacheOnDisk(clone_info);
832 (void) ClosePixelCacheOnDisk(cache_info);
833 blob=(unsigned char *) RelinquishMagickMemory(blob);
834 if (i < (MagickOffsetType) cache_info->length)
839 static MagickBooleanType OptimizedPixelCacheClone(CacheInfo *clone_info,
840 CacheInfo *cache_info,ExceptionInfo *exception)
845 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
848 Clone pixel cache (both caches in memory).
850 if (cache_info->debug != MagickFalse)
851 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
852 (void) memcpy(clone_info->pixels,cache_info->pixels,(size_t)
856 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
859 Clone pixel cache (one cache on disk, one in memory).
861 if (cache_info->debug != MagickFalse)
862 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
863 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
865 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
866 cache_info->cache_filename);
869 count=ReadPixelCacheRegion(cache_info,cache_info->offset,
870 cache_info->length,(unsigned char *) clone_info->pixels);
871 (void) ClosePixelCacheOnDisk(cache_info);
872 if ((MagickSizeType) count != cache_info->length)
874 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
875 cache_info->cache_filename);
880 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
883 Clone pixel cache (one cache on disk, one in memory).
885 if (clone_info->debug != MagickFalse)
886 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
887 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
889 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
890 clone_info->cache_filename);
893 count=WritePixelCacheRegion(clone_info,clone_info->offset,
894 clone_info->length,(unsigned char *) cache_info->pixels);
895 (void) ClosePixelCacheOnDisk(clone_info);
896 if ((MagickSizeType) count != clone_info->length)
898 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
899 clone_info->cache_filename);
905 Clone pixel cache (both caches on disk).
907 return(DiskToDiskPixelCacheClone(clone_info,cache_info,exception));
910 static MagickBooleanType UnoptimizedPixelCacheClone(CacheInfo *clone_info,
911 CacheInfo *cache_info,ExceptionInfo *exception)
934 Clone pixel cache (unoptimized).
936 if (cache_info->debug != MagickFalse)
938 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
939 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
941 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
942 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
944 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
945 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
947 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
949 length=(size_t) MagickMax(MagickMax(cache_info->number_channels,
950 clone_info->number_channels)*sizeof(Quantum),MagickMax(
951 cache_info->metacontent_extent,clone_info->metacontent_extent));
952 blob=(unsigned char *) AcquireAlignedMemory(length,sizeof(*blob));
953 if (blob == (unsigned char *) NULL)
955 (void) ThrowMagickException(exception,GetMagickModule(),
956 ResourceLimitError,"MemoryAllocationFailed","`%s'",
957 cache_info->filename);
960 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
963 if (cache_info->type == DiskCache)
965 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
967 blob=(unsigned char *) RelinquishMagickMemory(blob);
968 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
969 cache_info->cache_filename);
972 cache_offset=cache_info->offset;
974 if (clone_info->type == DiskCache)
976 if ((cache_info->type == DiskCache) &&
977 (strcmp(cache_info->cache_filename,clone_info->cache_filename) == 0))
979 (void) ClosePixelCacheOnDisk(clone_info);
980 *clone_info->cache_filename='\0';
982 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
984 if (cache_info->type == DiskCache)
985 (void) ClosePixelCacheOnDisk(cache_info);
986 blob=(unsigned char *) RelinquishMagickMemory(blob);
987 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
988 clone_info->cache_filename);
991 clone_offset=clone_info->offset;
994 Clone pixel channels.
997 for (y=0; y < (ssize_t) cache_info->rows; y++)
999 for (x=0; x < (ssize_t) cache_info->columns; x++)
1002 Read a set of pixel channels.
1004 length=cache_info->number_channels*sizeof(Quantum);
1005 if (cache_info->type != DiskCache)
1006 (void) memcpy(blob,(unsigned char *) cache_info->pixels+cache_offset,
1010 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1011 if ((MagickSizeType) count != length)
1017 cache_offset+=length;
1018 if ((y < (ssize_t) clone_info->rows) &&
1019 (x < (ssize_t) clone_info->columns))
1022 Write a set of pixel channels.
1024 length=clone_info->number_channels*sizeof(Quantum);
1025 if (clone_info->type != DiskCache)
1026 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1030 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1031 if ((MagickSizeType) count != length)
1037 clone_offset+=length;
1040 length=clone_info->number_channels*sizeof(Quantum);
1041 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1042 for ( ; x < (ssize_t) clone_info->columns; x++)
1045 Set remaining columns with transparent pixel channels.
1047 if (clone_info->type != DiskCache)
1048 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1052 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1053 if ((MagickSizeType) count != length)
1059 clone_offset+=length;
1062 length=clone_info->number_channels*sizeof(Quantum);
1063 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1064 for ( ; y < (ssize_t) clone_info->rows; y++)
1067 Set remaining rows with transparent pixels.
1069 for (x=0; x < (ssize_t) clone_info->columns; x++)
1071 if (clone_info->type != DiskCache)
1072 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1076 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1077 if ((MagickSizeType) count != length)
1083 clone_offset+=length;
1086 if ((cache_info->metacontent_extent != 0) &&
1087 (clone_info->metacontent_extent != 0))
1092 for (y=0; y < (ssize_t) cache_info->rows; y++)
1094 for (x=0; x < (ssize_t) cache_info->columns; x++)
1097 Read a set of metacontent.
1099 length=cache_info->metacontent_extent;
1100 if (cache_info->type != DiskCache)
1101 (void) memcpy(blob,(unsigned char *) cache_info->pixels+
1102 cache_offset,length);
1105 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1106 if ((MagickSizeType) count != length)
1112 cache_offset+=length;
1113 if ((y < (ssize_t) clone_info->rows) &&
1114 (x < (ssize_t) clone_info->columns))
1117 Write a set of metacontent.
1119 length=clone_info->metacontent_extent;
1120 if (clone_info->type != DiskCache)
1121 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1125 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1127 if ((MagickSizeType) count != length)
1133 clone_offset+=length;
1136 length=clone_info->metacontent_extent;
1137 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1138 for ( ; x < (ssize_t) clone_info->columns; x++)
1141 Set remaining columns with metacontent.
1143 if (clone_info->type != DiskCache)
1144 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1148 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1149 if ((MagickSizeType) count != length)
1155 clone_offset+=length;
1158 length=clone_info->metacontent_extent;
1159 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1160 for ( ; y < (ssize_t) clone_info->rows; y++)
1163 Set remaining rows with metacontent.
1165 for (x=0; x < (ssize_t) clone_info->columns; x++)
1167 if (clone_info->type != DiskCache)
1168 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1172 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1173 if ((MagickSizeType) count != length)
1179 clone_offset+=length;
1183 if (clone_info->type == DiskCache)
1184 (void) ClosePixelCacheOnDisk(clone_info);
1185 if (cache_info->type == DiskCache)
1186 (void) ClosePixelCacheOnDisk(cache_info);
1187 blob=(unsigned char *) RelinquishMagickMemory(blob);
1191 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1192 CacheInfo *cache_info,ExceptionInfo *exception)
1194 if (cache_info->type == PingCache)
1196 if ((cache_info->columns == clone_info->columns) &&
1197 (cache_info->rows == clone_info->rows) &&
1198 (cache_info->number_channels == clone_info->number_channels) &&
1199 (cache_info->metacontent_extent == clone_info->metacontent_extent))
1200 return(OptimizedPixelCacheClone(clone_info,cache_info,exception));
1201 return(UnoptimizedPixelCacheClone(clone_info,cache_info,exception));
1205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209 + C l o n e P i x e l C a c h e M e t h o d s %
1213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1218 % The format of the ClonePixelCacheMethods() method is:
1220 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
1222 % A description of each parameter follows:
1224 % o clone: Specifies a pointer to a Cache structure.
1226 % o cache: the pixel cache.
1229 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
1235 assert(clone != (Cache) NULL);
1236 source_info=(CacheInfo *) clone;
1237 assert(source_info->signature == MagickSignature);
1238 if (source_info->debug != MagickFalse)
1239 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1240 source_info->filename);
1241 assert(cache != (Cache) NULL);
1242 cache_info=(CacheInfo *) cache;
1243 assert(cache_info->signature == MagickSignature);
1244 source_info->methods=cache_info->methods;
1248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252 + D e s t r o y I m a g e P i x e l C a c h e %
1256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1258 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1260 % The format of the DestroyImagePixelCache() method is:
1262 % void DestroyImagePixelCache(Image *image)
1264 % A description of each parameter follows:
1266 % o image: the image.
1269 static void DestroyImagePixelCache(Image *image)
1271 assert(image != (Image *) NULL);
1272 assert(image->signature == MagickSignature);
1273 if (image->debug != MagickFalse)
1274 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1275 if (image->cache == (void *) NULL)
1277 image->cache=DestroyPixelCache(image->cache);
1281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1285 + D e s t r o y I m a g e P i x e l s %
1289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1291 % DestroyImagePixels() deallocates memory associated with the pixel cache.
1293 % The format of the DestroyImagePixels() method is:
1295 % void DestroyImagePixels(Image *image)
1297 % A description of each parameter follows:
1299 % o image: the image.
1302 MagickExport void DestroyImagePixels(Image *image)
1307 assert(image != (const Image *) NULL);
1308 assert(image->signature == MagickSignature);
1309 if (image->debug != MagickFalse)
1310 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1311 assert(image->cache != (Cache) NULL);
1312 cache_info=(CacheInfo *) image->cache;
1313 assert(cache_info->signature == MagickSignature);
1314 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1316 cache_info->methods.destroy_pixel_handler(image);
1319 image->cache=DestroyPixelCache(image->cache);
1323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327 + D e s t r o y P i x e l C a c h e %
1331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1333 % DestroyPixelCache() deallocates memory associated with the pixel cache.
1335 % The format of the DestroyPixelCache() method is:
1337 % Cache DestroyPixelCache(Cache cache)
1339 % A description of each parameter follows:
1341 % o cache: the pixel cache.
1345 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1347 switch (cache_info->type)
1351 if (cache_info->mapped == MagickFalse)
1352 cache_info->pixels=(Quantum *) RelinquishMagickMemory(
1353 cache_info->pixels);
1355 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,
1356 (size_t) cache_info->length);
1357 RelinquishMagickResource(MemoryResource,cache_info->length);
1362 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t)
1363 cache_info->length);
1364 RelinquishMagickResource(MapResource,cache_info->length);
1368 if (cache_info->file != -1)
1369 (void) ClosePixelCacheOnDisk(cache_info);
1370 RelinquishMagickResource(DiskResource,cache_info->length);
1376 cache_info->type=UndefinedCache;
1377 cache_info->mapped=MagickFalse;
1378 cache_info->metacontent=(void *) NULL;
1381 MagickPrivate Cache DestroyPixelCache(Cache cache)
1386 assert(cache != (Cache) NULL);
1387 cache_info=(CacheInfo *) cache;
1388 assert(cache_info->signature == MagickSignature);
1389 if (cache_info->debug != MagickFalse)
1390 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1391 cache_info->filename);
1392 LockSemaphoreInfo(cache_info->semaphore);
1393 cache_info->reference_count--;
1394 if (cache_info->reference_count != 0)
1396 UnlockSemaphoreInfo(cache_info->semaphore);
1397 return((Cache) NULL);
1399 UnlockSemaphoreInfo(cache_info->semaphore);
1400 if (cache_resources != (SplayTreeInfo *) NULL)
1401 (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
1402 if (cache_info->debug != MagickFalse)
1405 message[MaxTextExtent];
1407 (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
1408 cache_info->filename);
1409 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1411 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1412 (cache_info->type != DiskCache)))
1413 RelinquishPixelCachePixels(cache_info);
1416 RelinquishPixelCachePixels(cache_info);
1417 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1419 *cache_info->cache_filename='\0';
1420 if (cache_info->nexus_info != (NexusInfo **) NULL)
1421 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1422 cache_info->number_threads);
1423 if (cache_info->random_info != (RandomInfo *) NULL)
1424 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1425 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1426 DestroySemaphoreInfo(&cache_info->disk_semaphore);
1427 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1428 DestroySemaphoreInfo(&cache_info->semaphore);
1429 cache_info->signature=(~MagickSignature);
1430 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
1436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440 + D e s t r o y P i x e l C a c h e N e x u s %
1444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1448 % The format of the DestroyPixelCacheNexus() method is:
1450 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1451 % const size_t number_threads)
1453 % A description of each parameter follows:
1455 % o nexus_info: the nexus to destroy.
1457 % o number_threads: the number of nexus threads.
1461 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1463 if (nexus_info->mapped == MagickFalse)
1464 (void) RelinquishMagickMemory(nexus_info->cache);
1466 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1467 nexus_info->cache=(Quantum *) NULL;
1468 nexus_info->pixels=(Quantum *) NULL;
1469 nexus_info->metacontent=(void *) NULL;
1470 nexus_info->length=0;
1471 nexus_info->mapped=MagickFalse;
1474 MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1475 const size_t number_threads)
1480 assert(nexus_info != (NexusInfo **) NULL);
1481 for (i=0; i < (ssize_t) number_threads; i++)
1483 if (nexus_info[i]->cache != (Quantum *) NULL)
1484 RelinquishCacheNexusPixels(nexus_info[i]);
1485 nexus_info[i]->signature=(~MagickSignature);
1486 nexus_info[i]=(NexusInfo *) RelinquishMagickMemory(nexus_info[i]);
1488 nexus_info=(NexusInfo **) RelinquishMagickMemory(nexus_info);
1493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1497 % G e t A u t h e n t i c M e t a c o n t e n t %
1501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1503 % GetAuthenticMetacontent() returns the authentic metacontent corresponding
1504 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
1505 % returned if the associated pixels are not available.
1507 % The format of the GetAuthenticMetacontent() method is:
1509 % void *GetAuthenticMetacontent(const Image *image)
1511 % A description of each parameter follows:
1513 % o image: the image.
1516 MagickExport void *GetAuthenticMetacontent(const Image *image)
1522 id = GetOpenMPThreadId();
1527 assert(image != (const Image *) NULL);
1528 assert(image->signature == MagickSignature);
1529 assert(image->cache != (Cache) NULL);
1530 cache_info=(CacheInfo *) image->cache;
1531 assert(cache_info->signature == MagickSignature);
1532 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1533 (GetAuthenticMetacontentFromHandler) NULL)
1535 metacontent=cache_info->methods.
1536 get_authentic_metacontent_from_handler(image);
1537 return(metacontent);
1539 assert(id < (int) cache_info->number_threads);
1540 metacontent=GetPixelCacheNexusMetacontent(cache_info,
1541 cache_info->nexus_info[id]);
1542 return(metacontent);
1546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1550 + 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 %
1554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding
1557 % with the last call to QueueAuthenticPixelsCache() or
1558 % GetAuthenticPixelsCache().
1560 % The format of the GetAuthenticMetacontentFromCache() method is:
1562 % void *GetAuthenticMetacontentFromCache(const Image *image)
1564 % A description of each parameter follows:
1566 % o image: the image.
1569 static void *GetAuthenticMetacontentFromCache(const Image *image)
1575 id = GetOpenMPThreadId();
1580 assert(image != (const Image *) NULL);
1581 assert(image->signature == MagickSignature);
1582 assert(image->cache != (Cache) NULL);
1583 cache_info=(CacheInfo *) image->cache;
1584 assert(cache_info->signature == MagickSignature);
1585 assert(id < (int) cache_info->number_threads);
1586 metacontent=GetPixelCacheNexusMetacontent(image->cache,
1587 cache_info->nexus_info[id]);
1588 return(metacontent);
1592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1596 + 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 %
1600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1602 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1603 % disk pixel cache as defined by the geometry parameters. A pointer to the
1604 % pixels is returned if the pixels are transferred, otherwise a NULL is
1607 % The format of the GetAuthenticPixelCacheNexus() method is:
1609 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
1610 % const ssize_t y,const size_t columns,const size_t rows,
1611 % NexusInfo *nexus_info,ExceptionInfo *exception)
1613 % A description of each parameter follows:
1615 % o image: the image.
1617 % o x,y,columns,rows: These values define the perimeter of a region of
1620 % o nexus_info: the cache nexus to return.
1622 % o exception: return any errors or warnings in this structure.
1626 static inline MagickBooleanType IsPixelAuthentic(const CacheInfo *cache_info,
1627 NexusInfo *nexus_info)
1635 if (cache_info->type == PingCache)
1637 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1638 nexus_info->region.x;
1639 status=nexus_info->pixels == (cache_info->pixels+offset*
1640 cache_info->number_channels) ? MagickTrue : MagickFalse;
1644 MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
1645 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
1646 NexusInfo *nexus_info,ExceptionInfo *exception)
1655 Transfer pixels from the cache.
1657 assert(image != (Image *) NULL);
1658 assert(image->signature == MagickSignature);
1659 q=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
1660 if (q == (Quantum *) NULL)
1661 return((Quantum *) NULL);
1662 cache_info=(CacheInfo *) image->cache;
1663 assert(cache_info->signature == MagickSignature);
1664 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
1666 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1667 return((Quantum *) NULL);
1668 if (cache_info->metacontent_extent != 0)
1669 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1670 return((Quantum *) NULL);
1675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1679 + 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 %
1683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1685 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1686 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1688 % The format of the GetAuthenticPixelsFromCache() method is:
1690 % Quantum *GetAuthenticPixelsFromCache(const Image image)
1692 % A description of each parameter follows:
1694 % o image: the image.
1697 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
1703 id = GetOpenMPThreadId();
1705 assert(image != (const Image *) NULL);
1706 assert(image->signature == MagickSignature);
1707 assert(image->cache != (Cache) NULL);
1708 cache_info=(CacheInfo *) image->cache;
1709 assert(cache_info->signature == MagickSignature);
1710 assert(id < (int) cache_info->number_threads);
1711 return(GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]));
1715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1719 % G e t A u t h e n t i c P i x e l Q u e u e %
1723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 % GetAuthenticPixelQueue() returns the authentic pixels associated
1726 % corresponding with the last call to QueueAuthenticPixels() or
1727 % GetAuthenticPixels().
1729 % The format of the GetAuthenticPixelQueue() method is:
1731 % Quantum *GetAuthenticPixelQueue(const Image image)
1733 % A description of each parameter follows:
1735 % o image: the image.
1738 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
1744 id = GetOpenMPThreadId();
1746 assert(image != (const Image *) NULL);
1747 assert(image->signature == MagickSignature);
1748 assert(image->cache != (Cache) NULL);
1749 cache_info=(CacheInfo *) image->cache;
1750 assert(cache_info->signature == MagickSignature);
1751 if (cache_info->methods.get_authentic_pixels_from_handler !=
1752 (GetAuthenticPixelsFromHandler) NULL)
1753 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1754 assert(id < (int) cache_info->number_threads);
1755 return(GetPixelCacheNexusPixels(cache_info,cache_info->nexus_info[id]));
1759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 % G e t A u t h e n t i c P i x e l s %
1766 % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1768 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1769 % region is successfully accessed, a pointer to a Quantum array
1770 % representing the region is returned, otherwise NULL is returned.
1772 % The returned pointer may point to a temporary working copy of the pixels
1773 % or it may point to the original pixels in memory. Performance is maximized
1774 % if the selected region is part of one row, or one or more full rows, since
1775 % then there is opportunity to access the pixels in-place (without a copy)
1776 % if the image is in memory, or in a memory-mapped file. The returned pointer
1777 % must *never* be deallocated by the user.
1779 % Pixels accessed via the returned pointer represent a simple array of type
1780 % Quantum. If the image has corresponding metacontent,call
1781 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
1782 % meta-content corresponding to the region. Once the Quantum array has
1783 % been updated, the changes must be saved back to the underlying image using
1784 % SyncAuthenticPixels() or they may be lost.
1786 % The format of the GetAuthenticPixels() method is:
1788 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1789 % const ssize_t y,const size_t columns,const size_t rows,
1790 % ExceptionInfo *exception)
1792 % A description of each parameter follows:
1794 % o image: the image.
1796 % o x,y,columns,rows: These values define the perimeter of a region of
1799 % o exception: return any errors or warnings in this structure.
1802 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1803 const ssize_t y,const size_t columns,const size_t rows,
1804 ExceptionInfo *exception)
1810 id = GetOpenMPThreadId();
1815 assert(image != (Image *) NULL);
1816 assert(image->signature == MagickSignature);
1817 assert(image->cache != (Cache) NULL);
1818 cache_info=(CacheInfo *) image->cache;
1819 assert(cache_info->signature == MagickSignature);
1820 if (cache_info->methods.get_authentic_pixels_handler !=
1821 (GetAuthenticPixelsHandler) NULL)
1823 q=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,rows,
1827 assert(id < (int) cache_info->number_threads);
1828 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1829 cache_info->nexus_info[id],exception);
1834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1838 + G e t A u t h e n t i c P i x e l s C a c h e %
1842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1844 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1845 % as defined by the geometry parameters. A pointer to the pixels is returned
1846 % if the pixels are transferred, otherwise a NULL is returned.
1848 % The format of the GetAuthenticPixelsCache() method is:
1850 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1851 % const ssize_t y,const size_t columns,const size_t rows,
1852 % ExceptionInfo *exception)
1854 % A description of each parameter follows:
1856 % o image: the image.
1858 % o x,y,columns,rows: These values define the perimeter of a region of
1861 % o exception: return any errors or warnings in this structure.
1864 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1865 const ssize_t y,const size_t columns,const size_t rows,
1866 ExceptionInfo *exception)
1872 id = GetOpenMPThreadId();
1877 assert(image != (const Image *) NULL);
1878 assert(image->signature == MagickSignature);
1879 assert(image->cache != (Cache) NULL);
1880 cache_info=(CacheInfo *) image->cache;
1881 if (cache_info == (Cache) NULL)
1882 return((Quantum *) NULL);
1883 assert(cache_info->signature == MagickSignature);
1884 assert(id < (int) cache_info->number_threads);
1885 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1886 cache_info->nexus_info[id],exception);
1891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1895 + G e t I m a g e E x t e n t %
1899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1901 % GetImageExtent() returns the extent of the pixels associated corresponding
1902 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
1904 % The format of the GetImageExtent() method is:
1906 % MagickSizeType GetImageExtent(const Image *image)
1908 % A description of each parameter follows:
1910 % o image: the image.
1913 MagickExport MagickSizeType GetImageExtent(const Image *image)
1919 id = GetOpenMPThreadId();
1921 assert(image != (Image *) NULL);
1922 assert(image->signature == MagickSignature);
1923 if (image->debug != MagickFalse)
1924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1925 assert(image->cache != (Cache) NULL);
1926 cache_info=(CacheInfo *) image->cache;
1927 assert(cache_info->signature == MagickSignature);
1928 assert(id < (int) cache_info->number_threads);
1929 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
1933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1937 + G e t I m a g e P i x e l C a c h e %
1941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1943 % GetImagePixelCache() ensures that there is only a single reference to the
1944 % pixel cache to be modified, updating the provided cache pointer to point to
1945 % a clone of the original pixel cache if necessary.
1947 % The format of the GetImagePixelCache method is:
1949 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1950 % ExceptionInfo *exception)
1952 % A description of each parameter follows:
1954 % o image: the image.
1956 % o clone: any value other than MagickFalse clones the cache pixels.
1958 % o exception: return any errors or warnings in this structure.
1962 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
1968 Does the image match the pixel cache morphology?
1970 cache_info=(CacheInfo *) image->cache;
1971 if ((image->storage_class != cache_info->storage_class) ||
1972 (image->colorspace != cache_info->colorspace) ||
1973 (image->matte != cache_info->matte) ||
1974 (image->columns != cache_info->columns) ||
1975 (image->rows != cache_info->rows) ||
1976 (image->number_channels != cache_info->number_channels) ||
1977 (image->metacontent_extent != cache_info->metacontent_extent) ||
1978 (cache_info->nexus_info == (NexusInfo **) NULL) ||
1979 (cache_info->number_threads < GetOpenMPMaximumThreads()))
1980 return(MagickFalse);
1984 static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1985 ExceptionInfo *exception)
1994 static MagickSizeType
2000 cache_timestamp = 0;
2003 LockSemaphoreInfo(image->semaphore);
2004 if (cpu_throttle == 0)
2010 Set CPU throttle in milleseconds.
2012 cpu_throttle=MagickResourceInfinity;
2013 limit=GetEnvironmentValue("MAGICK_THROTTLE");
2014 if (limit == (char *) NULL)
2015 limit=GetPolicyValue("throttle");
2016 if (limit != (char *) NULL)
2018 cpu_throttle=(MagickSizeType) StringToInteger(limit);
2019 limit=DestroyString(limit);
2022 if ((cpu_throttle != MagickResourceInfinity) && ((cycles++ % 32) == 0))
2023 MagickDelay(cpu_throttle);
2024 if (time_limit == 0)
2027 Set the exire time in seconds.
2029 time_limit=GetMagickResourceLimit(TimeResource);
2030 cache_timestamp=time((time_t *) NULL);
2032 if ((time_limit != MagickResourceInfinity) &&
2033 ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
2034 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
2035 assert(image->cache != (Cache) NULL);
2036 cache_info=(CacheInfo *) image->cache;
2037 destroy=MagickFalse;
2038 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2040 LockSemaphoreInfo(cache_info->semaphore);
2041 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2052 clone_image=(*image);
2053 clone_image.semaphore=AllocateSemaphoreInfo();
2054 clone_image.reference_count=1;
2055 clone_image.cache=ClonePixelCache(cache_info);
2056 clone_info=(CacheInfo *) clone_image.cache;
2057 status=OpenPixelCache(&clone_image,IOMode,exception);
2058 if (status != MagickFalse)
2060 if (clone != MagickFalse)
2061 status=ClonePixelCachePixels(clone_info,cache_info,exception);
2062 if (status != MagickFalse)
2064 if (cache_info->mode == ReadMode)
2065 cache_info->nexus_info=(NexusInfo **) NULL;
2067 image->cache=clone_image.cache;
2070 DestroySemaphoreInfo(&clone_image.semaphore);
2072 UnlockSemaphoreInfo(cache_info->semaphore);
2074 if (destroy != MagickFalse)
2075 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
2076 if (status != MagickFalse)
2079 Ensure the image matches the pixel cache morphology.
2081 image->taint=MagickTrue;
2082 image->type=UndefinedType;
2083 if (ValidatePixelCacheMorphology(image) == MagickFalse)
2084 status=OpenPixelCache(image,IOMode,exception);
2086 UnlockSemaphoreInfo(image->semaphore);
2087 if (status == MagickFalse)
2088 return((Cache) NULL);
2089 return(image->cache);
2093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2097 % G e t O n e A u t h e n t i c P i x e l %
2101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2103 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2104 % location. The image background color is returned if an error occurs.
2106 % The format of the GetOneAuthenticPixel() method is:
2108 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
2109 % const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2111 % A description of each parameter follows:
2113 % o image: the image.
2115 % o x,y: These values define the location of the pixel to return.
2117 % o pixel: return a pixel at the specified (x,y) location.
2119 % o exception: return any errors or warnings in this structure.
2122 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2123 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2131 assert(image != (Image *) NULL);
2132 assert(image->signature == MagickSignature);
2133 assert(image->cache != (Cache) NULL);
2134 cache_info=(CacheInfo *) image->cache;
2135 assert(cache_info->signature == MagickSignature);
2136 *pixel=image->background_color;
2137 if (cache_info->methods.get_one_authentic_pixel_from_handler !=
2138 (GetOneAuthenticPixelFromHandler) NULL)
2139 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2141 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2142 if (q == (Quantum *) NULL)
2143 return(MagickFalse);
2144 GetPixelPacket(image,q,pixel);
2149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2153 + 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 %
2157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2159 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2160 % location. The image background color is returned if an error occurs.
2162 % The format of the GetOneAuthenticPixelFromCache() method is:
2164 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2165 % const ssize_t x,const ssize_t y,PixelPacket *pixel,
2166 % ExceptionInfo *exception)
2168 % A description of each parameter follows:
2170 % o image: the image.
2172 % o x,y: These values define the location of the pixel to return.
2174 % o pixel: return a pixel at the specified (x,y) location.
2176 % o exception: return any errors or warnings in this structure.
2179 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2180 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2186 id = GetOpenMPThreadId();
2191 assert(image != (const Image *) NULL);
2192 assert(image->signature == MagickSignature);
2193 assert(image->cache != (Cache) NULL);
2194 cache_info=(CacheInfo *) image->cache;
2195 assert(cache_info->signature == MagickSignature);
2196 assert(id < (int) cache_info->number_threads);
2197 *pixel=image->background_color;
2198 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
2200 if (q == (Quantum *) NULL)
2201 return(MagickFalse);
2202 GetPixelPacket(image,q,pixel);
2207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2211 % G e t O n e V i r t u a l M a g i c k P i x e l %
2215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2217 % GetOneVirtualMagickPixel() returns a single pixel at the specified (x,y)
2218 % location. The image background color is returned if an error occurs. If
2219 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2221 % The format of the GetOneVirtualMagickPixel() method is:
2223 % MagickBooleanType GetOneVirtualMagickPixel(const Image image,
2224 % const ssize_t x,const ssize_t y,PixelInfo *pixel,
2225 % ExceptionInfo exception)
2227 % A description of each parameter follows:
2229 % o image: the image.
2231 % o x,y: these values define the location of the pixel to return.
2233 % o pixel: return a pixel at the specified (x,y) location.
2235 % o exception: return any errors or warnings in this structure.
2238 MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
2239 const ssize_t x,const ssize_t y,PixelInfo *pixel,
2240 ExceptionInfo *exception)
2246 id = GetOpenMPThreadId();
2248 register const Quantum
2251 assert(image != (const Image *) NULL);
2252 assert(image->signature == MagickSignature);
2253 assert(image->cache != (Cache) NULL);
2254 cache_info=(CacheInfo *) image->cache;
2255 assert(cache_info->signature == MagickSignature);
2256 assert(id < (int) cache_info->number_threads);
2257 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2258 1UL,1UL,cache_info->nexus_info[id],exception);
2259 GetPixelInfo(image,pixel);
2260 if (p == (const Quantum *) NULL)
2261 return(MagickFalse);
2262 SetPixelInfo(image,p,pixel);
2267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2271 % G e t O n e V i r t u a l M e t h o d P i x e l %
2275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2277 % GetOneVirtualMethodPixel() returns a single pixel at the specified (x,y)
2278 % location as defined by specified pixel method. The image background color
2279 % is returned if an error occurs. If you plan to modify the pixel, use
2280 % GetOneAuthenticPixel() instead.
2282 % The format of the GetOneVirtualMethodPixel() method is:
2284 % MagickBooleanType GetOneVirtualMethodPixel(const Image image,
2285 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2286 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2288 % A description of each parameter follows:
2290 % o image: the image.
2292 % o virtual_pixel_method: the virtual pixel method.
2294 % o x,y: These values define the location of the pixel to return.
2296 % o pixel: return a pixel at the specified (x,y) location.
2298 % o exception: return any errors or warnings in this structure.
2301 MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
2302 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2303 PixelPacket *pixel,ExceptionInfo *exception)
2309 id = GetOpenMPThreadId();
2314 assert(image != (const Image *) NULL);
2315 assert(image->signature == MagickSignature);
2316 assert(image->cache != (Cache) NULL);
2317 cache_info=(CacheInfo *) image->cache;
2318 assert(cache_info->signature == MagickSignature);
2319 *pixel=image->background_color;
2320 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2321 (GetOneVirtualPixelFromHandler) NULL)
2322 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2323 virtual_pixel_method,x,y,pixel,exception));
2324 assert(id < (int) cache_info->number_threads);
2325 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2326 cache_info->nexus_info[id],exception);
2327 if (p == (const Quantum *) NULL)
2328 return(MagickFalse);
2329 GetPixelPacket(image,p,pixel);
2330 if (image->colorspace == CMYKColorspace)
2331 pixel->black=GetPixelBlack(image,p);
2336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2340 % G e t O n e V i r t u a l P i x e l %
2344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2346 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2347 % (x,y) location. The image background color is returned if an error occurs.
2348 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2350 % The format of the GetOneVirtualPixel() method is:
2352 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
2353 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2355 % A description of each parameter follows:
2357 % o image: the image.
2359 % o x,y: These values define the location of the pixel to return.
2361 % o pixel: return a pixel at the specified (x,y) location.
2363 % o exception: return any errors or warnings in this structure.
2366 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2367 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2373 id = GetOpenMPThreadId();
2378 assert(image != (const Image *) NULL);
2379 assert(image->signature == MagickSignature);
2380 assert(image->cache != (Cache) NULL);
2381 cache_info=(CacheInfo *) image->cache;
2382 assert(cache_info->signature == MagickSignature);
2383 *pixel=image->background_color;
2384 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2385 (GetOneVirtualPixelFromHandler) NULL)
2386 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2387 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2388 assert(id < (int) cache_info->number_threads);
2389 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2390 1UL,1UL,cache_info->nexus_info[id],exception);
2391 if (p == (const Quantum *) NULL)
2392 return(MagickFalse);
2393 GetPixelPacket(image,p,pixel);
2394 if (image->colorspace == CMYKColorspace)
2395 pixel->black=GetPixelBlack(image,p);
2400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2404 + 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 %
2408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2410 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2411 % specified (x,y) location. The image background color is returned if an
2414 % The format of the GetOneVirtualPixelFromCache() method is:
2416 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2417 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2418 % PixelPacket *pixel,ExceptionInfo *exception)
2420 % A description of each parameter follows:
2422 % o image: the image.
2424 % o virtual_pixel_method: the virtual pixel method.
2426 % o x,y: These values define the location of the pixel to return.
2428 % o pixel: return a pixel at the specified (x,y) location.
2430 % o exception: return any errors or warnings in this structure.
2433 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2434 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2435 PixelPacket *pixel,ExceptionInfo *exception)
2441 id = GetOpenMPThreadId();
2446 assert(image != (const Image *) NULL);
2447 assert(image->signature == MagickSignature);
2448 assert(image->cache != (Cache) NULL);
2449 cache_info=(CacheInfo *) image->cache;
2450 assert(cache_info->signature == MagickSignature);
2451 assert(id < (int) cache_info->number_threads);
2452 *pixel=image->background_color;
2453 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2454 cache_info->nexus_info[id],exception);
2455 if (p == (const Quantum *) NULL)
2456 return(MagickFalse);
2457 GetPixelPacket(image,p,pixel);
2458 if (image->colorspace == CMYKColorspace)
2459 pixel->black=GetPixelBlack(image,p);
2464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2468 + G e t P i x e l C a c h e C o l o r s p a c e %
2472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2474 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2476 % The format of the GetPixelCacheColorspace() method is:
2478 % Colorspace GetPixelCacheColorspace(Cache cache)
2480 % A description of each parameter follows:
2482 % o cache: the pixel cache.
2485 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
2490 assert(cache != (Cache) NULL);
2491 cache_info=(CacheInfo *) cache;
2492 assert(cache_info->signature == MagickSignature);
2493 if (cache_info->debug != MagickFalse)
2494 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2495 cache_info->filename);
2496 return(cache_info->colorspace);
2500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2504 + G e t P i x e l C a c h e M e t h o d s %
2508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2510 % GetPixelCacheMethods() initializes the CacheMethods structure.
2512 % The format of the GetPixelCacheMethods() method is:
2514 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2516 % A description of each parameter follows:
2518 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2521 MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
2523 assert(cache_methods != (CacheMethods *) NULL);
2524 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2525 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2526 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2527 cache_methods->get_virtual_metacontent_from_handler=
2528 GetVirtualMetacontentFromCache;
2529 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2530 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2531 cache_methods->get_authentic_metacontent_from_handler=
2532 GetAuthenticMetacontentFromCache;
2533 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2534 cache_methods->get_one_authentic_pixel_from_handler=
2535 GetOneAuthenticPixelFromCache;
2536 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2537 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2538 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2546 + G e t P i x e l C a c h e N e x u s E x t e n t %
2550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2552 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2553 % corresponding with the last call to SetPixelCacheNexusPixels() or
2554 % GetPixelCacheNexusPixels().
2556 % The format of the GetPixelCacheNexusExtent() method is:
2558 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2559 % NexusInfo *nexus_info)
2561 % A description of each parameter follows:
2563 % o nexus_info: the nexus info.
2566 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2567 NexusInfo *nexus_info)
2575 assert(cache != (const Cache) NULL);
2576 cache_info=(CacheInfo *) cache;
2577 assert(cache_info->signature == MagickSignature);
2578 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2580 return((MagickSizeType) cache_info->columns*cache_info->rows);
2585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2589 + 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 %
2593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2595 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2598 % The format of the GetPixelCacheNexusMetacontent() method is:
2600 % void *GetPixelCacheNexusMetacontent(const Cache cache,
2601 % NexusInfo *nexus_info)
2603 % A description of each parameter follows:
2605 % o cache: the pixel cache.
2607 % o nexus_info: the cache nexus to return the meta-content.
2610 MagickPrivate void *GetPixelCacheNexusMetacontent(const Cache cache,
2611 NexusInfo *nexus_info)
2616 assert(cache != (const Cache) NULL);
2617 cache_info=(CacheInfo *) cache;
2618 assert(cache_info->signature == MagickSignature);
2619 if (cache_info->storage_class == UndefinedClass)
2620 return((void *) NULL);
2621 return(nexus_info->metacontent);
2625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2629 + G e t P i x e l C a c h e N e x u s P i x e l s %
2633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2635 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2638 % The format of the GetPixelCacheNexusPixels() method is:
2640 % Quantum *GetPixelCacheNexusPixels(const Cache cache,
2641 % NexusInfo *nexus_info)
2643 % A description of each parameter follows:
2645 % o cache: the pixel cache.
2647 % o nexus_info: the cache nexus to return the pixels.
2650 MagickPrivate Quantum *GetPixelCacheNexusPixels(const Cache cache,
2651 NexusInfo *nexus_info)
2656 assert(cache != (const Cache) NULL);
2657 cache_info=(CacheInfo *) cache;
2658 assert(cache_info->signature == MagickSignature);
2659 if (cache_info->storage_class == UndefinedClass)
2660 return((Quantum *) NULL);
2661 return(nexus_info->pixels);
2665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2669 + G e t P i x e l C a c h e P i x e l s %
2673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2675 % GetPixelCachePixels() returns the pixels associated with the specified image.
2677 % The format of the GetPixelCachePixels() method is:
2679 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2680 % ExceptionInfo *exception)
2682 % A description of each parameter follows:
2684 % o image: the image.
2686 % o length: the pixel cache length.
2688 % o exception: return any errors or warnings in this structure.
2691 MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2692 ExceptionInfo *exception)
2697 assert(image != (const Image *) NULL);
2698 assert(image->signature == MagickSignature);
2699 assert(image->cache != (Cache) NULL);
2700 assert(length != (MagickSizeType *) NULL);
2701 assert(exception != (ExceptionInfo *) NULL);
2702 assert(exception->signature == MagickSignature);
2703 cache_info=(CacheInfo *) image->cache;
2704 assert(cache_info->signature == MagickSignature);
2706 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2707 return((void *) NULL);
2708 *length=cache_info->length;
2709 return((void *) cache_info->pixels);
2713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2717 + 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 %
2721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2723 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2725 % The format of the GetPixelCacheStorageClass() method is:
2727 % ClassType GetPixelCacheStorageClass(Cache cache)
2729 % A description of each parameter follows:
2731 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2733 % o cache: the pixel cache.
2736 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
2741 assert(cache != (Cache) NULL);
2742 cache_info=(CacheInfo *) cache;
2743 assert(cache_info->signature == MagickSignature);
2744 if (cache_info->debug != MagickFalse)
2745 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2746 cache_info->filename);
2747 return(cache_info->storage_class);
2751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2755 + G e t P i x e l C a c h e T i l e S i z e %
2759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2761 % GetPixelCacheTileSize() returns the pixel cache tile size.
2763 % The format of the GetPixelCacheTileSize() method is:
2765 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2768 % A description of each parameter follows:
2770 % o image: the image.
2772 % o width: the optimize cache tile width in pixels.
2774 % o height: the optimize cache tile height in pixels.
2777 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
2783 assert(image != (Image *) NULL);
2784 assert(image->signature == MagickSignature);
2785 if (image->debug != MagickFalse)
2786 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2787 cache_info=(CacheInfo *) image->cache;
2788 assert(cache_info->signature == MagickSignature);
2789 *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2790 if (GetPixelCacheType(image) == DiskCache)
2791 *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2800 + G e t P i x e l C a c h e T y p e %
2804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2806 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2808 % The format of the GetPixelCacheType() method is:
2810 % CacheType GetPixelCacheType(const Image *image)
2812 % A description of each parameter follows:
2814 % o image: the image.
2817 MagickPrivate CacheType GetPixelCacheType(const Image *image)
2822 assert(image != (Image *) NULL);
2823 assert(image->signature == MagickSignature);
2824 assert(image->cache != (Cache) NULL);
2825 cache_info=(CacheInfo *) image->cache;
2826 assert(cache_info->signature == MagickSignature);
2827 return(cache_info->type);
2831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2835 + 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 %
2839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2841 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2842 % pixel cache. A virtual pixel is any pixel access that is outside the
2843 % boundaries of the image cache.
2845 % The format of the GetPixelCacheVirtualMethod() method is:
2847 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2849 % A description of each parameter follows:
2851 % o image: the image.
2854 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2859 assert(image != (Image *) NULL);
2860 assert(image->signature == MagickSignature);
2861 assert(image->cache != (Cache) NULL);
2862 cache_info=(CacheInfo *) image->cache;
2863 assert(cache_info->signature == MagickSignature);
2864 return(cache_info->virtual_pixel_method);
2868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2872 + 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 %
2876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2878 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2879 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2881 % The format of the GetVirtualMetacontentFromCache() method is:
2883 % void *GetVirtualMetacontentFromCache(const Image *image)
2885 % A description of each parameter follows:
2887 % o image: the image.
2890 static const void *GetVirtualMetacontentFromCache(const Image *image)
2896 id = GetOpenMPThreadId();
2901 assert(image != (const Image *) NULL);
2902 assert(image->signature == MagickSignature);
2903 assert(image->cache != (Cache) NULL);
2904 cache_info=(CacheInfo *) image->cache;
2905 assert(cache_info->signature == MagickSignature);
2906 assert(id < (int) cache_info->number_threads);
2907 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2908 cache_info->nexus_info[id]);
2909 return(metacontent);
2913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2917 + 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 %
2921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2923 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2926 % The format of the GetVirtualMetacontentFromNexus() method is:
2928 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2929 % NexusInfo *nexus_info)
2931 % A description of each parameter follows:
2933 % o cache: the pixel cache.
2935 % o nexus_info: the cache nexus to return the meta-content.
2938 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
2939 NexusInfo *nexus_info)
2944 assert(cache != (Cache) NULL);
2945 cache_info=(CacheInfo *) cache;
2946 assert(cache_info->signature == MagickSignature);
2947 if (cache_info->storage_class == UndefinedClass)
2948 return((void *) NULL);
2949 return(nexus_info->metacontent);
2953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2957 % G e t V i r t u a l M e t a c o n t e n t %
2961 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2963 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
2964 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
2965 % returned if the meta-content are not available.
2967 % The format of the GetVirtualMetacontent() method is:
2969 % const void *GetVirtualMetacontent(const Image *image)
2971 % A description of each parameter follows:
2973 % o image: the image.
2976 MagickExport const void *GetVirtualMetacontent(const Image *image)
2982 id = GetOpenMPThreadId();
2987 assert(image != (const Image *) NULL);
2988 assert(image->signature == MagickSignature);
2989 assert(image->cache != (Cache) NULL);
2990 cache_info=(CacheInfo *) image->cache;
2991 assert(cache_info->signature == MagickSignature);
2992 if (cache_info->methods.get_virtual_metacontent_from_handler !=
2993 (GetVirtualMetacontentFromHandler) NULL)
2995 metacontent=cache_info->methods.
2996 get_virtual_metacontent_from_handler(image);
2997 return(metacontent);
2999 assert(id < (int) cache_info->number_threads);
3000 metacontent=GetVirtualMetacontentFromNexus(cache_info,
3001 cache_info->nexus_info[id]);
3002 return(metacontent);
3006 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3010 + 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 %
3014 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3016 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
3017 % pixel cache as defined by the geometry parameters. A pointer to the pixels
3018 % is returned if the pixels are transferred, otherwise a NULL is returned.
3020 % The format of the GetVirtualPixelsFromNexus() method is:
3022 % Quantum *GetVirtualPixelsFromNexus(const Image *image,
3023 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
3024 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
3025 % ExceptionInfo *exception)
3027 % A description of each parameter follows:
3029 % o image: the image.
3031 % o virtual_pixel_method: the virtual pixel method.
3033 % o x,y,columns,rows: These values define the perimeter of a region of
3036 % o nexus_info: the cache nexus to acquire.
3038 % o exception: return any errors or warnings in this structure.
3045 0, 48, 12, 60, 3, 51, 15, 63,
3046 32, 16, 44, 28, 35, 19, 47, 31,
3047 8, 56, 4, 52, 11, 59, 7, 55,
3048 40, 24, 36, 20, 43, 27, 39, 23,
3049 2, 50, 14, 62, 1, 49, 13, 61,
3050 34, 18, 46, 30, 33, 17, 45, 29,
3051 10, 58, 6, 54, 9, 57, 5, 53,
3052 42, 26, 38, 22, 41, 25, 37, 21
3055 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
3060 index=x+DitherMatrix[x & 0x07]-32L;
3063 if (index >= (ssize_t) columns)
3064 return((ssize_t) columns-1L);
3068 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
3073 index=y+DitherMatrix[y & 0x07]-32L;
3076 if (index >= (ssize_t) rows)
3077 return((ssize_t) rows-1L);
3081 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
3085 if (x >= (ssize_t) columns)
3086 return((ssize_t) (columns-1));
3090 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
3094 if (y >= (ssize_t) rows)
3095 return((ssize_t) (rows-1));
3099 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
3101 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
3104 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
3106 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
3109 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
3110 const size_t extent)
3116 Compute the remainder of dividing offset by extent. It returns not only
3117 the quotient (tile the offset falls in) but also the positive remainer
3118 within that tile such that 0 <= remainder < extent. This method is
3119 essentially a ldiv() using a floored modulo division rather than the
3120 normal default truncated modulo division.
3122 modulo.quotient=offset/(ssize_t) extent;
3125 modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
3129 MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
3130 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3131 const size_t columns,const size_t rows,NexusInfo *nexus_info,
3132 ExceptionInfo *exception)
3149 virtual_pixel[MaxPixelChannels];
3154 register const Quantum
3167 register unsigned char
3174 *virtual_metacontent;
3179 assert(image != (const Image *) NULL);
3180 assert(image->signature == MagickSignature);
3181 assert(image->cache != (Cache) NULL);
3182 cache_info=(CacheInfo *) image->cache;
3183 assert(cache_info->signature == MagickSignature);
3184 if (cache_info->type == UndefinedCache)
3185 return((const Quantum *) NULL);
3188 region.width=columns;
3190 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3191 if (pixels == (Quantum *) NULL)
3192 return((const Quantum *) NULL);
3194 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3195 nexus_info->region.x;
3196 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3197 nexus_info->region.width-1L;
3198 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3199 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3200 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3201 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3207 Pixel request is inside cache extents.
3209 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3211 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3212 if (status == MagickFalse)
3213 return((const Quantum *) NULL);
3214 if (cache_info->metacontent_extent != 0)
3216 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3217 if (status == MagickFalse)
3218 return((const Quantum *) NULL);
3223 Pixel request is outside cache extents.
3225 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3226 virtual_nexus=AcquirePixelCacheNexus(1);
3227 if (virtual_nexus == (NexusInfo **) NULL)
3229 if (virtual_nexus != (NexusInfo **) NULL)
3230 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3231 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3232 "UnableToGetCacheNexus","`%s'",image->filename);
3233 return((const Quantum *) NULL);
3235 (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
3236 sizeof(*virtual_pixel));
3237 virtual_metacontent=(void *) NULL;
3238 switch (virtual_pixel_method)
3240 case BackgroundVirtualPixelMethod:
3241 case BlackVirtualPixelMethod:
3242 case GrayVirtualPixelMethod:
3243 case TransparentVirtualPixelMethod:
3244 case MaskVirtualPixelMethod:
3245 case WhiteVirtualPixelMethod:
3246 case EdgeVirtualPixelMethod:
3247 case CheckerTileVirtualPixelMethod:
3248 case HorizontalTileVirtualPixelMethod:
3249 case VerticalTileVirtualPixelMethod:
3251 if (cache_info->metacontent_extent != 0)
3254 Acquire a metacontent buffer.
3256 virtual_metacontent=(void *) AcquireAlignedMemory(1,
3257 cache_info->metacontent_extent);
3258 if (virtual_metacontent == (void *) NULL)
3260 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3261 (void) ThrowMagickException(exception,GetMagickModule(),
3262 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
3263 return((const Quantum *) NULL);
3265 (void) ResetMagickMemory(virtual_metacontent,0,
3266 cache_info->metacontent_extent);
3268 switch (virtual_pixel_method)
3270 case BlackVirtualPixelMethod:
3272 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3273 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3274 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3277 case GrayVirtualPixelMethod:
3279 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3280 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
3282 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3285 case TransparentVirtualPixelMethod:
3287 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3288 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3289 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3292 case MaskVirtualPixelMethod:
3293 case WhiteVirtualPixelMethod:
3295 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3296 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
3297 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3302 SetPixelRed(image,image->background_color.red,virtual_pixel);
3303 SetPixelGreen(image,image->background_color.green,virtual_pixel);
3304 SetPixelBlue(image,image->background_color.blue,virtual_pixel);
3305 if (image->colorspace == CMYKColorspace)
3306 SetPixelBlack(image,image->background_color.black,virtual_pixel);
3307 SetPixelAlpha(image,image->background_color.alpha,virtual_pixel);
3316 for (v=0; v < (ssize_t) rows; v++)
3318 for (u=0; u < (ssize_t) columns; u+=length)
3320 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3321 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3322 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3330 Transfer a single pixel.
3332 length=(MagickSizeType) 1;
3333 switch (virtual_pixel_method)
3337 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3338 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3339 1UL,1UL,*virtual_nexus,exception);
3340 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3343 case RandomVirtualPixelMethod:
3345 if (cache_info->random_info == (RandomInfo *) NULL)
3346 cache_info->random_info=AcquireRandomInfo();
3347 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3348 RandomX(cache_info->random_info,cache_info->columns),
3349 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3350 *virtual_nexus,exception);
3351 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3354 case DitherVirtualPixelMethod:
3356 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3357 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3358 1UL,1UL,*virtual_nexus,exception);
3359 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3362 case TileVirtualPixelMethod:
3364 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3365 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3366 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3367 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3369 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3372 case MirrorVirtualPixelMethod:
3374 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3375 if ((x_modulo.quotient & 0x01) == 1L)
3376 x_modulo.remainder=(ssize_t) cache_info->columns-
3377 x_modulo.remainder-1L;
3378 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3379 if ((y_modulo.quotient & 0x01) == 1L)
3380 y_modulo.remainder=(ssize_t) cache_info->rows-
3381 y_modulo.remainder-1L;
3382 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3383 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3385 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3388 case HorizontalTileEdgeVirtualPixelMethod:
3390 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3391 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3392 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3393 *virtual_nexus,exception);
3394 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3397 case VerticalTileEdgeVirtualPixelMethod:
3399 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3400 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3401 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3402 *virtual_nexus,exception);
3403 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3406 case BackgroundVirtualPixelMethod:
3407 case BlackVirtualPixelMethod:
3408 case GrayVirtualPixelMethod:
3409 case TransparentVirtualPixelMethod:
3410 case MaskVirtualPixelMethod:
3411 case WhiteVirtualPixelMethod:
3414 r=virtual_metacontent;
3417 case EdgeVirtualPixelMethod:
3418 case CheckerTileVirtualPixelMethod:
3420 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3421 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3422 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3425 r=virtual_metacontent;
3428 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3429 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3431 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3434 case HorizontalTileVirtualPixelMethod:
3436 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3439 r=virtual_metacontent;
3442 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3443 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3444 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3445 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3447 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3450 case VerticalTileVirtualPixelMethod:
3452 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3455 r=virtual_metacontent;
3458 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3459 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3460 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3461 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3463 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3467 if (p == (const Quantum *) NULL)
3469 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3471 q+=cache_info->number_channels;
3472 if ((s != (void *) NULL) && (r != (const void *) NULL))
3474 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3475 s+=cache_info->metacontent_extent;
3480 Transfer a run of pixels.
3482 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3483 length,1UL,*virtual_nexus,exception);
3484 if (p == (const Quantum *) NULL)
3486 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3487 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3488 q+=length*cache_info->number_channels;
3489 if ((r != (void *) NULL) && (s != (const void *) NULL))
3491 (void) memcpy(s,r,(size_t) length);
3492 s+=length*cache_info->metacontent_extent;
3499 if (virtual_metacontent != (void *) NULL)
3500 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3501 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3510 + G e t V i r t u a l P i x e l C a c h e %
3514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3516 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3517 % cache as defined by the geometry parameters. A pointer to the pixels
3518 % is returned if the pixels are transferred, otherwise a NULL is returned.
3520 % The format of the GetVirtualPixelCache() method is:
3522 % const Quantum *GetVirtualPixelCache(const Image *image,
3523 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3524 % const ssize_t y,const size_t columns,const size_t rows,
3525 % ExceptionInfo *exception)
3527 % A description of each parameter follows:
3529 % o image: the image.
3531 % o virtual_pixel_method: the virtual pixel method.
3533 % o x,y,columns,rows: These values define the perimeter of a region of
3536 % o exception: return any errors or warnings in this structure.
3539 static const Quantum *GetVirtualPixelCache(const Image *image,
3540 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3541 const size_t columns,const size_t rows,ExceptionInfo *exception)
3547 id = GetOpenMPThreadId();
3552 assert(image != (const Image *) NULL);
3553 assert(image->signature == MagickSignature);
3554 assert(image->cache != (Cache) NULL);
3555 cache_info=(CacheInfo *) image->cache;
3556 assert(cache_info->signature == MagickSignature);
3557 assert(id < (int) cache_info->number_threads);
3558 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3559 cache_info->nexus_info[id],exception);
3564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3568 % G e t V i r t u a l P i x e l Q u e u e %
3572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3574 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3575 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3577 % The format of the GetVirtualPixelQueue() method is:
3579 % const Quantum *GetVirtualPixelQueue(const Image image)
3581 % A description of each parameter follows:
3583 % o image: the image.
3586 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3592 id = GetOpenMPThreadId();
3594 assert(image != (const Image *) NULL);
3595 assert(image->signature == MagickSignature);
3596 assert(image->cache != (Cache) NULL);
3597 cache_info=(CacheInfo *) image->cache;
3598 assert(cache_info->signature == MagickSignature);
3599 if (cache_info->methods.get_virtual_pixels_handler !=
3600 (GetVirtualPixelsHandler) NULL)
3601 return(cache_info->methods.get_virtual_pixels_handler(image));
3602 assert(id < (int) cache_info->number_threads);
3603 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3611 % G e t V i r t u a l P i x e l s %
3615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3617 % GetVirtualPixels() returns an immutable pixel region. If the
3618 % region is successfully accessed, a pointer to it is returned, otherwise
3619 % NULL is returned. The returned pointer may point to a temporary working
3620 % copy of the pixels or it may point to the original pixels in memory.
3621 % Performance is maximized if the selected region is part of one row, or one
3622 % or more full rows, since there is opportunity to access the pixels in-place
3623 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3624 % returned pointer must *never* be deallocated by the user.
3626 % Pixels accessed via the returned pointer represent a simple array of type
3627 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3628 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3629 % access the meta-content (of type void) corresponding to the the
3632 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3634 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3635 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3636 % GetCacheViewAuthenticPixels() instead.
3638 % The format of the GetVirtualPixels() method is:
3640 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3641 % const ssize_t y,const size_t columns,const size_t rows,
3642 % ExceptionInfo *exception)
3644 % A description of each parameter follows:
3646 % o image: the image.
3648 % o x,y,columns,rows: These values define the perimeter of a region of
3651 % o exception: return any errors or warnings in this structure.
3654 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3655 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3656 ExceptionInfo *exception)
3662 id = GetOpenMPThreadId();
3667 assert(image != (const Image *) NULL);
3668 assert(image->signature == MagickSignature);
3669 assert(image->cache != (Cache) NULL);
3670 cache_info=(CacheInfo *) image->cache;
3671 assert(cache_info->signature == MagickSignature);
3672 if (cache_info->methods.get_virtual_pixel_handler !=
3673 (GetVirtualPixelHandler) NULL)
3674 return(cache_info->methods.get_virtual_pixel_handler(image,
3675 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3676 assert(id < (int) cache_info->number_threads);
3677 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3678 columns,rows,cache_info->nexus_info[id],exception);
3683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3687 + 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 %
3691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3693 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3694 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3696 % The format of the GetVirtualPixelsCache() method is:
3698 % Quantum *GetVirtualPixelsCache(const Image *image)
3700 % A description of each parameter follows:
3702 % o image: the image.
3705 static const Quantum *GetVirtualPixelsCache(const Image *image)
3711 id = GetOpenMPThreadId();
3713 assert(image != (const Image *) NULL);
3714 assert(image->signature == MagickSignature);
3715 assert(image->cache != (Cache) NULL);
3716 cache_info=(CacheInfo *) image->cache;
3717 assert(cache_info->signature == MagickSignature);
3718 assert(id < (int) cache_info->number_threads);
3719 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3727 + G e t V i r t u a l P i x e l s N e x u s %
3731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3733 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3736 % The format of the GetVirtualPixelsNexus() method is:
3738 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3739 % NexusInfo *nexus_info)
3741 % A description of each parameter follows:
3743 % o cache: the pixel cache.
3745 % o nexus_info: the cache nexus to return the colormap pixels.
3748 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
3749 NexusInfo *nexus_info)
3754 assert(cache != (Cache) NULL);
3755 cache_info=(CacheInfo *) cache;
3756 assert(cache_info->signature == MagickSignature);
3757 if (cache_info->storage_class == UndefinedClass)
3758 return((Quantum *) NULL);
3759 return((const Quantum *) nexus_info->pixels);
3763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3767 + M a s k P i x e l C a c h e N e x u s %
3771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3773 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3774 % The method returns MagickTrue if the pixel region is masked, otherwise
3777 % The format of the MaskPixelCacheNexus() method is:
3779 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3780 % NexusInfo *nexus_info,ExceptionInfo *exception)
3782 % A description of each parameter follows:
3784 % o image: the image.
3786 % o nexus_info: the cache nexus to clip.
3788 % o exception: return any errors or warnings in this structure.
3792 static inline void MagickPixelCompositeMask(const PixelInfo *p,
3793 const MagickRealType alpha,const PixelInfo *q,
3794 const MagickRealType beta,PixelInfo *composite)
3799 if (alpha == TransparentAlpha)
3804 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3805 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3806 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3807 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3808 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3809 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3810 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
3813 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3814 ExceptionInfo *exception)
3830 register const Quantum
3843 if (image->debug != MagickFalse)
3844 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3845 if (image->mask == (Image *) NULL)
3846 return(MagickFalse);
3847 cache_info=(CacheInfo *) image->cache;
3848 if (cache_info == (Cache) NULL)
3849 return(MagickFalse);
3850 image_nexus=AcquirePixelCacheNexus(1);
3851 clip_nexus=AcquirePixelCacheNexus(1);
3852 if ((image_nexus == (NexusInfo **) NULL) ||
3853 (clip_nexus == (NexusInfo **) NULL))
3854 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3855 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3856 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3857 nexus_info->region.height,image_nexus[0],exception);
3858 q=nexus_info->pixels;
3859 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3860 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3861 nexus_info->region.height,clip_nexus[0],&image->exception);
3862 GetPixelInfo(image,&alpha);
3863 GetPixelInfo(image,&beta);
3864 number_pixels=(MagickSizeType) nexus_info->region.width*
3865 nexus_info->region.height;
3866 for (i=0; i < (ssize_t) number_pixels; i++)
3868 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3870 SetPixelInfo(image,p,&alpha);
3871 SetPixelInfo(image,q,&beta);
3872 MagickPixelCompositeMask(&beta,(MagickRealType) GetPixelIntensity(image,r),
3873 &alpha,alpha.alpha,&beta);
3874 SetPixelRed(image,ClampToQuantum(beta.red),q);
3875 SetPixelGreen(image,ClampToQuantum(beta.green),q);
3876 SetPixelBlue(image,ClampToQuantum(beta.blue),q);
3877 if (cache_info->colorspace == CMYKColorspace)
3878 SetPixelBlack(image,ClampToQuantum(beta.black),q);
3879 SetPixelAlpha(image,ClampToQuantum(beta.alpha),q);
3884 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3885 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3886 if (i < (ssize_t) number_pixels)
3887 return(MagickFalse);
3892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3896 + O p e n P i x e l C a c h e %
3900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3902 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3903 % dimensions, allocating space for the image pixels and optionally the
3904 % metacontent, and memory mapping the cache if it is disk based. The cache
3905 % nexus array is initialized as well.
3907 % The format of the OpenPixelCache() method is:
3909 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3910 % ExceptionInfo *exception)
3912 % A description of each parameter follows:
3914 % o image: the image.
3916 % o mode: ReadMode, WriteMode, or IOMode.
3918 % o exception: return any errors or warnings in this structure.
3922 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3924 cache_info->mapped=MagickFalse;
3925 cache_info->pixels=(Quantum *) AcquireAlignedMemory(1,(size_t)
3926 cache_info->length);
3927 if (cache_info->pixels == (Quantum *) NULL)
3929 cache_info->mapped=MagickTrue;
3930 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3931 cache_info->length);
3935 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3945 cache_info=(CacheInfo *) image->cache;
3946 if (image->debug != MagickFalse)
3949 format[MaxTextExtent],
3950 message[MaxTextExtent];
3952 (void) FormatMagickSize(length,MagickFalse,format);
3953 (void) FormatLocaleString(message,MaxTextExtent,
3954 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3955 cache_info->cache_filename,cache_info->file,format);
3956 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3958 if (length != (MagickSizeType) ((MagickOffsetType) length))
3959 return(MagickFalse);
3960 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3962 return(MagickFalse);
3963 if ((MagickSizeType) extent >= length)
3965 offset=(MagickOffsetType) length-1;
3966 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3967 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3970 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3971 ExceptionInfo *exception)
3978 format[MaxTextExtent],
3979 message[MaxTextExtent];
3992 assert(image != (const Image *) NULL);
3993 assert(image->signature == MagickSignature);
3994 assert(image->cache != (Cache) NULL);
3995 if (image->debug != MagickFalse)
3996 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3997 if ((image->columns == 0) || (image->rows == 0))
3998 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3999 cache_info=(CacheInfo *) image->cache;
4000 assert(cache_info->signature == MagickSignature);
4001 source_info=(*cache_info);
4002 source_info.file=(-1);
4003 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
4004 image->filename,(double) GetImageIndexInList(image));
4005 cache_info->storage_class=image->storage_class;
4006 cache_info->colorspace=image->colorspace;
4007 cache_info->matte=image->matte;
4008 cache_info->rows=image->rows;
4009 cache_info->columns=image->columns;
4010 InitializePixelChannelMap(image);
4011 cache_info->number_channels=GetPixelChannels(image);
4012 cache_info->metacontent_extent=image->metacontent_extent;
4013 cache_info->mode=mode;
4014 if (image->ping != MagickFalse)
4016 cache_info->type=PingCache;
4017 cache_info->pixels=(Quantum *) NULL;
4018 cache_info->metacontent=(void *) NULL;
4019 cache_info->length=0;
4022 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4023 packet_size=cache_info->number_channels*sizeof(Quantum);
4024 if (image->metacontent_extent != 0)
4025 packet_size+=cache_info->metacontent_extent;
4026 length=number_pixels*packet_size;
4027 columns=(size_t) (length/cache_info->rows/packet_size);
4028 if (cache_info->columns != columns)
4029 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4031 cache_info->length=length;
4032 if ((cache_info->type != UndefinedCache) &&
4033 (cache_info->columns <= source_info.columns) &&
4034 (cache_info->rows <= source_info.rows) &&
4035 (cache_info->number_channels <= source_info.number_channels) &&
4036 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4039 Inline pixel cache clone optimization.
4041 if ((cache_info->columns == source_info.columns) &&
4042 (cache_info->rows == source_info.rows) &&
4043 (cache_info->number_channels == source_info.number_channels) &&
4044 (cache_info->metacontent_extent == source_info.metacontent_extent))
4046 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4048 status=AcquireMagickResource(AreaResource,cache_info->length);
4049 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4050 cache_info->metacontent_extent);
4051 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4053 status=AcquireMagickResource(MemoryResource,cache_info->length);
4054 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4055 (cache_info->type == MemoryCache))
4057 AllocatePixelCachePixels(cache_info);
4058 if (cache_info->pixels == (Quantum *) NULL)
4059 cache_info->pixels=source_info.pixels;
4063 Create memory pixel cache.
4066 if (image->debug != MagickFalse)
4068 (void) FormatMagickSize(cache_info->length,MagickTrue,
4070 (void) FormatLocaleString(message,MaxTextExtent,
4071 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4072 cache_info->filename,cache_info->mapped != MagickFalse ?
4073 "anonymous" : "heap",(double) cache_info->columns,(double)
4074 cache_info->rows,(double) cache_info->number_channels,
4076 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4079 cache_info->type=MemoryCache;
4080 cache_info->metacontent=(void *) NULL;
4081 if (cache_info->metacontent_extent != 0)
4082 cache_info->metacontent=(void *) (cache_info->pixels+
4083 number_pixels*cache_info->number_channels);
4084 if (source_info.storage_class != UndefinedClass)
4086 status=ClonePixelCachePixels(cache_info,&source_info,
4088 RelinquishPixelCachePixels(&source_info);
4093 RelinquishMagickResource(MemoryResource,cache_info->length);
4096 Create pixel cache on disk.
4098 status=AcquireMagickResource(DiskResource,cache_info->length);
4099 if (status == MagickFalse)
4101 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4102 "CacheResourcesExhausted","`%s'",image->filename);
4103 return(MagickFalse);
4105 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4107 RelinquishMagickResource(DiskResource,cache_info->length);
4108 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4110 return(MagickFalse);
4112 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4113 cache_info->length);
4114 if (status == MagickFalse)
4116 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4118 return(MagickFalse);
4120 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4121 cache_info->metacontent_extent);
4122 status=AcquireMagickResource(AreaResource,cache_info->length);
4123 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
4124 cache_info->type=DiskCache;
4127 status=AcquireMagickResource(MapResource,cache_info->length);
4128 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4129 (cache_info->type != MemoryCache))
4130 cache_info->type=DiskCache;
4133 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4134 cache_info->offset,(size_t) cache_info->length);
4135 if (cache_info->pixels == (Quantum *) NULL)
4137 cache_info->type=DiskCache;
4138 cache_info->pixels=source_info.pixels;
4143 Create file-backed memory-mapped pixel cache.
4146 (void) ClosePixelCacheOnDisk(cache_info);
4147 cache_info->type=MapCache;
4148 cache_info->mapped=MagickTrue;
4149 cache_info->metacontent=(void *) NULL;
4150 if (cache_info->metacontent_extent != 0)
4151 cache_info->metacontent=(void *) (cache_info->pixels+
4152 number_pixels*cache_info->number_channels);
4153 if (source_info.storage_class != UndefinedClass)
4155 status=ClonePixelCachePixels(cache_info,&source_info,
4157 RelinquishPixelCachePixels(&source_info);
4159 if (image->debug != MagickFalse)
4161 (void) FormatMagickSize(cache_info->length,MagickTrue,
4163 (void) FormatLocaleString(message,MaxTextExtent,
4164 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4165 cache_info->filename,cache_info->cache_filename,
4166 cache_info->file,(double) cache_info->columns,(double)
4167 cache_info->rows,(double) cache_info->number_channels,
4169 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4175 RelinquishMagickResource(MapResource,cache_info->length);
4178 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4180 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4181 RelinquishPixelCachePixels(&source_info);
4183 if (image->debug != MagickFalse)
4185 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4186 (void) FormatLocaleString(message,MaxTextExtent,
4187 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4188 cache_info->cache_filename,cache_info->file,(double)
4189 cache_info->columns,(double) cache_info->rows,(double)
4190 cache_info->number_channels,format);
4191 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4201 + P e r s i s t P i x e l C a c h e %
4205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4207 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4208 % persistent pixel cache is one that resides on disk and is not destroyed
4209 % when the program exits.
4211 % The format of the PersistPixelCache() method is:
4213 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4214 % const MagickBooleanType attach,MagickOffsetType *offset,
4215 % ExceptionInfo *exception)
4217 % A description of each parameter follows:
4219 % o image: the image.
4221 % o filename: the persistent pixel cache filename.
4223 % o attach: A value other than zero initializes the persistent pixel cache.
4225 % o initialize: A value other than zero initializes the persistent pixel
4228 % o offset: the offset in the persistent cache to store pixels.
4230 % o exception: return any errors or warnings in this structure.
4233 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4234 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4235 ExceptionInfo *exception)
4250 assert(image != (Image *) NULL);
4251 assert(image->signature == MagickSignature);
4252 if (image->debug != MagickFalse)
4253 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4254 assert(image->cache != (void *) NULL);
4255 assert(filename != (const char *) NULL);
4256 assert(offset != (MagickOffsetType *) NULL);
4257 page_size=GetMagickPageSize();
4258 cache_info=(CacheInfo *) image->cache;
4259 assert(cache_info->signature == MagickSignature);
4260 if (attach != MagickFalse)
4263 Attach existing persistent pixel cache.
4265 if (image->debug != MagickFalse)
4266 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4267 "attach persistent cache");
4268 (void) CopyMagickString(cache_info->cache_filename,filename,
4270 cache_info->type=DiskCache;
4271 cache_info->offset=(*offset);
4272 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4273 return(MagickFalse);
4274 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4277 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4278 (cache_info->reference_count == 1))
4280 LockSemaphoreInfo(cache_info->semaphore);
4281 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4282 (cache_info->reference_count == 1))
4288 Usurp existing persistent pixel cache.
4290 status=rename(cache_info->cache_filename,filename);
4293 (void) CopyMagickString(cache_info->cache_filename,filename,
4295 *offset+=cache_info->length+page_size-(cache_info->length %
4297 UnlockSemaphoreInfo(cache_info->semaphore);
4298 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4299 if (image->debug != MagickFalse)
4300 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4301 "Usurp resident persistent cache");
4305 UnlockSemaphoreInfo(cache_info->semaphore);
4308 Clone persistent pixel cache.
4310 clone_image=(*image);
4311 clone_info=(CacheInfo *) clone_image.cache;
4312 image->cache=ClonePixelCache(cache_info);
4313 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4314 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4315 cache_info->type=DiskCache;
4316 cache_info->offset=(*offset);
4317 cache_info=(CacheInfo *) image->cache;
4318 status=OpenPixelCache(image,IOMode,exception);
4319 if (status != MagickFalse)
4320 status=ClonePixelCachePixels(cache_info,clone_info,&image->exception);
4321 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4322 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4331 + Q u e u e A u t h e n t i c N e x u s %
4335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4337 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4338 % by the region rectangle and returns a pointer to the region. This region is
4339 % subsequently transferred from the pixel cache with
4340 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4341 % pixels are transferred, otherwise a NULL is returned.
4343 % The format of the QueueAuthenticNexus() method is:
4345 % Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4346 % const ssize_t y,const size_t columns,const size_t rows,
4347 % NexusInfo *nexus_info,ExceptionInfo *exception)
4349 % A description of each parameter follows:
4351 % o image: the image.
4353 % o x,y,columns,rows: These values define the perimeter of a region of
4356 % o nexus_info: the cache nexus to set.
4358 % o exception: return any errors or warnings in this structure.
4361 MagickPrivate Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4362 const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
4363 ExceptionInfo *exception)
4378 Validate pixel cache geometry.
4380 assert(image != (const Image *) NULL);
4381 assert(image->signature == MagickSignature);
4382 assert(image->cache != (Cache) NULL);
4383 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
4384 if (cache_info == (Cache) NULL)
4385 return((Quantum *) NULL);
4386 assert(cache_info->signature == MagickSignature);
4387 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4389 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4390 "NoPixelsDefinedInCache","`%s'",image->filename);
4391 return((Quantum *) NULL);
4393 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4394 (y >= (ssize_t) cache_info->rows))
4396 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4397 "PixelsAreNotAuthentic","`%s'",image->filename);
4398 return((Quantum *) NULL);
4400 offset=(MagickOffsetType) y*cache_info->columns+x;
4402 return((Quantum *) NULL);
4403 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4404 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4405 if ((MagickSizeType) offset >= number_pixels)
4406 return((Quantum *) NULL);
4412 region.width=columns;
4414 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4422 + 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 %
4426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4428 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4429 % defined by the region rectangle and returns a pointer to the region. This
4430 % region is subsequently transferred from the pixel cache with
4431 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4432 % pixels are transferred, otherwise a NULL is returned.
4434 % The format of the QueueAuthenticPixelsCache() method is:
4436 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4437 % const ssize_t y,const size_t columns,const size_t rows,
4438 % ExceptionInfo *exception)
4440 % A description of each parameter follows:
4442 % o image: the image.
4444 % o x,y,columns,rows: These values define the perimeter of a region of
4447 % o exception: return any errors or warnings in this structure.
4450 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4451 const ssize_t y,const size_t columns,const size_t rows,
4452 ExceptionInfo *exception)
4458 id = GetOpenMPThreadId();
4463 assert(image != (const Image *) NULL);
4464 assert(image->signature == MagickSignature);
4465 assert(image->cache != (Cache) NULL);
4466 cache_info=(CacheInfo *) image->cache;
4467 assert(cache_info->signature == MagickSignature);
4468 assert(id < (int) cache_info->number_threads);
4469 q=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4475 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4479 % Q u e u e A u t h e n t i c P i x e l s %
4483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4485 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4486 % successfully initialized a pointer to a Quantum array representing the
4487 % region is returned, otherwise NULL is returned. The returned pointer may
4488 % point to a temporary working buffer for the pixels or it may point to the
4489 % final location of the pixels in memory.
4491 % Write-only access means that any existing pixel values corresponding to
4492 % the region are ignored. This is useful if the initial image is being
4493 % created from scratch, or if the existing pixel values are to be
4494 % completely replaced without need to refer to their pre-existing values.
4495 % The application is free to read and write the pixel buffer returned by
4496 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4497 % initialize the pixel array values. Initializing pixel array values is the
4498 % application's responsibility.
4500 % Performance is maximized if the selected region is part of one row, or
4501 % one or more full rows, since then there is opportunity to access the
4502 % pixels in-place (without a copy) if the image is in memory, or in a
4503 % memory-mapped file. The returned pointer must *never* be deallocated
4506 % Pixels accessed via the returned pointer represent a simple array of type
4507 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4508 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4509 % obtain the meta-content (of type void) corresponding to the region.
4510 % Once the Quantum (and/or Quantum) array has been updated, the
4511 % changes must be saved back to the underlying image using
4512 % SyncAuthenticPixels() or they may be lost.
4514 % The format of the QueueAuthenticPixels() method is:
4516 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4517 % const ssize_t y,const size_t columns,const size_t rows,
4518 % ExceptionInfo *exception)
4520 % A description of each parameter follows:
4522 % o image: the image.
4524 % o x,y,columns,rows: These values define the perimeter of a region of
4527 % o exception: return any errors or warnings in this structure.
4530 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4531 const ssize_t y,const size_t columns,const size_t rows,
4532 ExceptionInfo *exception)
4538 id = GetOpenMPThreadId();
4543 assert(image != (Image *) NULL);
4544 assert(image->signature == MagickSignature);
4545 assert(image->cache != (Cache) NULL);
4546 cache_info=(CacheInfo *) image->cache;
4547 assert(cache_info->signature == MagickSignature);
4548 if (cache_info->methods.queue_authentic_pixels_handler !=
4549 (QueueAuthenticPixelsHandler) NULL)
4551 q=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4552 columns,rows,exception);
4555 assert(id < (int) cache_info->number_threads);
4556 q=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4566 + 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 %
4570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4572 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4575 % The format of the ReadPixelCacheMetacontent() method is:
4577 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4578 % NexusInfo *nexus_info,ExceptionInfo *exception)
4580 % A description of each parameter follows:
4582 % o cache_info: the pixel cache.
4584 % o nexus_info: the cache nexus to read the metacontent.
4586 % o exception: return any errors or warnings in this structure.
4589 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4590 NexusInfo *nexus_info,ExceptionInfo *exception)
4603 register unsigned char
4609 if (cache_info->metacontent_extent == 0)
4610 return(MagickFalse);
4611 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4613 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4614 nexus_info->region.x;
4615 length=(MagickSizeType) nexus_info->region.width*
4616 cache_info->metacontent_extent;
4617 rows=nexus_info->region.height;
4619 q=(unsigned char *) nexus_info->metacontent;
4620 switch (cache_info->type)
4625 register unsigned char
4629 Read meta-content from memory.
4631 if ((cache_info->columns == nexus_info->region.width) &&
4632 (extent == (MagickSizeType) ((size_t) extent)))
4637 p=(unsigned char *) cache_info->metacontent+offset*
4638 cache_info->metacontent_extent;
4639 for (y=0; y < (ssize_t) rows; y++)
4641 (void) memcpy(q,p,(size_t) length);
4642 p+=cache_info->metacontent_extent*cache_info->columns;
4643 q+=cache_info->metacontent_extent*nexus_info->region.width;
4650 Read meta content from disk.
4652 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4654 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4655 cache_info->cache_filename);
4656 return(MagickFalse);
4658 if ((cache_info->columns == nexus_info->region.width) &&
4659 (extent <= MagickMaxBufferExtent))
4664 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4665 for (y=0; y < (ssize_t) rows; y++)
4667 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4668 cache_info->number_channels*sizeof(Quantum)+offset*
4669 cache_info->metacontent_extent,length,(unsigned char *) q);
4670 if ((MagickSizeType) count != length)
4672 offset+=cache_info->columns;
4673 q+=cache_info->metacontent_extent*nexus_info->region.width;
4675 if (y < (ssize_t) rows)
4677 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4678 cache_info->cache_filename);
4679 return(MagickFalse);
4686 if ((cache_info->debug != MagickFalse) &&
4687 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4688 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4689 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4690 nexus_info->region.width,(double) nexus_info->region.height,(double)
4691 nexus_info->region.x,(double) nexus_info->region.y);
4696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4700 + R e a d P i x e l C a c h e P i x e l s %
4704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4706 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4709 % The format of the ReadPixelCachePixels() method is:
4711 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4712 % NexusInfo *nexus_info,ExceptionInfo *exception)
4714 % A description of each parameter follows:
4716 % o cache_info: the pixel cache.
4718 % o nexus_info: the cache nexus to read the pixels.
4720 % o exception: return any errors or warnings in this structure.
4723 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4724 NexusInfo *nexus_info,ExceptionInfo *exception)
4743 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4745 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4746 nexus_info->region.x;
4747 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4749 rows=nexus_info->region.height;
4751 q=nexus_info->pixels;
4752 switch (cache_info->type)
4761 Read pixels from memory.
4763 if ((cache_info->columns == nexus_info->region.width) &&
4764 (extent == (MagickSizeType) ((size_t) extent)))
4769 p=cache_info->pixels+offset*cache_info->number_channels;
4770 for (y=0; y < (ssize_t) rows; y++)
4772 (void) memcpy(q,p,(size_t) length);
4773 p+=cache_info->number_channels*cache_info->columns;
4774 q+=cache_info->number_channels*nexus_info->region.width;
4781 Read pixels from disk.
4783 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4785 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4786 cache_info->cache_filename);
4787 return(MagickFalse);
4789 if ((cache_info->columns == nexus_info->region.width) &&
4790 (extent <= MagickMaxBufferExtent))
4795 for (y=0; y < (ssize_t) rows; y++)
4797 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4798 cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4799 if ((MagickSizeType) count != length)
4801 offset+=cache_info->columns;
4802 q+=cache_info->number_channels*nexus_info->region.width;
4804 if (y < (ssize_t) rows)
4806 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4807 cache_info->cache_filename);
4808 return(MagickFalse);
4815 if ((cache_info->debug != MagickFalse) &&
4816 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4817 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4818 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4819 nexus_info->region.width,(double) nexus_info->region.height,(double)
4820 nexus_info->region.x,(double) nexus_info->region.y);
4825 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4829 + R e f e r e n c e P i x e l C a c h e %
4833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4835 % ReferencePixelCache() increments the reference count associated with the
4836 % pixel cache returning a pointer to the cache.
4838 % The format of the ReferencePixelCache method is:
4840 % Cache ReferencePixelCache(Cache cache_info)
4842 % A description of each parameter follows:
4844 % o cache_info: the pixel cache.
4847 MagickPrivate Cache ReferencePixelCache(Cache cache)
4852 assert(cache != (Cache *) NULL);
4853 cache_info=(CacheInfo *) cache;
4854 assert(cache_info->signature == MagickSignature);
4855 LockSemaphoreInfo(cache_info->semaphore);
4856 cache_info->reference_count++;
4857 UnlockSemaphoreInfo(cache_info->semaphore);
4862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4866 + S e t P i x e l C a c h e M e t h o d s %
4870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4872 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4874 % The format of the SetPixelCacheMethods() method is:
4876 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4878 % A description of each parameter follows:
4880 % o cache: the pixel cache.
4882 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4885 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4890 GetOneAuthenticPixelFromHandler
4891 get_one_authentic_pixel_from_handler;
4893 GetOneVirtualPixelFromHandler
4894 get_one_virtual_pixel_from_handler;
4897 Set cache pixel methods.
4899 assert(cache != (Cache) NULL);
4900 assert(cache_methods != (CacheMethods *) NULL);
4901 cache_info=(CacheInfo *) cache;
4902 assert(cache_info->signature == MagickSignature);
4903 if (cache_info->debug != MagickFalse)
4904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4905 cache_info->filename);
4906 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4907 cache_info->methods.get_virtual_pixel_handler=
4908 cache_methods->get_virtual_pixel_handler;
4909 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4910 cache_info->methods.destroy_pixel_handler=
4911 cache_methods->destroy_pixel_handler;
4912 if (cache_methods->get_virtual_metacontent_from_handler !=
4913 (GetVirtualMetacontentFromHandler) NULL)
4914 cache_info->methods.get_virtual_metacontent_from_handler=
4915 cache_methods->get_virtual_metacontent_from_handler;
4916 if (cache_methods->get_authentic_pixels_handler !=
4917 (GetAuthenticPixelsHandler) NULL)
4918 cache_info->methods.get_authentic_pixels_handler=
4919 cache_methods->get_authentic_pixels_handler;
4920 if (cache_methods->queue_authentic_pixels_handler !=
4921 (QueueAuthenticPixelsHandler) NULL)
4922 cache_info->methods.queue_authentic_pixels_handler=
4923 cache_methods->queue_authentic_pixels_handler;
4924 if (cache_methods->sync_authentic_pixels_handler !=
4925 (SyncAuthenticPixelsHandler) NULL)
4926 cache_info->methods.sync_authentic_pixels_handler=
4927 cache_methods->sync_authentic_pixels_handler;
4928 if (cache_methods->get_authentic_pixels_from_handler !=
4929 (GetAuthenticPixelsFromHandler) NULL)
4930 cache_info->methods.get_authentic_pixels_from_handler=
4931 cache_methods->get_authentic_pixels_from_handler;
4932 if (cache_methods->get_authentic_metacontent_from_handler !=
4933 (GetAuthenticMetacontentFromHandler) NULL)
4934 cache_info->methods.get_authentic_metacontent_from_handler=
4935 cache_methods->get_authentic_metacontent_from_handler;
4936 get_one_virtual_pixel_from_handler=
4937 cache_info->methods.get_one_virtual_pixel_from_handler;
4938 if (get_one_virtual_pixel_from_handler !=
4939 (GetOneVirtualPixelFromHandler) NULL)
4940 cache_info->methods.get_one_virtual_pixel_from_handler=
4941 cache_methods->get_one_virtual_pixel_from_handler;
4942 get_one_authentic_pixel_from_handler=
4943 cache_methods->get_one_authentic_pixel_from_handler;
4944 if (get_one_authentic_pixel_from_handler !=
4945 (GetOneAuthenticPixelFromHandler) NULL)
4946 cache_info->methods.get_one_authentic_pixel_from_handler=
4947 cache_methods->get_one_authentic_pixel_from_handler;
4951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4955 + S e t P i x e l C a c h e N e x u s P i x e l s %
4959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4961 % SetPixelCacheNexusPixels() defines the region of the cache for the
4962 % specified cache nexus.
4964 % The format of the SetPixelCacheNexusPixels() method is:
4966 % Quantum SetPixelCacheNexusPixels(const Image *image,
4967 % const RectangleInfo *region,NexusInfo *nexus_info,
4968 % ExceptionInfo *exception)
4970 % A description of each parameter follows:
4972 % o image: the image.
4974 % o region: A pointer to the RectangleInfo structure that defines the
4975 % region of this particular cache nexus.
4977 % o nexus_info: the cache nexus to set.
4979 % o exception: return any errors or warnings in this structure.
4983 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
4984 NexusInfo *nexus_info,ExceptionInfo *exception)
4986 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4987 return(MagickFalse);
4988 nexus_info->mapped=MagickFalse;
4989 nexus_info->cache=(Quantum *) AcquireAlignedMemory(1,(size_t)
4990 nexus_info->length);
4991 if (nexus_info->cache == (Quantum *) NULL)
4993 nexus_info->mapped=MagickTrue;
4994 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4995 nexus_info->length);
4997 if (nexus_info->cache == (Quantum *) NULL)
4999 (void) ThrowMagickException(exception,GetMagickModule(),
5000 ResourceLimitError,"MemoryAllocationFailed","`%s'",
5001 cache_info->filename);
5002 return(MagickFalse);
5007 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5008 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5020 cache_info=(CacheInfo *) image->cache;
5021 assert(cache_info->signature == MagickSignature);
5022 if (cache_info->type == UndefinedCache)
5023 return((Quantum *) NULL);
5024 nexus_info->region=(*region);
5025 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5026 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5032 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5033 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5034 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5035 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5036 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5037 ((nexus_info->region.width == cache_info->columns) ||
5038 ((nexus_info->region.width % cache_info->columns) == 0)))))
5044 Pixels are accessed directly from memory.
5046 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5047 nexus_info->region.x;
5048 nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5050 nexus_info->metacontent=(void *) NULL;
5051 if (cache_info->metacontent_extent != 0)
5052 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5053 offset*cache_info->metacontent_extent;
5054 return(nexus_info->pixels);
5058 Pixels are stored in a cache region until they are synced to the cache.
5060 number_pixels=(MagickSizeType) nexus_info->region.width*
5061 nexus_info->region.height;
5062 length=number_pixels*cache_info->number_channels*sizeof(Quantum);
5063 if (cache_info->metacontent_extent != 0)
5064 length+=number_pixels*cache_info->metacontent_extent;
5065 if (nexus_info->cache == (Quantum *) NULL)
5067 nexus_info->length=length;
5068 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5069 if (status == MagickFalse)
5071 nexus_info->length=0;
5072 return((Quantum *) NULL);
5076 if (nexus_info->length != length)
5078 RelinquishCacheNexusPixels(nexus_info);
5079 nexus_info->length=length;
5080 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5081 if (status == MagickFalse)
5083 nexus_info->length=0;
5084 return((Quantum *) NULL);
5087 nexus_info->pixels=nexus_info->cache;
5088 nexus_info->metacontent=(void *) NULL;
5089 if (cache_info->metacontent_extent != 0)
5090 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5091 cache_info->number_channels);
5092 return(nexus_info->pixels);
5096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5100 % 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 %
5104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5106 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5107 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5108 % access that is outside the boundaries of the image cache.
5110 % The format of the SetPixelCacheVirtualMethod() method is:
5112 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5113 % const VirtualPixelMethod virtual_pixel_method)
5115 % A description of each parameter follows:
5117 % o image: the image.
5119 % o virtual_pixel_method: choose the type of virtual pixel.
5122 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5123 const VirtualPixelMethod virtual_pixel_method)
5131 assert(image != (Image *) NULL);
5132 assert(image->signature == MagickSignature);
5133 if (image->debug != MagickFalse)
5134 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5135 assert(image->cache != (Cache) NULL);
5136 cache_info=(CacheInfo *) image->cache;
5137 assert(cache_info->signature == MagickSignature);
5138 method=cache_info->virtual_pixel_method;
5139 cache_info->virtual_pixel_method=virtual_pixel_method;
5144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5148 + 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 %
5152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5154 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5155 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5156 % is synced, otherwise MagickFalse.
5158 % The format of the SyncAuthenticPixelCacheNexus() method is:
5160 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5161 % NexusInfo *nexus_info,ExceptionInfo *exception)
5163 % A description of each parameter follows:
5165 % o image: the image.
5167 % o nexus_info: the cache nexus to sync.
5169 % o exception: return any errors or warnings in this structure.
5172 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5173 NexusInfo *nexus_info,ExceptionInfo *exception)
5182 Transfer pixels to the cache.
5184 assert(image != (Image *) NULL);
5185 assert(image->signature == MagickSignature);
5186 if (image->cache == (Cache) NULL)
5187 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5188 cache_info=(CacheInfo *) image->cache;
5189 assert(cache_info->signature == MagickSignature);
5190 if (cache_info->type == UndefinedCache)
5191 return(MagickFalse);
5192 if ((image->clip_mask != (Image *) NULL) &&
5193 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5194 return(MagickFalse);
5195 if ((image->mask != (Image *) NULL) &&
5196 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5197 return(MagickFalse);
5198 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5200 assert(cache_info->signature == MagickSignature);
5201 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5202 if ((cache_info->metacontent_extent != 0) &&
5203 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5204 return(MagickFalse);
5209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5213 + S y n c A u t h e n t i c P i x e l C a c h e %
5217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5219 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5220 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5221 % otherwise MagickFalse.
5223 % The format of the SyncAuthenticPixelsCache() method is:
5225 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5226 % ExceptionInfo *exception)
5228 % A description of each parameter follows:
5230 % o image: the image.
5232 % o exception: return any errors or warnings in this structure.
5235 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5236 ExceptionInfo *exception)
5242 id = GetOpenMPThreadId();
5247 assert(image != (Image *) NULL);
5248 assert(image->signature == MagickSignature);
5249 assert(image->cache != (Cache) NULL);
5250 cache_info=(CacheInfo *) image->cache;
5251 assert(cache_info->signature == MagickSignature);
5252 assert(id < (int) cache_info->number_threads);
5253 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5263 % S y n c A u t h e n t i c P i x e l s %
5267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5269 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5270 % The method returns MagickTrue if the pixel region is flushed, otherwise
5273 % The format of the SyncAuthenticPixels() method is:
5275 % MagickBooleanType SyncAuthenticPixels(Image *image,
5276 % ExceptionInfo *exception)
5278 % A description of each parameter follows:
5280 % o image: the image.
5282 % o exception: return any errors or warnings in this structure.
5285 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5286 ExceptionInfo *exception)
5292 id = GetOpenMPThreadId();
5297 assert(image != (Image *) NULL);
5298 assert(image->signature == MagickSignature);
5299 assert(image->cache != (Cache) NULL);
5300 cache_info=(CacheInfo *) image->cache;
5301 assert(cache_info->signature == MagickSignature);
5302 if (cache_info->methods.sync_authentic_pixels_handler !=
5303 (SyncAuthenticPixelsHandler) NULL)
5305 status=cache_info->methods.sync_authentic_pixels_handler(image,
5309 assert(id < (int) cache_info->number_threads);
5310 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5320 + S y n c I m a g e P i x e l C a c h e %
5324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5326 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5327 % The method returns MagickTrue if the pixel region is flushed, otherwise
5330 % The format of the SyncImagePixelCache() method is:
5332 % MagickBooleanType SyncImagePixelCache(Image *image,
5333 % ExceptionInfo *exception)
5335 % A description of each parameter follows:
5337 % o image: the image.
5339 % o exception: return any errors or warnings in this structure.
5342 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5343 ExceptionInfo *exception)
5348 assert(image != (Image *) NULL);
5349 assert(exception != (ExceptionInfo *) NULL);
5350 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5351 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5359 + 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 %
5363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5365 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5366 % of the pixel cache.
5368 % The format of the WritePixelCacheMetacontent() method is:
5370 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5371 % NexusInfo *nexus_info,ExceptionInfo *exception)
5373 % A description of each parameter follows:
5375 % o cache_info: the pixel cache.
5377 % o nexus_info: the cache nexus to write the meta-content.
5379 % o exception: return any errors or warnings in this structure.
5382 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5383 NexusInfo *nexus_info,ExceptionInfo *exception)
5393 register const unsigned char
5402 if (cache_info->metacontent_extent == 0)
5403 return(MagickFalse);
5404 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5406 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5407 nexus_info->region.x;
5408 length=(MagickSizeType) nexus_info->region.width*
5409 cache_info->metacontent_extent;
5410 rows=nexus_info->region.height;
5411 extent=(MagickSizeType) length*rows;
5412 p=(unsigned char *) nexus_info->metacontent;
5413 switch (cache_info->type)
5418 register unsigned char
5422 Write associated pixels to memory.
5424 if ((cache_info->columns == nexus_info->region.width) &&
5425 (extent == (MagickSizeType) ((size_t) extent)))
5430 q=(unsigned char *) cache_info->metacontent+offset*
5431 cache_info->metacontent_extent;
5432 for (y=0; y < (ssize_t) rows; y++)
5434 (void) memcpy(q,p,(size_t) length);
5435 p+=nexus_info->region.width*cache_info->metacontent_extent;
5436 q+=cache_info->columns*cache_info->metacontent_extent;
5443 Write associated pixels to disk.
5445 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5447 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5448 cache_info->cache_filename);
5449 return(MagickFalse);
5451 if ((cache_info->columns == nexus_info->region.width) &&
5452 (extent <= MagickMaxBufferExtent))
5457 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5458 for (y=0; y < (ssize_t) rows; y++)
5460 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5461 cache_info->number_channels*sizeof(Quantum)+offset*
5462 cache_info->metacontent_extent,length,(const unsigned char *) p);
5463 if ((MagickSizeType) count != length)
5465 p+=nexus_info->region.width*cache_info->metacontent_extent;
5466 offset+=cache_info->columns;
5468 if (y < (ssize_t) rows)
5470 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5471 cache_info->cache_filename);
5472 return(MagickFalse);
5479 if ((cache_info->debug != MagickFalse) &&
5480 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5481 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5482 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5483 nexus_info->region.width,(double) nexus_info->region.height,(double)
5484 nexus_info->region.x,(double) nexus_info->region.y);
5489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5493 + W r i t e C a c h e P i x e l s %
5497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5499 % WritePixelCachePixels() writes image pixels to the specified region of the
5502 % The format of the WritePixelCachePixels() method is:
5504 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5505 % NexusInfo *nexus_info,ExceptionInfo *exception)
5507 % A description of each parameter follows:
5509 % o cache_info: the pixel cache.
5511 % o nexus_info: the cache nexus to write the pixels.
5513 % o exception: return any errors or warnings in this structure.
5516 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5517 NexusInfo *nexus_info,ExceptionInfo *exception)
5527 register const Quantum
5536 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5538 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5539 nexus_info->region.x;
5540 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5542 rows=nexus_info->region.height;
5544 p=nexus_info->pixels;
5545 switch (cache_info->type)
5554 Write pixels to memory.
5556 if ((cache_info->columns == nexus_info->region.width) &&
5557 (extent == (MagickSizeType) ((size_t) extent)))
5562 q=cache_info->pixels+offset*cache_info->number_channels;
5563 for (y=0; y < (ssize_t) rows; y++)
5565 (void) memcpy(q,p,(size_t) length);
5566 p+=nexus_info->region.width*cache_info->number_channels;
5567 q+=cache_info->columns*cache_info->number_channels;
5574 Write pixels to disk.
5576 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5578 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5579 cache_info->cache_filename);
5580 return(MagickFalse);
5582 if ((cache_info->columns == nexus_info->region.width) &&
5583 (extent <= MagickMaxBufferExtent))
5588 for (y=0; y < (ssize_t) rows; y++)
5590 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5591 cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5593 if ((MagickSizeType) count != length)
5595 p+=nexus_info->region.width*cache_info->number_channels;
5596 offset+=cache_info->columns;
5598 if (y < (ssize_t) rows)
5600 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5601 cache_info->cache_filename);
5602 return(MagickFalse);
5609 if ((cache_info->debug != MagickFalse) &&
5610 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5611 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5612 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5613 nexus_info->region.width,(double) nexus_info->region.height,(double)
5614 nexus_info->region.x,(double) nexus_info->region.y);