2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % CCCC AAA CCCC H H EEEEE %
8 % C AAAAA C HHHHH EEE %
10 % CCCC A A CCCC H H EEEEE %
13 % MagickCore Pixel Cache Methods %
20 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/composite-private.h"
50 #include "MagickCore/exception.h"
51 #include "MagickCore/exception-private.h"
52 #include "MagickCore/geometry.h"
53 #include "MagickCore/list.h"
54 #include "MagickCore/log.h"
55 #include "MagickCore/magick.h"
56 #include "MagickCore/memory_.h"
57 #include "MagickCore/pixel.h"
58 #include "MagickCore/pixel-accessor.h"
59 #include "MagickCore/policy.h"
60 #include "MagickCore/quantum.h"
61 #include "MagickCore/random_.h"
62 #include "MagickCore/resource_.h"
63 #include "MagickCore/semaphore.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/string-private.h"
67 #include "MagickCore/thread-private.h"
68 #include "MagickCore/utility.h"
69 #include "MagickCore/utility-private.h"
70 #if defined(MAGICKCORE_ZLIB_DELEGATE)
77 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
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 Quantum *,ExceptionInfo *),
129 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
130 const ssize_t,const ssize_t,Quantum *,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 *) AcquireQuantumMemory(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 **) AcquireQuantumMemory(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 != 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_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
650 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
651 O_BINARY | O_EXCL,S_MODE);
653 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
659 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
662 file=open_utf8(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 *) AcquireQuantumMemory(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 *) AcquireQuantumMemory(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 ((cache_info->type != MemoryCache) && (clone_info->type != MemoryCache) &&
975 (strcmp(cache_info->cache_filename,clone_info->cache_filename) == 0))
978 Inplace cloning not reliable.
980 (void) ClosePixelCacheOnDisk(clone_info);
981 if (cache_info->type == MapCache)
983 clone_info->pixels=(Quantum *) UnmapBlob(clone_info->pixels,(size_t)
985 RelinquishMagickResource(MapResource,clone_info->length);
987 *clone_info->cache_filename='\0';
988 clone_info->type=DiskCache;
990 if (clone_info->type == DiskCache)
992 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
994 if (cache_info->type == DiskCache)
995 (void) ClosePixelCacheOnDisk(cache_info);
996 blob=(unsigned char *) RelinquishMagickMemory(blob);
997 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
998 clone_info->cache_filename);
1001 clone_offset=clone_info->offset;
1004 Clone pixel channels.
1007 for (y=0; y < (ssize_t) cache_info->rows; y++)
1009 for (x=0; x < (ssize_t) cache_info->columns; x++)
1015 Read a set of pixel channels.
1017 length=cache_info->number_channels*sizeof(Quantum);
1018 if (cache_info->type != DiskCache)
1019 (void) memcpy(blob,(unsigned char *) cache_info->pixels+cache_offset,
1023 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1024 if ((MagickSizeType) count != length)
1030 cache_offset+=length;
1031 if ((y < (ssize_t) clone_info->rows) &&
1032 (x < (ssize_t) clone_info->columns))
1033 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
1045 Write a set of pixel channels.
1047 channel=clone_info->channel_map[i].channel;
1048 traits=cache_info->channel_map[channel].traits;
1049 if (traits == UndefinedPixelTrait)
1051 clone_offset+=sizeof(Quantum);
1054 offset=cache_info->channel_map[channel].offset;
1055 if (clone_info->type != DiskCache)
1056 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1057 blob+offset*sizeof(Quantum),sizeof(Quantum));
1060 count=WritePixelCacheRegion(clone_info,clone_offset,
1061 sizeof(Quantum),blob+offset*sizeof(Quantum));
1062 if ((MagickSizeType) count != sizeof(Quantum))
1068 clone_offset+=sizeof(Quantum);
1071 length=clone_info->number_channels*sizeof(Quantum);
1072 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1073 for ( ; x < (ssize_t) clone_info->columns; x++)
1076 Set remaining columns as undefined.
1078 if (clone_info->type != DiskCache)
1079 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1083 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1084 if ((MagickSizeType) count != length)
1090 clone_offset+=length;
1093 length=clone_info->number_channels*sizeof(Quantum);
1094 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1095 for ( ; y < (ssize_t) clone_info->rows; y++)
1098 Set remaining rows as undefined.
1100 for (x=0; x < (ssize_t) clone_info->columns; x++)
1102 if (clone_info->type != DiskCache)
1103 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1107 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1108 if ((MagickSizeType) count != length)
1114 clone_offset+=length;
1117 if ((cache_info->metacontent_extent != 0) ||
1118 (clone_info->metacontent_extent != 0))
1123 for (y=0; y < (ssize_t) cache_info->rows; y++)
1125 for (x=0; x < (ssize_t) cache_info->columns; x++)
1128 Read a set of metacontent.
1130 length=cache_info->metacontent_extent;
1131 if (cache_info->type != DiskCache)
1132 (void) memcpy(blob,(unsigned char *) cache_info->pixels+
1133 cache_offset,length);
1136 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1137 if ((MagickSizeType) count != length)
1143 cache_offset+=length;
1144 if ((y < (ssize_t) clone_info->rows) &&
1145 (x < (ssize_t) clone_info->columns))
1148 Write a set of metacontent.
1150 length=clone_info->metacontent_extent;
1151 if (clone_info->type != DiskCache)
1152 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1156 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1158 if ((MagickSizeType) count != length)
1164 clone_offset+=length;
1167 length=clone_info->metacontent_extent;
1168 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1169 for ( ; x < (ssize_t) clone_info->columns; x++)
1172 Set remaining columns as undefined.
1174 if (clone_info->type != DiskCache)
1175 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1179 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1180 if ((MagickSizeType) count != length)
1186 clone_offset+=length;
1189 length=clone_info->metacontent_extent;
1190 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1191 for ( ; y < (ssize_t) clone_info->rows; y++)
1194 Set remaining rows as undefined.
1196 for (x=0; x < (ssize_t) clone_info->columns; x++)
1198 if (clone_info->type != DiskCache)
1199 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1203 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1204 if ((MagickSizeType) count != length)
1210 clone_offset+=length;
1214 if (clone_info->type == DiskCache)
1215 (void) ClosePixelCacheOnDisk(clone_info);
1216 if (cache_info->type == DiskCache)
1217 (void) ClosePixelCacheOnDisk(cache_info);
1218 blob=(unsigned char *) RelinquishMagickMemory(blob);
1222 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1223 CacheInfo *cache_info,ExceptionInfo *exception)
1229 if (cache_info->type == PingCache)
1231 p=cache_info->channel_map;
1232 q=clone_info->channel_map;
1233 if ((cache_info->columns == clone_info->columns) &&
1234 (cache_info->rows == clone_info->rows) &&
1235 (cache_info->number_channels == clone_info->number_channels) &&
1236 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) &&
1237 (cache_info->metacontent_extent == clone_info->metacontent_extent))
1238 return(OptimizedPixelCacheClone(clone_info,cache_info,exception));
1239 return(UnoptimizedPixelCacheClone(clone_info,cache_info,exception));
1243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1247 + C l o n e P i x e l C a c h e M e t h o d s %
1251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1253 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1256 % The format of the ClonePixelCacheMethods() method is:
1258 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
1260 % A description of each parameter follows:
1262 % o clone: Specifies a pointer to a Cache structure.
1264 % o cache: the pixel cache.
1267 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
1273 assert(clone != (Cache) NULL);
1274 source_info=(CacheInfo *) clone;
1275 assert(source_info->signature == MagickSignature);
1276 if (source_info->debug != MagickFalse)
1277 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1278 source_info->filename);
1279 assert(cache != (Cache) NULL);
1280 cache_info=(CacheInfo *) cache;
1281 assert(cache_info->signature == MagickSignature);
1282 source_info->methods=cache_info->methods;
1286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1290 + D e s t r o y I m a g e P i x e l C a c h e %
1294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1296 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1298 % The format of the DestroyImagePixelCache() method is:
1300 % void DestroyImagePixelCache(Image *image)
1302 % A description of each parameter follows:
1304 % o image: the image.
1307 static void DestroyImagePixelCache(Image *image)
1309 assert(image != (Image *) NULL);
1310 assert(image->signature == MagickSignature);
1311 if (image->debug != MagickFalse)
1312 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1313 if (image->cache == (void *) NULL)
1315 image->cache=DestroyPixelCache(image->cache);
1319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1323 + D e s t r o y I m a g e P i x e l s %
1327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1329 % DestroyImagePixels() deallocates memory associated with the pixel cache.
1331 % The format of the DestroyImagePixels() method is:
1333 % void DestroyImagePixels(Image *image)
1335 % A description of each parameter follows:
1337 % o image: the image.
1340 MagickExport void DestroyImagePixels(Image *image)
1345 assert(image != (const Image *) NULL);
1346 assert(image->signature == MagickSignature);
1347 if (image->debug != MagickFalse)
1348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1349 assert(image->cache != (Cache) NULL);
1350 cache_info=(CacheInfo *) image->cache;
1351 assert(cache_info->signature == MagickSignature);
1352 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1354 cache_info->methods.destroy_pixel_handler(image);
1357 image->cache=DestroyPixelCache(image->cache);
1361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1365 + D e s t r o y P i x e l C a c h e %
1369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1371 % DestroyPixelCache() deallocates memory associated with the pixel cache.
1373 % The format of the DestroyPixelCache() method is:
1375 % Cache DestroyPixelCache(Cache cache)
1377 % A description of each parameter follows:
1379 % o cache: the pixel cache.
1383 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1385 switch (cache_info->type)
1389 if (cache_info->mapped == MagickFalse)
1390 cache_info->pixels=(Quantum *) RelinquishMagickMemory(
1391 cache_info->pixels);
1393 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,
1394 (size_t) cache_info->length);
1395 RelinquishMagickResource(MemoryResource,cache_info->length);
1400 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t)
1401 cache_info->length);
1402 RelinquishMagickResource(MapResource,cache_info->length);
1406 if (cache_info->file != -1)
1407 (void) ClosePixelCacheOnDisk(cache_info);
1408 RelinquishMagickResource(DiskResource,cache_info->length);
1414 cache_info->type=UndefinedCache;
1415 cache_info->mapped=MagickFalse;
1416 cache_info->metacontent=(void *) NULL;
1419 MagickPrivate Cache DestroyPixelCache(Cache cache)
1424 assert(cache != (Cache) NULL);
1425 cache_info=(CacheInfo *) cache;
1426 assert(cache_info->signature == MagickSignature);
1427 if (cache_info->debug != MagickFalse)
1428 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1429 cache_info->filename);
1430 LockSemaphoreInfo(cache_info->semaphore);
1431 cache_info->reference_count--;
1432 if (cache_info->reference_count != 0)
1434 UnlockSemaphoreInfo(cache_info->semaphore);
1435 return((Cache) NULL);
1437 UnlockSemaphoreInfo(cache_info->semaphore);
1438 if (cache_resources != (SplayTreeInfo *) NULL)
1439 (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
1440 if (cache_info->debug != MagickFalse)
1443 message[MaxTextExtent];
1445 (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
1446 cache_info->filename);
1447 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1449 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1450 (cache_info->type != DiskCache)))
1451 RelinquishPixelCachePixels(cache_info);
1454 RelinquishPixelCachePixels(cache_info);
1455 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1457 *cache_info->cache_filename='\0';
1458 if (cache_info->nexus_info != (NexusInfo **) NULL)
1459 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1460 cache_info->number_threads);
1461 if (cache_info->random_info != (RandomInfo *) NULL)
1462 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1463 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1464 DestroySemaphoreInfo(&cache_info->disk_semaphore);
1465 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1466 DestroySemaphoreInfo(&cache_info->semaphore);
1467 cache_info->signature=(~MagickSignature);
1468 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
1474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1478 + D e s t r o y P i x e l C a c h e N e x u s %
1482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1484 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1486 % The format of the DestroyPixelCacheNexus() method is:
1488 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1489 % const size_t number_threads)
1491 % A description of each parameter follows:
1493 % o nexus_info: the nexus to destroy.
1495 % o number_threads: the number of nexus threads.
1499 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1501 if (nexus_info->mapped == MagickFalse)
1502 (void) RelinquishMagickMemory(nexus_info->cache);
1504 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1505 nexus_info->cache=(Quantum *) NULL;
1506 nexus_info->pixels=(Quantum *) NULL;
1507 nexus_info->metacontent=(void *) NULL;
1508 nexus_info->length=0;
1509 nexus_info->mapped=MagickFalse;
1512 MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1513 const size_t number_threads)
1518 assert(nexus_info != (NexusInfo **) NULL);
1519 for (i=0; i < (ssize_t) number_threads; i++)
1521 if (nexus_info[i]->cache != (Quantum *) NULL)
1522 RelinquishCacheNexusPixels(nexus_info[i]);
1523 nexus_info[i]->signature=(~MagickSignature);
1524 nexus_info[i]=(NexusInfo *) RelinquishAlignedMemory(nexus_info[i]);
1526 nexus_info=(NexusInfo **) RelinquishMagickMemory(nexus_info);
1531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1535 % G e t A u t h e n t i c M e t a c o n t e n t %
1539 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1541 % GetAuthenticMetacontent() returns the authentic metacontent corresponding
1542 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
1543 % returned if the associated pixels are not available.
1545 % The format of the GetAuthenticMetacontent() method is:
1547 % void *GetAuthenticMetacontent(const Image *image)
1549 % A description of each parameter follows:
1551 % o image: the image.
1554 MagickExport void *GetAuthenticMetacontent(const Image *image)
1560 id = GetOpenMPThreadId();
1565 assert(image != (const Image *) NULL);
1566 assert(image->signature == MagickSignature);
1567 assert(image->cache != (Cache) NULL);
1568 cache_info=(CacheInfo *) image->cache;
1569 assert(cache_info->signature == MagickSignature);
1570 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1571 (GetAuthenticMetacontentFromHandler) NULL)
1573 metacontent=cache_info->methods.
1574 get_authentic_metacontent_from_handler(image);
1575 return(metacontent);
1577 assert(id < (int) cache_info->number_threads);
1578 metacontent=GetPixelCacheNexusMetacontent(cache_info,
1579 cache_info->nexus_info[id]);
1580 return(metacontent);
1584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1588 + 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 %
1592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1594 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding
1595 % with the last call to QueueAuthenticPixelsCache() or
1596 % GetAuthenticPixelsCache().
1598 % The format of the GetAuthenticMetacontentFromCache() method is:
1600 % void *GetAuthenticMetacontentFromCache(const Image *image)
1602 % A description of each parameter follows:
1604 % o image: the image.
1607 static void *GetAuthenticMetacontentFromCache(const Image *image)
1613 id = GetOpenMPThreadId();
1618 assert(image != (const Image *) NULL);
1619 assert(image->signature == MagickSignature);
1620 assert(image->cache != (Cache) NULL);
1621 cache_info=(CacheInfo *) image->cache;
1622 assert(cache_info->signature == MagickSignature);
1623 assert(id < (int) cache_info->number_threads);
1624 metacontent=GetPixelCacheNexusMetacontent(image->cache,
1625 cache_info->nexus_info[id]);
1626 return(metacontent);
1630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634 + 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 %
1638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1640 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1641 % disk pixel cache as defined by the geometry parameters. A pointer to the
1642 % pixels is returned if the pixels are transferred, otherwise a NULL is
1645 % The format of the GetAuthenticPixelCacheNexus() method is:
1647 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
1648 % const ssize_t y,const size_t columns,const size_t rows,
1649 % NexusInfo *nexus_info,ExceptionInfo *exception)
1651 % A description of each parameter follows:
1653 % o image: the image.
1655 % o x,y,columns,rows: These values define the perimeter of a region of
1658 % o nexus_info: the cache nexus to return.
1660 % o exception: return any errors or warnings in this structure.
1664 static inline MagickBooleanType IsPixelAuthentic(const CacheInfo *cache_info,
1665 NexusInfo *nexus_info)
1673 if (cache_info->type == PingCache)
1675 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1676 nexus_info->region.x;
1677 status=nexus_info->pixels == (cache_info->pixels+offset*
1678 cache_info->number_channels) ? MagickTrue : MagickFalse;
1682 MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
1683 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
1684 NexusInfo *nexus_info,ExceptionInfo *exception)
1693 Transfer pixels from the cache.
1695 assert(image != (Image *) NULL);
1696 assert(image->signature == MagickSignature);
1697 q=QueueAuthenticNexus(image,x,y,columns,rows,MagickTrue,nexus_info,exception);
1698 if (q == (Quantum *) NULL)
1699 return((Quantum *) NULL);
1700 cache_info=(CacheInfo *) image->cache;
1701 assert(cache_info->signature == MagickSignature);
1702 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
1704 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1705 return((Quantum *) NULL);
1706 if (cache_info->metacontent_extent != 0)
1707 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1708 return((Quantum *) NULL);
1713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717 + 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 %
1721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1723 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1724 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1726 % The format of the GetAuthenticPixelsFromCache() method is:
1728 % Quantum *GetAuthenticPixelsFromCache(const Image image)
1730 % A description of each parameter follows:
1732 % o image: the image.
1735 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
1741 id = GetOpenMPThreadId();
1743 assert(image != (const Image *) NULL);
1744 assert(image->signature == MagickSignature);
1745 assert(image->cache != (Cache) NULL);
1746 cache_info=(CacheInfo *) image->cache;
1747 assert(cache_info->signature == MagickSignature);
1748 assert(id < (int) cache_info->number_threads);
1749 return(GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]));
1753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1757 % G e t A u t h e n t i c P i x e l Q u e u e %
1761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 % GetAuthenticPixelQueue() returns the authentic pixels associated
1764 % corresponding with the last call to QueueAuthenticPixels() or
1765 % GetAuthenticPixels().
1767 % The format of the GetAuthenticPixelQueue() method is:
1769 % Quantum *GetAuthenticPixelQueue(const Image image)
1771 % A description of each parameter follows:
1773 % o image: the image.
1776 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
1782 id = GetOpenMPThreadId();
1784 assert(image != (const Image *) NULL);
1785 assert(image->signature == MagickSignature);
1786 assert(image->cache != (Cache) NULL);
1787 cache_info=(CacheInfo *) image->cache;
1788 assert(cache_info->signature == MagickSignature);
1789 if (cache_info->methods.get_authentic_pixels_from_handler !=
1790 (GetAuthenticPixelsFromHandler) NULL)
1791 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1792 assert(id < (int) cache_info->number_threads);
1793 return(GetPixelCacheNexusPixels(cache_info,cache_info->nexus_info[id]));
1797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1801 % G e t A u t h e n t i c P i x e l s %
1804 % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1806 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1807 % region is successfully accessed, a pointer to a Quantum array
1808 % representing the region is returned, otherwise NULL is returned.
1810 % The returned pointer may point to a temporary working copy of the pixels
1811 % or it may point to the original pixels in memory. Performance is maximized
1812 % if the selected region is part of one row, or one or more full rows, since
1813 % then there is opportunity to access the pixels in-place (without a copy)
1814 % if the image is in memory, or in a memory-mapped file. The returned pointer
1815 % must *never* be deallocated by the user.
1817 % Pixels accessed via the returned pointer represent a simple array of type
1818 % Quantum. If the image has corresponding metacontent,call
1819 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
1820 % meta-content corresponding to the region. Once the Quantum array has
1821 % been updated, the changes must be saved back to the underlying image using
1822 % SyncAuthenticPixels() or they may be lost.
1824 % The format of the GetAuthenticPixels() method is:
1826 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1827 % const ssize_t y,const size_t columns,const size_t rows,
1828 % ExceptionInfo *exception)
1830 % A description of each parameter follows:
1832 % o image: the image.
1834 % o x,y,columns,rows: These values define the perimeter of a region of
1837 % o exception: return any errors or warnings in this structure.
1840 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1841 const ssize_t y,const size_t columns,const size_t rows,
1842 ExceptionInfo *exception)
1848 id = GetOpenMPThreadId();
1853 assert(image != (Image *) NULL);
1854 assert(image->signature == MagickSignature);
1855 assert(image->cache != (Cache) NULL);
1856 cache_info=(CacheInfo *) image->cache;
1857 assert(cache_info->signature == MagickSignature);
1858 if (cache_info->methods.get_authentic_pixels_handler !=
1859 (GetAuthenticPixelsHandler) NULL)
1861 q=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,rows,
1865 assert(id < (int) cache_info->number_threads);
1866 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1867 cache_info->nexus_info[id],exception);
1872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1876 + G e t A u t h e n t i c P i x e l s C a c h e %
1880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1882 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1883 % as defined by the geometry parameters. A pointer to the pixels is returned
1884 % if the pixels are transferred, otherwise a NULL is returned.
1886 % The format of the GetAuthenticPixelsCache() method is:
1888 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1889 % const ssize_t y,const size_t columns,const size_t rows,
1890 % ExceptionInfo *exception)
1892 % A description of each parameter follows:
1894 % o image: the image.
1896 % o x,y,columns,rows: These values define the perimeter of a region of
1899 % o exception: return any errors or warnings in this structure.
1902 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1903 const ssize_t y,const size_t columns,const size_t rows,
1904 ExceptionInfo *exception)
1910 id = GetOpenMPThreadId();
1915 assert(image != (const Image *) NULL);
1916 assert(image->signature == MagickSignature);
1917 assert(image->cache != (Cache) NULL);
1918 cache_info=(CacheInfo *) image->cache;
1919 if (cache_info == (Cache) NULL)
1920 return((Quantum *) NULL);
1921 assert(cache_info->signature == MagickSignature);
1922 assert(id < (int) cache_info->number_threads);
1923 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1924 cache_info->nexus_info[id],exception);
1929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1933 + G e t I m a g e E x t e n t %
1937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1939 % GetImageExtent() returns the extent of the pixels associated corresponding
1940 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
1942 % The format of the GetImageExtent() method is:
1944 % MagickSizeType GetImageExtent(const Image *image)
1946 % A description of each parameter follows:
1948 % o image: the image.
1951 MagickExport MagickSizeType GetImageExtent(const Image *image)
1957 id = GetOpenMPThreadId();
1959 assert(image != (Image *) NULL);
1960 assert(image->signature == MagickSignature);
1961 if (image->debug != MagickFalse)
1962 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1963 assert(image->cache != (Cache) NULL);
1964 cache_info=(CacheInfo *) image->cache;
1965 assert(cache_info->signature == MagickSignature);
1966 assert(id < (int) cache_info->number_threads);
1967 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
1971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1975 + G e t I m a g e P i x e l C a c h e %
1979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1981 % GetImagePixelCache() ensures that there is only a single reference to the
1982 % pixel cache to be modified, updating the provided cache pointer to point to
1983 % a clone of the original pixel cache if necessary.
1985 % The format of the GetImagePixelCache method is:
1987 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1988 % ExceptionInfo *exception)
1990 % A description of each parameter follows:
1992 % o image: the image.
1994 % o clone: any value other than MagickFalse clones the cache pixels.
1996 % o exception: return any errors or warnings in this structure.
2000 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
2010 Does the image match the pixel cache morphology?
2012 cache_info=(CacheInfo *) image->cache;
2013 p=image->channel_map;
2014 q=cache_info->channel_map;
2015 if ((image->storage_class != cache_info->storage_class) ||
2016 (image->colorspace != cache_info->colorspace) ||
2017 (image->matte != cache_info->matte) ||
2018 (image->columns != cache_info->columns) ||
2019 (image->rows != cache_info->rows) ||
2020 (image->number_channels != cache_info->number_channels) ||
2021 (memcmp(p,q,image->number_channels*sizeof(*p)) != 0) ||
2022 (image->metacontent_extent != cache_info->metacontent_extent) ||
2023 (cache_info->nexus_info == (NexusInfo **) NULL) ||
2024 (cache_info->number_threads < GetOpenMPMaximumThreads()))
2025 return(MagickFalse);
2029 static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
2030 ExceptionInfo *exception)
2039 static MagickSizeType
2045 cache_timestamp = 0;
2048 LockSemaphoreInfo(image->semaphore);
2049 if (cpu_throttle == 0)
2055 Set CPU throttle in milleseconds.
2057 cpu_throttle=MagickResourceInfinity;
2058 limit=GetEnvironmentValue("MAGICK_THROTTLE");
2059 if (limit == (char *) NULL)
2060 limit=GetPolicyValue("throttle");
2061 if (limit != (char *) NULL)
2063 cpu_throttle=(MagickSizeType) StringToInteger(limit);
2064 limit=DestroyString(limit);
2067 if ((cpu_throttle != MagickResourceInfinity) && ((cycles++ % 32) == 0))
2068 MagickDelay(cpu_throttle);
2069 if (time_limit == 0)
2072 Set the exire time in seconds.
2074 time_limit=GetMagickResourceLimit(TimeResource);
2075 cache_timestamp=time((time_t *) NULL);
2077 if ((time_limit != MagickResourceInfinity) &&
2078 ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
2079 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
2080 assert(image->cache != (Cache) NULL);
2081 cache_info=(CacheInfo *) image->cache;
2082 destroy=MagickFalse;
2083 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2085 LockSemaphoreInfo(cache_info->semaphore);
2086 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2097 clone_image=(*image);
2098 clone_image.semaphore=AllocateSemaphoreInfo();
2099 clone_image.reference_count=1;
2100 clone_image.cache=ClonePixelCache(cache_info);
2101 clone_info=(CacheInfo *) clone_image.cache;
2102 status=OpenPixelCache(&clone_image,IOMode,exception);
2103 if (status != MagickFalse)
2105 if (clone != MagickFalse)
2106 status=ClonePixelCachePixels(clone_info,cache_info,exception);
2107 if (status != MagickFalse)
2109 if (cache_info->mode == ReadMode)
2110 cache_info->nexus_info=(NexusInfo **) NULL;
2112 image->cache=clone_image.cache;
2115 DestroySemaphoreInfo(&clone_image.semaphore);
2117 UnlockSemaphoreInfo(cache_info->semaphore);
2119 if (destroy != MagickFalse)
2120 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
2121 if (status != MagickFalse)
2124 Ensure the image matches the pixel cache morphology.
2126 image->taint=MagickTrue;
2127 image->type=UndefinedType;
2128 if (ValidatePixelCacheMorphology(image) == MagickFalse)
2129 status=OpenPixelCache(image,IOMode,exception);
2131 UnlockSemaphoreInfo(image->semaphore);
2132 if (status == MagickFalse)
2133 return((Cache) NULL);
2134 return(image->cache);
2138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2142 % G e t O n e A u t h e n t i c P i x e l %
2146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2148 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2149 % location. The image background color is returned if an error occurs.
2151 % The format of the GetOneAuthenticPixel() method is:
2153 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
2154 % const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2156 % A description of each parameter follows:
2158 % o image: the image.
2160 % o x,y: These values define the location of the pixel to return.
2162 % o pixel: return a pixel at the specified (x,y) location.
2164 % o exception: return any errors or warnings in this structure.
2167 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2168 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2179 assert(image != (Image *) NULL);
2180 assert(image->signature == MagickSignature);
2181 assert(image->cache != (Cache) NULL);
2182 cache_info=(CacheInfo *) image->cache;
2183 assert(cache_info->signature == MagickSignature);
2184 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2185 if (cache_info->methods.get_one_authentic_pixel_from_handler !=
2186 (GetOneAuthenticPixelFromHandler) NULL)
2187 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2189 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2190 if (q == (Quantum *) NULL)
2192 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2193 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2194 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2195 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2196 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2197 return(MagickFalse);
2199 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2204 channel=GetPixelChannelMapChannel(image,i);
2205 pixel[channel]=q[i];
2211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2215 + 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 %
2219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2221 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2222 % location. The image background color is returned if an error occurs.
2224 % The format of the GetOneAuthenticPixelFromCache() method is:
2226 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2227 % const ssize_t x,const ssize_t y,Quantum *pixel,
2228 % ExceptionInfo *exception)
2230 % A description of each parameter follows:
2232 % o image: the image.
2234 % o x,y: These values define the location of the pixel to return.
2236 % o pixel: return a pixel at the specified (x,y) location.
2238 % o exception: return any errors or warnings in this structure.
2241 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2242 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2248 id = GetOpenMPThreadId();
2256 assert(image != (const Image *) NULL);
2257 assert(image->signature == MagickSignature);
2258 assert(image->cache != (Cache) NULL);
2259 cache_info=(CacheInfo *) image->cache;
2260 assert(cache_info->signature == MagickSignature);
2261 assert(id < (int) cache_info->number_threads);
2262 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2263 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
2265 if (q == (Quantum *) NULL)
2267 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2268 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2269 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2270 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2271 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2272 return(MagickFalse);
2274 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2279 channel=GetPixelChannelMapChannel(image,i);
2280 pixel[channel]=q[i];
2286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2290 % G e t O n e V i r t u a l P i x e l %
2294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2296 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2297 % (x,y) location. The image background color is returned if an error occurs.
2298 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2300 % The format of the GetOneVirtualPixel() method is:
2302 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
2303 % const ssize_t y,Quantum *pixel,ExceptionInfo exception)
2305 % A description of each parameter follows:
2307 % o image: the image.
2309 % o x,y: These values define the location of the pixel to return.
2311 % o pixel: return a pixel at the specified (x,y) location.
2313 % o exception: return any errors or warnings in this structure.
2316 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2317 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2323 id = GetOpenMPThreadId();
2331 assert(image != (const Image *) NULL);
2332 assert(image->signature == MagickSignature);
2333 assert(image->cache != (Cache) NULL);
2334 cache_info=(CacheInfo *) image->cache;
2335 assert(cache_info->signature == MagickSignature);
2336 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2337 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2338 (GetOneVirtualPixelFromHandler) NULL)
2339 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2340 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2341 assert(id < (int) cache_info->number_threads);
2342 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2343 1UL,1UL,cache_info->nexus_info[id],exception);
2344 if (p == (const Quantum *) NULL)
2346 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2347 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2348 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2349 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2350 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2351 return(MagickFalse);
2353 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2358 channel=GetPixelChannelMapChannel(image,i);
2359 pixel[channel]=p[i];
2365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2369 + 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 %
2373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2375 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2376 % specified (x,y) location. The image background color is returned if an
2379 % The format of the GetOneVirtualPixelFromCache() method is:
2381 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2382 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2383 % Quantum *pixel,ExceptionInfo *exception)
2385 % A description of each parameter follows:
2387 % o image: the image.
2389 % o virtual_pixel_method: the virtual pixel method.
2391 % o x,y: These values define the location of the pixel to return.
2393 % o pixel: return a pixel at the specified (x,y) location.
2395 % o exception: return any errors or warnings in this structure.
2398 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2399 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2400 Quantum *pixel,ExceptionInfo *exception)
2406 id = GetOpenMPThreadId();
2414 assert(image != (const Image *) NULL);
2415 assert(image->signature == MagickSignature);
2416 assert(image->cache != (Cache) NULL);
2417 cache_info=(CacheInfo *) image->cache;
2418 assert(cache_info->signature == MagickSignature);
2419 assert(id < (int) cache_info->number_threads);
2420 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2421 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2422 cache_info->nexus_info[id],exception);
2423 if (p == (const Quantum *) NULL)
2425 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2426 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2427 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2428 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2429 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2430 return(MagickFalse);
2432 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2437 channel=GetPixelChannelMapChannel(image,i);
2438 pixel[channel]=p[i];
2444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2448 % G e t O n e V i r t u a l P i x e l I n f o %
2452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2454 % GetOneVirtualPixelInfo() returns a single pixel at the specified (x,y)
2455 % location. The image background color is returned if an error occurs. If
2456 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2458 % The format of the GetOneVirtualPixelInfo() method is:
2460 % MagickBooleanType GetOneVirtualPixelInfo(const Image image,
2461 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2462 % const ssize_t y,PixelInfo *pixel,ExceptionInfo exception)
2464 % A description of each parameter follows:
2466 % o image: the image.
2468 % o virtual_pixel_method: the virtual pixel method.
2470 % o x,y: these values define the location of the pixel to return.
2472 % o pixel: return a pixel at the specified (x,y) location.
2474 % o exception: return any errors or warnings in this structure.
2477 MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
2478 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2479 PixelInfo *pixel,ExceptionInfo *exception)
2485 id = GetOpenMPThreadId();
2487 register const Quantum
2490 assert(image != (const Image *) NULL);
2491 assert(image->signature == MagickSignature);
2492 assert(image->cache != (Cache) NULL);
2493 cache_info=(CacheInfo *) image->cache;
2494 assert(cache_info->signature == MagickSignature);
2495 assert(id < (int) cache_info->number_threads);
2496 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2497 cache_info->nexus_info[id],exception);
2498 GetPixelInfo(image,pixel);
2499 if (p == (const Quantum *) NULL)
2500 return(MagickFalse);
2501 GetPixelInfoPixel(image,p,pixel);
2506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2510 + G e t P i x e l C a c h e C o l o r s p a c e %
2514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2516 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2518 % The format of the GetPixelCacheColorspace() method is:
2520 % Colorspace GetPixelCacheColorspace(Cache cache)
2522 % A description of each parameter follows:
2524 % o cache: the pixel cache.
2527 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
2532 assert(cache != (Cache) NULL);
2533 cache_info=(CacheInfo *) cache;
2534 assert(cache_info->signature == MagickSignature);
2535 if (cache_info->debug != MagickFalse)
2536 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2537 cache_info->filename);
2538 return(cache_info->colorspace);
2542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2546 + G e t P i x e l C a c h e M e t h o d s %
2550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2552 % GetPixelCacheMethods() initializes the CacheMethods structure.
2554 % The format of the GetPixelCacheMethods() method is:
2556 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2558 % A description of each parameter follows:
2560 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2563 MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
2565 assert(cache_methods != (CacheMethods *) NULL);
2566 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2567 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2568 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2569 cache_methods->get_virtual_metacontent_from_handler=
2570 GetVirtualMetacontentFromCache;
2571 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2572 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2573 cache_methods->get_authentic_metacontent_from_handler=
2574 GetAuthenticMetacontentFromCache;
2575 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2576 cache_methods->get_one_authentic_pixel_from_handler=
2577 GetOneAuthenticPixelFromCache;
2578 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2579 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2580 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2588 + G e t P i x e l C a c h e N e x u s E x t e n t %
2592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2594 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2595 % corresponding with the last call to SetPixelCacheNexusPixels() or
2596 % GetPixelCacheNexusPixels().
2598 % The format of the GetPixelCacheNexusExtent() method is:
2600 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2601 % NexusInfo *nexus_info)
2603 % A description of each parameter follows:
2605 % o nexus_info: the nexus info.
2608 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2609 NexusInfo *nexus_info)
2617 assert(cache != NULL);
2618 cache_info=(CacheInfo *) cache;
2619 assert(cache_info->signature == MagickSignature);
2620 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2622 return((MagickSizeType) cache_info->columns*cache_info->rows);
2627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2631 + 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 %
2635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2637 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2640 % The format of the GetPixelCacheNexusMetacontent() method is:
2642 % void *GetPixelCacheNexusMetacontent(const Cache cache,
2643 % NexusInfo *nexus_info)
2645 % A description of each parameter follows:
2647 % o cache: the pixel cache.
2649 % o nexus_info: the cache nexus to return the meta-content.
2652 MagickPrivate void *GetPixelCacheNexusMetacontent(const Cache cache,
2653 NexusInfo *nexus_info)
2658 assert(cache != NULL);
2659 cache_info=(CacheInfo *) cache;
2660 assert(cache_info->signature == MagickSignature);
2661 if (cache_info->storage_class == UndefinedClass)
2662 return((void *) NULL);
2663 return(nexus_info->metacontent);
2667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2671 + G e t P i x e l C a c h e N e x u s P i x e l s %
2675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2677 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2680 % The format of the GetPixelCacheNexusPixels() method is:
2682 % Quantum *GetPixelCacheNexusPixels(const Cache cache,
2683 % NexusInfo *nexus_info)
2685 % A description of each parameter follows:
2687 % o cache: the pixel cache.
2689 % o nexus_info: the cache nexus to return the pixels.
2692 MagickPrivate Quantum *GetPixelCacheNexusPixels(const Cache cache,
2693 NexusInfo *nexus_info)
2698 assert(cache != NULL);
2699 cache_info=(CacheInfo *) cache;
2700 assert(cache_info->signature == MagickSignature);
2701 if (cache_info->storage_class == UndefinedClass)
2702 return((Quantum *) NULL);
2703 return(nexus_info->pixels);
2707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2711 + G e t P i x e l C a c h e P i x e l s %
2715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2717 % GetPixelCachePixels() returns the pixels associated with the specified image.
2719 % The format of the GetPixelCachePixels() method is:
2721 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2722 % ExceptionInfo *exception)
2724 % A description of each parameter follows:
2726 % o image: the image.
2728 % o length: the pixel cache length.
2730 % o exception: return any errors or warnings in this structure.
2733 MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2734 ExceptionInfo *exception)
2739 assert(image != (const Image *) NULL);
2740 assert(image->signature == MagickSignature);
2741 assert(image->cache != (Cache) NULL);
2742 assert(length != (MagickSizeType *) NULL);
2743 assert(exception != (ExceptionInfo *) NULL);
2744 assert(exception->signature == MagickSignature);
2745 cache_info=(CacheInfo *) image->cache;
2746 assert(cache_info->signature == MagickSignature);
2748 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2749 return((void *) NULL);
2750 *length=cache_info->length;
2751 return((void *) cache_info->pixels);
2755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2759 + 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 %
2763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2765 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2767 % The format of the GetPixelCacheStorageClass() method is:
2769 % ClassType GetPixelCacheStorageClass(Cache cache)
2771 % A description of each parameter follows:
2773 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2775 % o cache: the pixel cache.
2778 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
2783 assert(cache != (Cache) NULL);
2784 cache_info=(CacheInfo *) cache;
2785 assert(cache_info->signature == MagickSignature);
2786 if (cache_info->debug != MagickFalse)
2787 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2788 cache_info->filename);
2789 return(cache_info->storage_class);
2793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2797 + G e t P i x e l C a c h e T i l e S i z e %
2801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2803 % GetPixelCacheTileSize() returns the pixel cache tile size.
2805 % The format of the GetPixelCacheTileSize() method is:
2807 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2810 % A description of each parameter follows:
2812 % o image: the image.
2814 % o width: the optimize cache tile width in pixels.
2816 % o height: the optimize cache tile height in pixels.
2819 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
2825 assert(image != (Image *) NULL);
2826 assert(image->signature == MagickSignature);
2827 if (image->debug != MagickFalse)
2828 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2829 cache_info=(CacheInfo *) image->cache;
2830 assert(cache_info->signature == MagickSignature);
2831 *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2832 if (GetPixelCacheType(image) == DiskCache)
2833 *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2842 + G e t P i x e l C a c h e T y p e %
2846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2848 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2850 % The format of the GetPixelCacheType() method is:
2852 % CacheType GetPixelCacheType(const Image *image)
2854 % A description of each parameter follows:
2856 % o image: the image.
2859 MagickPrivate CacheType GetPixelCacheType(const Image *image)
2864 assert(image != (Image *) NULL);
2865 assert(image->signature == MagickSignature);
2866 assert(image->cache != (Cache) NULL);
2867 cache_info=(CacheInfo *) image->cache;
2868 assert(cache_info->signature == MagickSignature);
2869 return(cache_info->type);
2873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877 + 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 %
2881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2883 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2884 % pixel cache. A virtual pixel is any pixel access that is outside the
2885 % boundaries of the image cache.
2887 % The format of the GetPixelCacheVirtualMethod() method is:
2889 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2891 % A description of each parameter follows:
2893 % o image: the image.
2896 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2901 assert(image != (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 return(cache_info->virtual_pixel_method);
2910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2914 + 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 %
2918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2920 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2921 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2923 % The format of the GetVirtualMetacontentFromCache() method is:
2925 % void *GetVirtualMetacontentFromCache(const Image *image)
2927 % A description of each parameter follows:
2929 % o image: the image.
2932 static const void *GetVirtualMetacontentFromCache(const Image *image)
2938 id = GetOpenMPThreadId();
2943 assert(image != (const Image *) NULL);
2944 assert(image->signature == MagickSignature);
2945 assert(image->cache != (Cache) NULL);
2946 cache_info=(CacheInfo *) image->cache;
2947 assert(cache_info->signature == MagickSignature);
2948 assert(id < (int) cache_info->number_threads);
2949 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2950 cache_info->nexus_info[id]);
2951 return(metacontent);
2955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2959 + 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 %
2963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2965 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2968 % The format of the GetVirtualMetacontentFromNexus() method is:
2970 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2971 % NexusInfo *nexus_info)
2973 % A description of each parameter follows:
2975 % o cache: the pixel cache.
2977 % o nexus_info: the cache nexus to return the meta-content.
2980 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
2981 NexusInfo *nexus_info)
2986 assert(cache != (Cache) NULL);
2987 cache_info=(CacheInfo *) cache;
2988 assert(cache_info->signature == MagickSignature);
2989 if (cache_info->storage_class == UndefinedClass)
2990 return((void *) NULL);
2991 return(nexus_info->metacontent);
2995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2999 % G e t V i r t u a l M e t a c o n t e n t %
3003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3005 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
3006 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
3007 % returned if the meta-content are not available.
3009 % The format of the GetVirtualMetacontent() method is:
3011 % const void *GetVirtualMetacontent(const Image *image)
3013 % A description of each parameter follows:
3015 % o image: the image.
3018 MagickExport const void *GetVirtualMetacontent(const Image *image)
3024 id = GetOpenMPThreadId();
3029 assert(image != (const Image *) NULL);
3030 assert(image->signature == MagickSignature);
3031 assert(image->cache != (Cache) NULL);
3032 cache_info=(CacheInfo *) image->cache;
3033 assert(cache_info->signature == MagickSignature);
3034 if (cache_info->methods.get_virtual_metacontent_from_handler !=
3035 (GetVirtualMetacontentFromHandler) NULL)
3037 metacontent=cache_info->methods.
3038 get_virtual_metacontent_from_handler(image);
3039 return(metacontent);
3041 assert(id < (int) cache_info->number_threads);
3042 metacontent=GetVirtualMetacontentFromNexus(cache_info,
3043 cache_info->nexus_info[id]);
3044 return(metacontent);
3048 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3052 + 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 %
3056 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3058 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
3059 % pixel cache as defined by the geometry parameters. A pointer to the pixels
3060 % is returned if the pixels are transferred, otherwise a NULL is returned.
3062 % The format of the GetVirtualPixelsFromNexus() method is:
3064 % Quantum *GetVirtualPixelsFromNexus(const Image *image,
3065 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
3066 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
3067 % ExceptionInfo *exception)
3069 % A description of each parameter follows:
3071 % o image: the image.
3073 % o virtual_pixel_method: the virtual pixel method.
3075 % o x,y,columns,rows: These values define the perimeter of a region of
3078 % o nexus_info: the cache nexus to acquire.
3080 % o exception: return any errors or warnings in this structure.
3087 0, 48, 12, 60, 3, 51, 15, 63,
3088 32, 16, 44, 28, 35, 19, 47, 31,
3089 8, 56, 4, 52, 11, 59, 7, 55,
3090 40, 24, 36, 20, 43, 27, 39, 23,
3091 2, 50, 14, 62, 1, 49, 13, 61,
3092 34, 18, 46, 30, 33, 17, 45, 29,
3093 10, 58, 6, 54, 9, 57, 5, 53,
3094 42, 26, 38, 22, 41, 25, 37, 21
3097 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
3102 index=x+DitherMatrix[x & 0x07]-32L;
3105 if (index >= (ssize_t) columns)
3106 return((ssize_t) columns-1L);
3110 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
3115 index=y+DitherMatrix[y & 0x07]-32L;
3118 if (index >= (ssize_t) rows)
3119 return((ssize_t) rows-1L);
3123 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
3127 if (x >= (ssize_t) columns)
3128 return((ssize_t) (columns-1));
3132 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
3136 if (y >= (ssize_t) rows)
3137 return((ssize_t) (rows-1));
3141 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
3143 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
3146 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
3148 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
3151 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
3152 const size_t extent)
3158 Compute the remainder of dividing offset by extent. It returns not only
3159 the quotient (tile the offset falls in) but also the positive remainer
3160 within that tile such that 0 <= remainder < extent. This method is
3161 essentially a ldiv() using a floored modulo division rather than the
3162 normal default truncated modulo division.
3164 modulo.quotient=offset/(ssize_t) extent;
3167 modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
3171 MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
3172 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3173 const size_t columns,const size_t rows,NexusInfo *nexus_info,
3174 ExceptionInfo *exception)
3191 virtual_pixel[CompositePixelChannel];
3196 register const Quantum
3209 register unsigned char
3216 *virtual_metacontent;
3221 assert(image != (const Image *) NULL);
3222 assert(image->signature == MagickSignature);
3223 assert(image->cache != (Cache) NULL);
3224 cache_info=(CacheInfo *) image->cache;
3225 assert(cache_info->signature == MagickSignature);
3226 if (cache_info->type == UndefinedCache)
3227 return((const Quantum *) NULL);
3230 region.width=columns;
3232 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3233 if (pixels == (Quantum *) NULL)
3234 return((const Quantum *) NULL);
3236 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3237 nexus_info->region.x;
3238 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3239 nexus_info->region.width-1L;
3240 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3241 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3242 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3243 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3249 Pixel request is inside cache extents.
3251 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3253 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3254 if (status == MagickFalse)
3255 return((const Quantum *) NULL);
3256 if (cache_info->metacontent_extent != 0)
3258 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3259 if (status == MagickFalse)
3260 return((const Quantum *) NULL);
3265 Pixel request is outside cache extents.
3267 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3268 virtual_nexus=AcquirePixelCacheNexus(1);
3269 if (virtual_nexus == (NexusInfo **) NULL)
3271 if (virtual_nexus != (NexusInfo **) NULL)
3272 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3273 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3274 "UnableToGetCacheNexus","`%s'",image->filename);
3275 return((const Quantum *) NULL);
3277 (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
3278 sizeof(*virtual_pixel));
3279 virtual_metacontent=(void *) NULL;
3280 switch (virtual_pixel_method)
3282 case BackgroundVirtualPixelMethod:
3283 case BlackVirtualPixelMethod:
3284 case GrayVirtualPixelMethod:
3285 case TransparentVirtualPixelMethod:
3286 case MaskVirtualPixelMethod:
3287 case WhiteVirtualPixelMethod:
3288 case EdgeVirtualPixelMethod:
3289 case CheckerTileVirtualPixelMethod:
3290 case HorizontalTileVirtualPixelMethod:
3291 case VerticalTileVirtualPixelMethod:
3293 if (cache_info->metacontent_extent != 0)
3296 Acquire a metacontent buffer.
3298 virtual_metacontent=(void *) AcquireQuantumMemory(1,
3299 cache_info->metacontent_extent);
3300 if (virtual_metacontent == (void *) NULL)
3302 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3303 (void) ThrowMagickException(exception,GetMagickModule(),
3304 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
3305 return((const Quantum *) NULL);
3307 (void) ResetMagickMemory(virtual_metacontent,0,
3308 cache_info->metacontent_extent);
3310 switch (virtual_pixel_method)
3312 case BlackVirtualPixelMethod:
3314 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3315 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3316 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3319 case GrayVirtualPixelMethod:
3321 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3322 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
3324 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3327 case TransparentVirtualPixelMethod:
3329 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3330 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3331 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3334 case MaskVirtualPixelMethod:
3335 case WhiteVirtualPixelMethod:
3337 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3338 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
3339 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3344 SetPixelRed(image,ClampToQuantum(image->background_color.red),
3346 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
3348 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
3350 if (image->colorspace == CMYKColorspace)
3351 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
3353 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
3363 for (v=0; v < (ssize_t) rows; v++)
3365 for (u=0; u < (ssize_t) columns; u+=length)
3367 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3368 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3369 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3377 Transfer a single pixel.
3379 length=(MagickSizeType) 1;
3380 switch (virtual_pixel_method)
3384 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3385 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3386 1UL,1UL,*virtual_nexus,exception);
3387 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3390 case RandomVirtualPixelMethod:
3392 if (cache_info->random_info == (RandomInfo *) NULL)
3393 cache_info->random_info=AcquireRandomInfo();
3394 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3395 RandomX(cache_info->random_info,cache_info->columns),
3396 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3397 *virtual_nexus,exception);
3398 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3401 case DitherVirtualPixelMethod:
3403 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3404 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3405 1UL,1UL,*virtual_nexus,exception);
3406 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3409 case TileVirtualPixelMethod:
3411 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3412 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3413 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3414 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3416 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3419 case MirrorVirtualPixelMethod:
3421 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3422 if ((x_modulo.quotient & 0x01) == 1L)
3423 x_modulo.remainder=(ssize_t) cache_info->columns-
3424 x_modulo.remainder-1L;
3425 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3426 if ((y_modulo.quotient & 0x01) == 1L)
3427 y_modulo.remainder=(ssize_t) cache_info->rows-
3428 y_modulo.remainder-1L;
3429 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3430 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3432 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3435 case HorizontalTileEdgeVirtualPixelMethod:
3437 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3438 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3439 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3440 *virtual_nexus,exception);
3441 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3444 case VerticalTileEdgeVirtualPixelMethod:
3446 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3447 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3448 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3449 *virtual_nexus,exception);
3450 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3453 case BackgroundVirtualPixelMethod:
3454 case BlackVirtualPixelMethod:
3455 case GrayVirtualPixelMethod:
3456 case TransparentVirtualPixelMethod:
3457 case MaskVirtualPixelMethod:
3458 case WhiteVirtualPixelMethod:
3461 r=virtual_metacontent;
3464 case EdgeVirtualPixelMethod:
3465 case CheckerTileVirtualPixelMethod:
3467 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3468 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3469 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3472 r=virtual_metacontent;
3475 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3476 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3478 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3481 case HorizontalTileVirtualPixelMethod:
3483 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3486 r=virtual_metacontent;
3489 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3490 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3491 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3492 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3494 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3497 case VerticalTileVirtualPixelMethod:
3499 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3502 r=virtual_metacontent;
3505 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3506 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3507 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3508 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3510 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3514 if (p == (const Quantum *) NULL)
3516 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3518 q+=cache_info->number_channels;
3519 if ((s != (void *) NULL) && (r != (const void *) NULL))
3521 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3522 s+=cache_info->metacontent_extent;
3527 Transfer a run of pixels.
3529 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3530 length,1UL,*virtual_nexus,exception);
3531 if (p == (const Quantum *) NULL)
3533 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3534 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3535 q+=length*cache_info->number_channels;
3536 if ((r != (void *) NULL) && (s != (const void *) NULL))
3538 (void) memcpy(s,r,(size_t) length);
3539 s+=length*cache_info->metacontent_extent;
3546 if (virtual_metacontent != (void *) NULL)
3547 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3548 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3557 + G e t V i r t u a l P i x e l C a c h e %
3561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3563 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3564 % cache as defined by the geometry parameters. A pointer to the pixels
3565 % is returned if the pixels are transferred, otherwise a NULL is returned.
3567 % The format of the GetVirtualPixelCache() method is:
3569 % const Quantum *GetVirtualPixelCache(const Image *image,
3570 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3571 % const ssize_t y,const size_t columns,const size_t rows,
3572 % ExceptionInfo *exception)
3574 % A description of each parameter follows:
3576 % o image: the image.
3578 % o virtual_pixel_method: the virtual pixel method.
3580 % o x,y,columns,rows: These values define the perimeter of a region of
3583 % o exception: return any errors or warnings in this structure.
3586 static const Quantum *GetVirtualPixelCache(const Image *image,
3587 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3588 const size_t columns,const size_t rows,ExceptionInfo *exception)
3594 id = GetOpenMPThreadId();
3599 assert(image != (const Image *) NULL);
3600 assert(image->signature == MagickSignature);
3601 assert(image->cache != (Cache) NULL);
3602 cache_info=(CacheInfo *) image->cache;
3603 assert(cache_info->signature == MagickSignature);
3604 assert(id < (int) cache_info->number_threads);
3605 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3606 cache_info->nexus_info[id],exception);
3611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3615 % G e t V i r t u a l P i x e l Q u e u e %
3619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3621 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3622 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3624 % The format of the GetVirtualPixelQueue() method is:
3626 % const Quantum *GetVirtualPixelQueue(const Image image)
3628 % A description of each parameter follows:
3630 % o image: the image.
3633 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3639 id = GetOpenMPThreadId();
3641 assert(image != (const Image *) NULL);
3642 assert(image->signature == MagickSignature);
3643 assert(image->cache != (Cache) NULL);
3644 cache_info=(CacheInfo *) image->cache;
3645 assert(cache_info->signature == MagickSignature);
3646 if (cache_info->methods.get_virtual_pixels_handler !=
3647 (GetVirtualPixelsHandler) NULL)
3648 return(cache_info->methods.get_virtual_pixels_handler(image));
3649 assert(id < (int) cache_info->number_threads);
3650 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3658 % G e t V i r t u a l P i x e l s %
3662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3664 % GetVirtualPixels() returns an immutable pixel region. If the
3665 % region is successfully accessed, a pointer to it is returned, otherwise
3666 % NULL is returned. The returned pointer may point to a temporary working
3667 % copy of the pixels or it may point to the original pixels in memory.
3668 % Performance is maximized if the selected region is part of one row, or one
3669 % or more full rows, since there is opportunity to access the pixels in-place
3670 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3671 % returned pointer must *never* be deallocated by the user.
3673 % Pixels accessed via the returned pointer represent a simple array of type
3674 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3675 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3676 % access the meta-content (of type void) corresponding to the the
3679 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3681 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3682 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3683 % GetCacheViewAuthenticPixels() instead.
3685 % The format of the GetVirtualPixels() method is:
3687 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3688 % const ssize_t y,const size_t columns,const size_t rows,
3689 % ExceptionInfo *exception)
3691 % A description of each parameter follows:
3693 % o image: the image.
3695 % o x,y,columns,rows: These values define the perimeter of a region of
3698 % o exception: return any errors or warnings in this structure.
3701 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3702 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3703 ExceptionInfo *exception)
3709 id = GetOpenMPThreadId();
3714 assert(image != (const Image *) NULL);
3715 assert(image->signature == MagickSignature);
3716 assert(image->cache != (Cache) NULL);
3717 cache_info=(CacheInfo *) image->cache;
3718 assert(cache_info->signature == MagickSignature);
3719 if (cache_info->methods.get_virtual_pixel_handler !=
3720 (GetVirtualPixelHandler) NULL)
3721 return(cache_info->methods.get_virtual_pixel_handler(image,
3722 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3723 assert(id < (int) cache_info->number_threads);
3724 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3725 columns,rows,cache_info->nexus_info[id],exception);
3730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3734 + 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 %
3738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3740 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3741 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3743 % The format of the GetVirtualPixelsCache() method is:
3745 % Quantum *GetVirtualPixelsCache(const Image *image)
3747 % A description of each parameter follows:
3749 % o image: the image.
3752 static const Quantum *GetVirtualPixelsCache(const Image *image)
3758 id = GetOpenMPThreadId();
3760 assert(image != (const Image *) NULL);
3761 assert(image->signature == MagickSignature);
3762 assert(image->cache != (Cache) NULL);
3763 cache_info=(CacheInfo *) image->cache;
3764 assert(cache_info->signature == MagickSignature);
3765 assert(id < (int) cache_info->number_threads);
3766 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3774 + G e t V i r t u a l P i x e l s N e x u s %
3778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3780 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3783 % The format of the GetVirtualPixelsNexus() method is:
3785 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3786 % NexusInfo *nexus_info)
3788 % A description of each parameter follows:
3790 % o cache: the pixel cache.
3792 % o nexus_info: the cache nexus to return the colormap pixels.
3795 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
3796 NexusInfo *nexus_info)
3801 assert(cache != (Cache) NULL);
3802 cache_info=(CacheInfo *) cache;
3803 assert(cache_info->signature == MagickSignature);
3804 if (cache_info->storage_class == UndefinedClass)
3805 return((Quantum *) NULL);
3806 return((const Quantum *) nexus_info->pixels);
3810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3814 + M a s k P i x e l C a c h e N e x u s %
3818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3820 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3821 % The method returns MagickTrue if the pixel region is masked, otherwise
3824 % The format of the MaskPixelCacheNexus() method is:
3826 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3827 % NexusInfo *nexus_info,ExceptionInfo *exception)
3829 % A description of each parameter follows:
3831 % o image: the image.
3833 % o nexus_info: the cache nexus to clip.
3835 % o exception: return any errors or warnings in this structure.
3839 static inline void MaskPixelOver(const PixelInfo *p,const MagickRealType alpha,
3840 const PixelInfo *q,const MagickRealType beta,PixelInfo *composite)
3845 if (fabs(alpha-TransparentAlpha) < MagickEpsilon)
3850 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3851 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3852 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3853 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3854 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3855 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3856 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
3859 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3860 ExceptionInfo *exception)
3876 register const Quantum
3889 if (image->debug != MagickFalse)
3890 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3891 if (image->mask == (Image *) NULL)
3892 return(MagickFalse);
3893 cache_info=(CacheInfo *) image->cache;
3894 if (cache_info == (Cache) NULL)
3895 return(MagickFalse);
3896 image_nexus=AcquirePixelCacheNexus(1);
3897 clip_nexus=AcquirePixelCacheNexus(1);
3898 if ((image_nexus == (NexusInfo **) NULL) ||
3899 (clip_nexus == (NexusInfo **) NULL))
3900 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3901 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3902 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3903 nexus_info->region.height,image_nexus[0],exception);
3904 q=nexus_info->pixels;
3905 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3906 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3907 nexus_info->region.height,clip_nexus[0],exception);
3908 GetPixelInfo(image,&alpha);
3909 GetPixelInfo(image,&beta);
3910 number_pixels=(MagickSizeType) nexus_info->region.width*
3911 nexus_info->region.height;
3912 for (i=0; i < (ssize_t) number_pixels; i++)
3914 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3916 GetPixelInfoPixel(image,p,&alpha);
3917 GetPixelInfoPixel(image,q,&beta);
3918 MaskPixelOver(&beta,(MagickRealType) GetPixelIntensity(image,r),
3919 &alpha,alpha.alpha,&beta);
3920 SetPixelRed(image,ClampToQuantum(beta.red),q);
3921 SetPixelGreen(image,ClampToQuantum(beta.green),q);
3922 SetPixelBlue(image,ClampToQuantum(beta.blue),q);
3923 if (cache_info->colorspace == CMYKColorspace)
3924 SetPixelBlack(image,ClampToQuantum(beta.black),q);
3925 SetPixelAlpha(image,ClampToQuantum(beta.alpha),q);
3930 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3931 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3932 if (i < (ssize_t) number_pixels)
3933 return(MagickFalse);
3938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3942 + O p e n P i x e l C a c h e %
3946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3948 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3949 % dimensions, allocating space for the image pixels and optionally the
3950 % metacontent, and memory mapping the cache if it is disk based. The cache
3951 % nexus array is initialized as well.
3953 % The format of the OpenPixelCache() method is:
3955 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3956 % ExceptionInfo *exception)
3958 % A description of each parameter follows:
3960 % o image: the image.
3962 % o mode: ReadMode, WriteMode, or IOMode.
3964 % o exception: return any errors or warnings in this structure.
3968 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3970 cache_info->mapped=MagickFalse;
3971 cache_info->pixels=(Quantum *) AcquireQuantumMemory(1,(size_t)
3972 cache_info->length);
3973 if (cache_info->pixels == (Quantum *) NULL)
3975 cache_info->mapped=MagickTrue;
3976 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3977 cache_info->length);
3981 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3991 cache_info=(CacheInfo *) image->cache;
3992 if (image->debug != MagickFalse)
3995 format[MaxTextExtent],
3996 message[MaxTextExtent];
3998 (void) FormatMagickSize(length,MagickFalse,format);
3999 (void) FormatLocaleString(message,MaxTextExtent,
4000 "extend %s (%s[%d], disk, %s)",cache_info->filename,
4001 cache_info->cache_filename,cache_info->file,format);
4002 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4004 if (length != (MagickSizeType) ((MagickOffsetType) length))
4005 return(MagickFalse);
4006 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
4008 return(MagickFalse);
4009 if ((MagickSizeType) extent >= length)
4011 offset=(MagickOffsetType) length-1;
4012 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
4013 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
4016 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
4017 ExceptionInfo *exception)
4024 format[MaxTextExtent],
4025 message[MaxTextExtent];
4042 assert(image != (const Image *) NULL);
4043 assert(image->signature == MagickSignature);
4044 assert(image->cache != (Cache) NULL);
4045 if (image->debug != MagickFalse)
4046 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4047 if ((image->columns == 0) || (image->rows == 0))
4048 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
4049 cache_info=(CacheInfo *) image->cache;
4050 assert(cache_info->signature == MagickSignature);
4051 source_info=(*cache_info);
4052 source_info.file=(-1);
4053 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
4054 image->filename,(double) GetImageIndexInList(image));
4055 cache_info->storage_class=image->storage_class;
4056 cache_info->colorspace=image->colorspace;
4057 cache_info->matte=image->matte;
4058 cache_info->rows=image->rows;
4059 cache_info->columns=image->columns;
4060 InitializePixelChannelMap(image);
4061 cache_info->number_channels=GetPixelChannels(image);
4062 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
4063 sizeof(*image->channel_map));
4064 cache_info->metacontent_extent=image->metacontent_extent;
4065 cache_info->mode=mode;
4066 if (image->ping != MagickFalse)
4068 cache_info->type=PingCache;
4069 cache_info->pixels=(Quantum *) NULL;
4070 cache_info->metacontent=(void *) NULL;
4071 cache_info->length=0;
4074 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4075 packet_size=cache_info->number_channels*sizeof(Quantum);
4076 if (image->metacontent_extent != 0)
4077 packet_size+=cache_info->metacontent_extent;
4078 length=number_pixels*packet_size;
4079 columns=(size_t) (length/cache_info->rows/packet_size);
4080 if (cache_info->columns != columns)
4081 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4083 cache_info->length=length;
4084 p=cache_info->channel_map;
4085 q=source_info.channel_map;
4086 if ((cache_info->type != UndefinedCache) &&
4087 (cache_info->columns <= source_info.columns) &&
4088 (cache_info->rows <= source_info.rows) &&
4089 (cache_info->number_channels <= source_info.number_channels) &&
4090 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) &&
4091 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4094 Inline pixel cache clone optimization.
4096 if ((cache_info->columns == source_info.columns) &&
4097 (cache_info->rows == source_info.rows) &&
4098 (cache_info->number_channels == source_info.number_channels) &&
4099 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) &&
4100 (cache_info->metacontent_extent == source_info.metacontent_extent))
4102 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4104 status=AcquireMagickResource(AreaResource,cache_info->length);
4105 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4106 cache_info->metacontent_extent);
4107 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4109 status=AcquireMagickResource(MemoryResource,cache_info->length);
4110 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4111 (cache_info->type == MemoryCache))
4113 AllocatePixelCachePixels(cache_info);
4114 if (cache_info->pixels == (Quantum *) NULL)
4115 cache_info->pixels=source_info.pixels;
4119 Create memory pixel cache.
4122 if (image->debug != MagickFalse)
4124 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4125 (void) FormatLocaleString(message,MaxTextExtent,
4126 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4127 cache_info->filename,cache_info->mapped != MagickFalse ?
4128 "anonymous" : "heap",(double) cache_info->columns,(double)
4129 cache_info->rows,(double) cache_info->number_channels,
4131 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4134 cache_info->type=MemoryCache;
4135 cache_info->metacontent=(void *) NULL;
4136 if (cache_info->metacontent_extent != 0)
4137 cache_info->metacontent=(void *) (cache_info->pixels+
4138 number_pixels*cache_info->number_channels);
4139 if (source_info.storage_class != UndefinedClass)
4141 status=ClonePixelCachePixels(cache_info,&source_info,
4143 RelinquishPixelCachePixels(&source_info);
4148 RelinquishMagickResource(MemoryResource,cache_info->length);
4151 Create pixel cache on disk.
4153 status=AcquireMagickResource(DiskResource,cache_info->length);
4154 if (status == MagickFalse)
4156 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4157 "CacheResourcesExhausted","`%s'",image->filename);
4158 return(MagickFalse);
4160 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4162 RelinquishMagickResource(DiskResource,cache_info->length);
4163 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4165 return(MagickFalse);
4167 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4168 cache_info->length);
4169 if (status == MagickFalse)
4171 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4173 return(MagickFalse);
4175 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4176 cache_info->metacontent_extent);
4177 if (length != (MagickSizeType) ((size_t) length))
4178 cache_info->type=DiskCache;
4181 status=AcquireMagickResource(MapResource,cache_info->length);
4182 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4183 (cache_info->type != MemoryCache))
4184 cache_info->type=DiskCache;
4187 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4188 cache_info->offset,(size_t) cache_info->length);
4189 if (cache_info->pixels == (Quantum *) NULL)
4191 cache_info->type=DiskCache;
4192 cache_info->pixels=source_info.pixels;
4197 Create file-backed memory-mapped pixel cache.
4200 (void) ClosePixelCacheOnDisk(cache_info);
4201 cache_info->type=MapCache;
4202 cache_info->mapped=MagickTrue;
4203 cache_info->metacontent=(void *) NULL;
4204 if (cache_info->metacontent_extent != 0)
4205 cache_info->metacontent=(void *) (cache_info->pixels+
4206 number_pixels*cache_info->number_channels);
4207 if (source_info.storage_class != UndefinedClass)
4209 status=ClonePixelCachePixels(cache_info,&source_info,
4211 RelinquishPixelCachePixels(&source_info);
4213 if (image->debug != MagickFalse)
4215 (void) FormatMagickSize(cache_info->length,MagickTrue,
4217 (void) FormatLocaleString(message,MaxTextExtent,
4218 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4219 cache_info->filename,cache_info->cache_filename,
4220 cache_info->file,(double) cache_info->columns,(double)
4221 cache_info->rows,(double) cache_info->number_channels,
4223 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4229 RelinquishMagickResource(MapResource,cache_info->length);
4232 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4234 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4235 RelinquishPixelCachePixels(&source_info);
4237 if (image->debug != MagickFalse)
4239 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4240 (void) FormatLocaleString(message,MaxTextExtent,
4241 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4242 cache_info->cache_filename,cache_info->file,(double)
4243 cache_info->columns,(double) cache_info->rows,(double)
4244 cache_info->number_channels,format);
4245 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4255 + P e r s i s t P i x e l C a c h e %
4259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4261 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4262 % persistent pixel cache is one that resides on disk and is not destroyed
4263 % when the program exits.
4265 % The format of the PersistPixelCache() method is:
4267 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4268 % const MagickBooleanType attach,MagickOffsetType *offset,
4269 % ExceptionInfo *exception)
4271 % A description of each parameter follows:
4273 % o image: the image.
4275 % o filename: the persistent pixel cache filename.
4277 % o attach: A value other than zero initializes the persistent pixel cache.
4279 % o initialize: A value other than zero initializes the persistent pixel
4282 % o offset: the offset in the persistent cache to store pixels.
4284 % o exception: return any errors or warnings in this structure.
4287 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4288 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4289 ExceptionInfo *exception)
4304 assert(image != (Image *) NULL);
4305 assert(image->signature == MagickSignature);
4306 if (image->debug != MagickFalse)
4307 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4308 assert(image->cache != (void *) NULL);
4309 assert(filename != (const char *) NULL);
4310 assert(offset != (MagickOffsetType *) NULL);
4311 page_size=GetMagickPageSize();
4312 cache_info=(CacheInfo *) image->cache;
4313 assert(cache_info->signature == MagickSignature);
4314 if (attach != MagickFalse)
4317 Attach existing persistent pixel cache.
4319 if (image->debug != MagickFalse)
4320 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4321 "attach persistent cache");
4322 (void) CopyMagickString(cache_info->cache_filename,filename,
4324 cache_info->type=DiskCache;
4325 cache_info->offset=(*offset);
4326 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4327 return(MagickFalse);
4328 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4331 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4332 (cache_info->reference_count == 1))
4334 LockSemaphoreInfo(cache_info->semaphore);
4335 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4336 (cache_info->reference_count == 1))
4342 Usurp existing persistent pixel cache.
4344 status=rename_utf8(cache_info->cache_filename,filename);
4347 (void) CopyMagickString(cache_info->cache_filename,filename,
4349 *offset+=cache_info->length+page_size-(cache_info->length %
4351 UnlockSemaphoreInfo(cache_info->semaphore);
4352 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4353 if (image->debug != MagickFalse)
4354 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4355 "Usurp resident persistent cache");
4359 UnlockSemaphoreInfo(cache_info->semaphore);
4362 Clone persistent pixel cache.
4364 clone_image=(*image);
4365 clone_info=(CacheInfo *) clone_image.cache;
4366 image->cache=ClonePixelCache(cache_info);
4367 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4368 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4369 cache_info->type=DiskCache;
4370 cache_info->offset=(*offset);
4371 cache_info=(CacheInfo *) image->cache;
4372 status=OpenPixelCache(image,IOMode,exception);
4373 if (status != MagickFalse)
4374 status=ClonePixelCachePixels(cache_info,clone_info,exception);
4375 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4376 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4385 + Q u e u e A u t h e n t i c N e x u s %
4389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4391 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4392 % by the region rectangle and returns a pointer to the region. This region is
4393 % subsequently transferred from the pixel cache with
4394 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4395 % pixels are transferred, otherwise a NULL is returned.
4397 % The format of the QueueAuthenticNexus() method is:
4399 % Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4400 % const ssize_t y,const size_t columns,const size_t rows,
4401 % const MagickBooleanType clone,NexusInfo *nexus_info,
4402 % ExceptionInfo *exception)
4404 % A description of each parameter follows:
4406 % o image: the image.
4408 % o x,y,columns,rows: These values define the perimeter of a region of
4411 % o nexus_info: the cache nexus to set.
4413 % o clone: clone the pixel cache.
4415 % o exception: return any errors or warnings in this structure.
4418 MagickPrivate Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4419 const ssize_t y,const size_t columns,const size_t rows,
4420 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4435 Validate pixel cache geometry.
4437 assert(image != (const Image *) NULL);
4438 assert(image->signature == MagickSignature);
4439 assert(image->cache != (Cache) NULL);
4440 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4441 if (cache_info == (Cache) NULL)
4442 return((Quantum *) NULL);
4443 assert(cache_info->signature == MagickSignature);
4444 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4446 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4447 "NoPixelsDefinedInCache","`%s'",image->filename);
4448 return((Quantum *) NULL);
4450 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4451 (y >= (ssize_t) cache_info->rows))
4453 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4454 "PixelsAreNotAuthentic","`%s'",image->filename);
4455 return((Quantum *) NULL);
4457 offset=(MagickOffsetType) y*cache_info->columns+x;
4459 return((Quantum *) NULL);
4460 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4461 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4462 if ((MagickSizeType) offset >= number_pixels)
4463 return((Quantum *) NULL);
4469 region.width=columns;
4471 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4475 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4479 + 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 %
4483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4485 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4486 % defined by the region rectangle and returns a pointer to the region. This
4487 % region is subsequently transferred from the pixel cache with
4488 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4489 % pixels are transferred, otherwise a NULL is returned.
4491 % The format of the QueueAuthenticPixelsCache() method is:
4493 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4494 % const ssize_t y,const size_t columns,const size_t rows,
4495 % ExceptionInfo *exception)
4497 % A description of each parameter follows:
4499 % o image: the image.
4501 % o x,y,columns,rows: These values define the perimeter of a region of
4504 % o exception: return any errors or warnings in this structure.
4507 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4508 const ssize_t y,const size_t columns,const size_t rows,
4509 ExceptionInfo *exception)
4515 id = GetOpenMPThreadId();
4520 assert(image != (const Image *) NULL);
4521 assert(image->signature == MagickSignature);
4522 assert(image->cache != (Cache) NULL);
4523 cache_info=(CacheInfo *) image->cache;
4524 assert(cache_info->signature == MagickSignature);
4525 assert(id < (int) cache_info->number_threads);
4526 q=QueueAuthenticNexus(image,x,y,columns,rows,MagickFalse,
4527 cache_info->nexus_info[id],exception);
4532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4536 % Q u e u e A u t h e n t i c P i x e l s %
4540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4542 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4543 % successfully initialized a pointer to a Quantum array representing the
4544 % region is returned, otherwise NULL is returned. The returned pointer may
4545 % point to a temporary working buffer for the pixels or it may point to the
4546 % final location of the pixels in memory.
4548 % Write-only access means that any existing pixel values corresponding to
4549 % the region are ignored. This is useful if the initial image is being
4550 % created from scratch, or if the existing pixel values are to be
4551 % completely replaced without need to refer to their pre-existing values.
4552 % The application is free to read and write the pixel buffer returned by
4553 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4554 % initialize the pixel array values. Initializing pixel array values is the
4555 % application's responsibility.
4557 % Performance is maximized if the selected region is part of one row, or
4558 % one or more full rows, since then there is opportunity to access the
4559 % pixels in-place (without a copy) if the image is in memory, or in a
4560 % memory-mapped file. The returned pointer must *never* be deallocated
4563 % Pixels accessed via the returned pointer represent a simple array of type
4564 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4565 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4566 % obtain the meta-content (of type void) corresponding to the region.
4567 % Once the Quantum (and/or Quantum) array has been updated, the
4568 % changes must be saved back to the underlying image using
4569 % SyncAuthenticPixels() or they may be lost.
4571 % The format of the QueueAuthenticPixels() method is:
4573 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4574 % const ssize_t y,const size_t columns,const size_t rows,
4575 % ExceptionInfo *exception)
4577 % A description of each parameter follows:
4579 % o image: the image.
4581 % o x,y,columns,rows: These values define the perimeter of a region of
4584 % o exception: return any errors or warnings in this structure.
4587 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4588 const ssize_t y,const size_t columns,const size_t rows,
4589 ExceptionInfo *exception)
4595 id = GetOpenMPThreadId();
4600 assert(image != (Image *) NULL);
4601 assert(image->signature == MagickSignature);
4602 assert(image->cache != (Cache) NULL);
4603 cache_info=(CacheInfo *) image->cache;
4604 assert(cache_info->signature == MagickSignature);
4605 if (cache_info->methods.queue_authentic_pixels_handler !=
4606 (QueueAuthenticPixelsHandler) NULL)
4608 q=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4609 columns,rows,exception);
4612 assert(id < (int) cache_info->number_threads);
4613 q=QueueAuthenticNexus(image,x,y,columns,rows,MagickFalse,
4614 cache_info->nexus_info[id],exception);
4619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4623 + 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 %
4627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4629 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4632 % The format of the ReadPixelCacheMetacontent() method is:
4634 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4635 % NexusInfo *nexus_info,ExceptionInfo *exception)
4637 % A description of each parameter follows:
4639 % o cache_info: the pixel cache.
4641 % o nexus_info: the cache nexus to read the metacontent.
4643 % o exception: return any errors or warnings in this structure.
4646 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4647 NexusInfo *nexus_info,ExceptionInfo *exception)
4660 register unsigned char
4666 if (cache_info->metacontent_extent == 0)
4667 return(MagickFalse);
4668 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4670 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4671 nexus_info->region.x;
4672 length=(MagickSizeType) nexus_info->region.width*
4673 cache_info->metacontent_extent;
4674 rows=nexus_info->region.height;
4676 q=(unsigned char *) nexus_info->metacontent;
4677 switch (cache_info->type)
4682 register unsigned char
4686 Read meta-content from memory.
4688 if ((cache_info->columns == nexus_info->region.width) &&
4689 (extent == (MagickSizeType) ((size_t) extent)))
4694 p=(unsigned char *) cache_info->metacontent+offset*
4695 cache_info->metacontent_extent;
4696 for (y=0; y < (ssize_t) rows; y++)
4698 (void) memcpy(q,p,(size_t) length);
4699 p+=cache_info->metacontent_extent*cache_info->columns;
4700 q+=cache_info->metacontent_extent*nexus_info->region.width;
4707 Read meta content from disk.
4709 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4711 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4712 cache_info->cache_filename);
4713 return(MagickFalse);
4715 if ((cache_info->columns == nexus_info->region.width) &&
4716 (extent <= MagickMaxBufferExtent))
4721 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4722 for (y=0; y < (ssize_t) rows; y++)
4724 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4725 cache_info->number_channels*sizeof(Quantum)+offset*
4726 cache_info->metacontent_extent,length,(unsigned char *) q);
4727 if ((MagickSizeType) count != length)
4729 offset+=cache_info->columns;
4730 q+=cache_info->metacontent_extent*nexus_info->region.width;
4732 if (y < (ssize_t) rows)
4734 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4735 cache_info->cache_filename);
4736 return(MagickFalse);
4743 if ((cache_info->debug != MagickFalse) &&
4744 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4745 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4746 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4747 nexus_info->region.width,(double) nexus_info->region.height,(double)
4748 nexus_info->region.x,(double) nexus_info->region.y);
4753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4757 + R e a d P i x e l C a c h e P i x e l s %
4761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4763 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4766 % The format of the ReadPixelCachePixels() method is:
4768 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4769 % NexusInfo *nexus_info,ExceptionInfo *exception)
4771 % A description of each parameter follows:
4773 % o cache_info: the pixel cache.
4775 % o nexus_info: the cache nexus to read the pixels.
4777 % o exception: return any errors or warnings in this structure.
4780 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4781 NexusInfo *nexus_info,ExceptionInfo *exception)
4800 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4802 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4803 nexus_info->region.x;
4804 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4806 rows=nexus_info->region.height;
4808 q=nexus_info->pixels;
4809 switch (cache_info->type)
4818 Read pixels from memory.
4820 if ((cache_info->columns == nexus_info->region.width) &&
4821 (extent == (MagickSizeType) ((size_t) extent)))
4826 p=cache_info->pixels+offset*cache_info->number_channels;
4827 for (y=0; y < (ssize_t) rows; y++)
4829 (void) memcpy(q,p,(size_t) length);
4830 p+=cache_info->number_channels*cache_info->columns;
4831 q+=cache_info->number_channels*nexus_info->region.width;
4838 Read pixels from disk.
4840 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4842 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4843 cache_info->cache_filename);
4844 return(MagickFalse);
4846 if ((cache_info->columns == nexus_info->region.width) &&
4847 (extent <= MagickMaxBufferExtent))
4852 for (y=0; y < (ssize_t) rows; y++)
4854 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4855 cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4856 if ((MagickSizeType) count != length)
4858 offset+=cache_info->columns;
4859 q+=cache_info->number_channels*nexus_info->region.width;
4861 if (y < (ssize_t) rows)
4863 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4864 cache_info->cache_filename);
4865 return(MagickFalse);
4872 if ((cache_info->debug != MagickFalse) &&
4873 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4874 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4875 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4876 nexus_info->region.width,(double) nexus_info->region.height,(double)
4877 nexus_info->region.x,(double) nexus_info->region.y);
4882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4886 + R e f e r e n c e P i x e l C a c h e %
4890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4892 % ReferencePixelCache() increments the reference count associated with the
4893 % pixel cache returning a pointer to the cache.
4895 % The format of the ReferencePixelCache method is:
4897 % Cache ReferencePixelCache(Cache cache_info)
4899 % A description of each parameter follows:
4901 % o cache_info: the pixel cache.
4904 MagickPrivate Cache ReferencePixelCache(Cache cache)
4909 assert(cache != (Cache *) NULL);
4910 cache_info=(CacheInfo *) cache;
4911 assert(cache_info->signature == MagickSignature);
4912 LockSemaphoreInfo(cache_info->semaphore);
4913 cache_info->reference_count++;
4914 UnlockSemaphoreInfo(cache_info->semaphore);
4919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4923 + S e t P i x e l C a c h e M e t h o d s %
4927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4929 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4931 % The format of the SetPixelCacheMethods() method is:
4933 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4935 % A description of each parameter follows:
4937 % o cache: the pixel cache.
4939 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4942 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4947 GetOneAuthenticPixelFromHandler
4948 get_one_authentic_pixel_from_handler;
4950 GetOneVirtualPixelFromHandler
4951 get_one_virtual_pixel_from_handler;
4954 Set cache pixel methods.
4956 assert(cache != (Cache) NULL);
4957 assert(cache_methods != (CacheMethods *) NULL);
4958 cache_info=(CacheInfo *) cache;
4959 assert(cache_info->signature == MagickSignature);
4960 if (cache_info->debug != MagickFalse)
4961 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4962 cache_info->filename);
4963 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4964 cache_info->methods.get_virtual_pixel_handler=
4965 cache_methods->get_virtual_pixel_handler;
4966 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4967 cache_info->methods.destroy_pixel_handler=
4968 cache_methods->destroy_pixel_handler;
4969 if (cache_methods->get_virtual_metacontent_from_handler !=
4970 (GetVirtualMetacontentFromHandler) NULL)
4971 cache_info->methods.get_virtual_metacontent_from_handler=
4972 cache_methods->get_virtual_metacontent_from_handler;
4973 if (cache_methods->get_authentic_pixels_handler !=
4974 (GetAuthenticPixelsHandler) NULL)
4975 cache_info->methods.get_authentic_pixels_handler=
4976 cache_methods->get_authentic_pixels_handler;
4977 if (cache_methods->queue_authentic_pixels_handler !=
4978 (QueueAuthenticPixelsHandler) NULL)
4979 cache_info->methods.queue_authentic_pixels_handler=
4980 cache_methods->queue_authentic_pixels_handler;
4981 if (cache_methods->sync_authentic_pixels_handler !=
4982 (SyncAuthenticPixelsHandler) NULL)
4983 cache_info->methods.sync_authentic_pixels_handler=
4984 cache_methods->sync_authentic_pixels_handler;
4985 if (cache_methods->get_authentic_pixels_from_handler !=
4986 (GetAuthenticPixelsFromHandler) NULL)
4987 cache_info->methods.get_authentic_pixels_from_handler=
4988 cache_methods->get_authentic_pixels_from_handler;
4989 if (cache_methods->get_authentic_metacontent_from_handler !=
4990 (GetAuthenticMetacontentFromHandler) NULL)
4991 cache_info->methods.get_authentic_metacontent_from_handler=
4992 cache_methods->get_authentic_metacontent_from_handler;
4993 get_one_virtual_pixel_from_handler=
4994 cache_info->methods.get_one_virtual_pixel_from_handler;
4995 if (get_one_virtual_pixel_from_handler !=
4996 (GetOneVirtualPixelFromHandler) NULL)
4997 cache_info->methods.get_one_virtual_pixel_from_handler=
4998 cache_methods->get_one_virtual_pixel_from_handler;
4999 get_one_authentic_pixel_from_handler=
5000 cache_methods->get_one_authentic_pixel_from_handler;
5001 if (get_one_authentic_pixel_from_handler !=
5002 (GetOneAuthenticPixelFromHandler) NULL)
5003 cache_info->methods.get_one_authentic_pixel_from_handler=
5004 cache_methods->get_one_authentic_pixel_from_handler;
5008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5012 + S e t P i x e l C a c h e N e x u s P i x e l s %
5016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5018 % SetPixelCacheNexusPixels() defines the region of the cache for the
5019 % specified cache nexus.
5021 % The format of the SetPixelCacheNexusPixels() method is:
5023 % Quantum SetPixelCacheNexusPixels(const Image *image,
5024 % const RectangleInfo *region,NexusInfo *nexus_info,
5025 % ExceptionInfo *exception)
5027 % A description of each parameter follows:
5029 % o image: the image.
5031 % o region: A pointer to the RectangleInfo structure that defines the
5032 % region of this particular cache nexus.
5034 % o nexus_info: the cache nexus to set.
5036 % o exception: return any errors or warnings in this structure.
5040 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
5041 NexusInfo *nexus_info,ExceptionInfo *exception)
5043 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
5044 return(MagickFalse);
5045 nexus_info->mapped=MagickFalse;
5046 nexus_info->cache=(Quantum *) AcquireQuantumMemory(1,(size_t)
5047 nexus_info->length);
5048 if (nexus_info->cache == (Quantum *) NULL)
5050 nexus_info->mapped=MagickTrue;
5051 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
5052 nexus_info->length);
5054 if (nexus_info->cache == (Quantum *) NULL)
5056 (void) ThrowMagickException(exception,GetMagickModule(),
5057 ResourceLimitError,"MemoryAllocationFailed","`%s'",
5058 cache_info->filename);
5059 return(MagickFalse);
5064 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5065 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5077 cache_info=(CacheInfo *) image->cache;
5078 assert(cache_info->signature == MagickSignature);
5079 if (cache_info->type == UndefinedCache)
5080 return((Quantum *) NULL);
5081 nexus_info->region=(*region);
5082 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5083 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5089 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5090 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5091 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5092 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5093 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5094 ((nexus_info->region.width == cache_info->columns) ||
5095 ((nexus_info->region.width % cache_info->columns) == 0)))))
5101 Pixels are accessed directly from memory.
5103 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5104 nexus_info->region.x;
5105 nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5107 nexus_info->metacontent=(void *) NULL;
5108 if (cache_info->metacontent_extent != 0)
5109 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5110 offset*cache_info->metacontent_extent;
5111 return(nexus_info->pixels);
5115 Pixels are stored in a cache region until they are synced to the cache.
5117 number_pixels=(MagickSizeType) nexus_info->region.width*
5118 nexus_info->region.height;
5119 length=number_pixels*cache_info->number_channels*sizeof(Quantum);
5120 if (cache_info->metacontent_extent != 0)
5121 length+=number_pixels*cache_info->metacontent_extent;
5122 if (nexus_info->cache == (Quantum *) NULL)
5124 nexus_info->length=length;
5125 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5126 if (status == MagickFalse)
5128 nexus_info->length=0;
5129 return((Quantum *) NULL);
5133 if (nexus_info->length != length)
5135 RelinquishCacheNexusPixels(nexus_info);
5136 nexus_info->length=length;
5137 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5138 if (status == MagickFalse)
5140 nexus_info->length=0;
5141 return((Quantum *) NULL);
5144 nexus_info->pixels=nexus_info->cache;
5145 nexus_info->metacontent=(void *) NULL;
5146 if (cache_info->metacontent_extent != 0)
5147 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5148 cache_info->number_channels);
5149 return(nexus_info->pixels);
5153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5157 % 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 %
5161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5163 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5164 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5165 % access that is outside the boundaries of the image cache.
5167 % The format of the SetPixelCacheVirtualMethod() method is:
5169 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5170 % const VirtualPixelMethod virtual_pixel_method)
5172 % A description of each parameter follows:
5174 % o image: the image.
5176 % o virtual_pixel_method: choose the type of virtual pixel.
5179 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5180 const VirtualPixelMethod virtual_pixel_method)
5188 assert(image != (Image *) NULL);
5189 assert(image->signature == MagickSignature);
5190 if (image->debug != MagickFalse)
5191 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5192 assert(image->cache != (Cache) NULL);
5193 cache_info=(CacheInfo *) image->cache;
5194 assert(cache_info->signature == MagickSignature);
5195 method=cache_info->virtual_pixel_method;
5196 cache_info->virtual_pixel_method=virtual_pixel_method;
5201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5205 + 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 %
5209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5211 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5212 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5213 % is synced, otherwise MagickFalse.
5215 % The format of the SyncAuthenticPixelCacheNexus() method is:
5217 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5218 % NexusInfo *nexus_info,ExceptionInfo *exception)
5220 % A description of each parameter follows:
5222 % o image: the image.
5224 % o nexus_info: the cache nexus to sync.
5226 % o exception: return any errors or warnings in this structure.
5229 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5230 NexusInfo *nexus_info,ExceptionInfo *exception)
5239 Transfer pixels to the cache.
5241 assert(image != (Image *) NULL);
5242 assert(image->signature == MagickSignature);
5243 if (image->cache == (Cache) NULL)
5244 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5245 cache_info=(CacheInfo *) image->cache;
5246 assert(cache_info->signature == MagickSignature);
5247 if (cache_info->type == UndefinedCache)
5248 return(MagickFalse);
5249 if ((image->clip_mask != (Image *) NULL) &&
5250 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5251 return(MagickFalse);
5252 if ((image->mask != (Image *) NULL) &&
5253 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5254 return(MagickFalse);
5255 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5257 assert(cache_info->signature == MagickSignature);
5258 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5259 if ((cache_info->metacontent_extent != 0) &&
5260 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5261 return(MagickFalse);
5266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5270 + S y n c A u t h e n t i c P i x e l C a c h e %
5274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5276 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5277 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5278 % otherwise MagickFalse.
5280 % The format of the SyncAuthenticPixelsCache() method is:
5282 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5283 % ExceptionInfo *exception)
5285 % A description of each parameter follows:
5287 % o image: the image.
5289 % o exception: return any errors or warnings in this structure.
5292 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5293 ExceptionInfo *exception)
5299 id = GetOpenMPThreadId();
5304 assert(image != (Image *) NULL);
5305 assert(image->signature == MagickSignature);
5306 assert(image->cache != (Cache) NULL);
5307 cache_info=(CacheInfo *) image->cache;
5308 assert(cache_info->signature == MagickSignature);
5309 assert(id < (int) cache_info->number_threads);
5310 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5320 % S y n c A u t h e n t i c P i x e l s %
5324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5326 % SyncAuthenticPixels() 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 SyncAuthenticPixels() method is:
5332 % MagickBooleanType SyncAuthenticPixels(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 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5343 ExceptionInfo *exception)
5349 id = GetOpenMPThreadId();
5354 assert(image != (Image *) NULL);
5355 assert(image->signature == MagickSignature);
5356 assert(image->cache != (Cache) NULL);
5357 cache_info=(CacheInfo *) image->cache;
5358 assert(cache_info->signature == MagickSignature);
5359 if (cache_info->methods.sync_authentic_pixels_handler !=
5360 (SyncAuthenticPixelsHandler) NULL)
5362 status=cache_info->methods.sync_authentic_pixels_handler(image,
5366 assert(id < (int) cache_info->number_threads);
5367 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5377 + S y n c I m a g e P i x e l C a c h e %
5381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5383 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5384 % The method returns MagickTrue if the pixel region is flushed, otherwise
5387 % The format of the SyncImagePixelCache() method is:
5389 % MagickBooleanType SyncImagePixelCache(Image *image,
5390 % ExceptionInfo *exception)
5392 % A description of each parameter follows:
5394 % o image: the image.
5396 % o exception: return any errors or warnings in this structure.
5399 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5400 ExceptionInfo *exception)
5405 assert(image != (Image *) NULL);
5406 assert(exception != (ExceptionInfo *) NULL);
5407 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5408 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5416 + 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 %
5420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5422 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5423 % of the pixel cache.
5425 % The format of the WritePixelCacheMetacontent() method is:
5427 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5428 % NexusInfo *nexus_info,ExceptionInfo *exception)
5430 % A description of each parameter follows:
5432 % o cache_info: the pixel cache.
5434 % o nexus_info: the cache nexus to write the meta-content.
5436 % o exception: return any errors or warnings in this structure.
5439 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5440 NexusInfo *nexus_info,ExceptionInfo *exception)
5450 register const unsigned char
5459 if (cache_info->metacontent_extent == 0)
5460 return(MagickFalse);
5461 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5463 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5464 nexus_info->region.x;
5465 length=(MagickSizeType) nexus_info->region.width*
5466 cache_info->metacontent_extent;
5467 rows=nexus_info->region.height;
5468 extent=(MagickSizeType) length*rows;
5469 p=(unsigned char *) nexus_info->metacontent;
5470 switch (cache_info->type)
5475 register unsigned char
5479 Write associated pixels to memory.
5481 if ((cache_info->columns == nexus_info->region.width) &&
5482 (extent == (MagickSizeType) ((size_t) extent)))
5487 q=(unsigned char *) cache_info->metacontent+offset*
5488 cache_info->metacontent_extent;
5489 for (y=0; y < (ssize_t) rows; y++)
5491 (void) memcpy(q,p,(size_t) length);
5492 p+=nexus_info->region.width*cache_info->metacontent_extent;
5493 q+=cache_info->columns*cache_info->metacontent_extent;
5500 Write associated pixels to disk.
5502 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5504 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5505 cache_info->cache_filename);
5506 return(MagickFalse);
5508 if ((cache_info->columns == nexus_info->region.width) &&
5509 (extent <= MagickMaxBufferExtent))
5514 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5515 for (y=0; y < (ssize_t) rows; y++)
5517 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5518 cache_info->number_channels*sizeof(Quantum)+offset*
5519 cache_info->metacontent_extent,length,(const unsigned char *) p);
5520 if ((MagickSizeType) count != length)
5522 p+=nexus_info->region.width*cache_info->metacontent_extent;
5523 offset+=cache_info->columns;
5525 if (y < (ssize_t) rows)
5527 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5528 cache_info->cache_filename);
5529 return(MagickFalse);
5536 if ((cache_info->debug != MagickFalse) &&
5537 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5538 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5539 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5540 nexus_info->region.width,(double) nexus_info->region.height,(double)
5541 nexus_info->region.x,(double) nexus_info->region.y);
5546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5550 + W r i t e C a c h e P i x e l s %
5554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5556 % WritePixelCachePixels() writes image pixels to the specified region of the
5559 % The format of the WritePixelCachePixels() method is:
5561 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5562 % NexusInfo *nexus_info,ExceptionInfo *exception)
5564 % A description of each parameter follows:
5566 % o cache_info: the pixel cache.
5568 % o nexus_info: the cache nexus to write the pixels.
5570 % o exception: return any errors or warnings in this structure.
5573 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5574 NexusInfo *nexus_info,ExceptionInfo *exception)
5584 register const Quantum
5593 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5595 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5596 nexus_info->region.x;
5597 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5599 rows=nexus_info->region.height;
5601 p=nexus_info->pixels;
5602 switch (cache_info->type)
5611 Write pixels to memory.
5613 if ((cache_info->columns == nexus_info->region.width) &&
5614 (extent == (MagickSizeType) ((size_t) extent)))
5619 q=cache_info->pixels+offset*cache_info->number_channels;
5620 for (y=0; y < (ssize_t) rows; y++)
5622 (void) memcpy(q,p,(size_t) length);
5623 p+=nexus_info->region.width*cache_info->number_channels;
5624 q+=cache_info->columns*cache_info->number_channels;
5631 Write pixels to disk.
5633 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5635 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5636 cache_info->cache_filename);
5637 return(MagickFalse);
5639 if ((cache_info->columns == nexus_info->region.width) &&
5640 (extent <= MagickMaxBufferExtent))
5645 for (y=0; y < (ssize_t) rows; y++)
5647 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5648 cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5650 if ((MagickSizeType) count != length)
5652 p+=nexus_info->region.width*cache_info->number_channels;
5653 offset+=cache_info->columns;
5655 if (y < (ssize_t) rows)
5657 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5658 cache_info->cache_filename);
5659 return(MagickFalse);
5666 if ((cache_info->debug != MagickFalse) &&
5667 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5668 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5669 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5670 nexus_info->region.width,(double) nexus_info->region.height,(double)
5671 nexus_info->region.x,(double) nexus_info->region.y);