2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % CCCC AAA CCCC H H EEEEE %
8 % C AAAAA C HHHHH EEE %
10 % CCCC A A CCCC H H EEEEE %
13 % MagickCore Pixel Cache Methods %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/composite-private.h"
50 #include "MagickCore/exception.h"
51 #include "MagickCore/exception-private.h"
52 #include "MagickCore/geometry.h"
53 #include "MagickCore/list.h"
54 #include "MagickCore/log.h"
55 #include "MagickCore/magick.h"
56 #include "MagickCore/memory_.h"
57 #include "MagickCore/pixel.h"
58 #include "MagickCore/pixel-accessor.h"
59 #include "MagickCore/policy.h"
60 #include "MagickCore/quantum.h"
61 #include "MagickCore/random_.h"
62 #include "MagickCore/resource_.h"
63 #include "MagickCore/semaphore.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/string-private.h"
67 #include "MagickCore/thread-private.h"
68 #include "MagickCore/utility.h"
69 #if defined(MAGICKCORE_ZLIB_DELEGATE)
76 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
81 typedef struct _MagickModulo
111 Forward declarations.
113 #if defined(__cplusplus) || defined(c_plusplus)
118 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
119 const ssize_t,const size_t,const size_t,ExceptionInfo *),
120 *GetVirtualPixelsCache(const Image *);
123 *GetVirtualMetacontentFromCache(const Image *);
125 static MagickBooleanType
126 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,
127 PixelPacket *,ExceptionInfo *),
128 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
129 const ssize_t,const ssize_t,PixelPacket *,ExceptionInfo *),
130 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
131 ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
132 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
133 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
134 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
135 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
138 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
139 const size_t,ExceptionInfo *),
140 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
141 const size_t,ExceptionInfo *),
142 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *,
145 #if defined(__cplusplus) || defined(c_plusplus)
152 static volatile MagickBooleanType
153 instantiate_cache = MagickFalse;
156 *cache_semaphore = (SemaphoreInfo *) NULL;
159 *cache_resources = (SplayTreeInfo *) NULL;
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 + A c q u i r e P i x e l C a c h e %
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % AcquirePixelCache() acquires a pixel cache.
174 % The format of the AcquirePixelCache() method is:
176 % Cache AcquirePixelCache(const size_t number_threads)
178 % A description of each parameter follows:
180 % o number_threads: the number of nexus threads.
183 MagickExport Cache AcquirePixelCache(const size_t number_threads)
188 cache_info=(CacheInfo *) AcquireMagickMemory(sizeof(*cache_info));
189 if (cache_info == (CacheInfo *) NULL)
190 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
191 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
192 cache_info->type=UndefinedCache;
193 cache_info->mode=IOMode;
194 cache_info->colorspace=RGBColorspace;
195 cache_info->file=(-1);
196 cache_info->id=GetMagickThreadId();
197 cache_info->number_threads=number_threads;
198 if (number_threads == 0)
199 cache_info->number_threads=GetOpenMPMaximumThreads();
200 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
201 if (cache_info->nexus_info == (NexusInfo **) NULL)
202 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
203 cache_info->semaphore=AllocateSemaphoreInfo();
204 cache_info->reference_count=1;
205 cache_info->disk_semaphore=AllocateSemaphoreInfo();
206 cache_info->debug=IsEventLogging();
207 cache_info->signature=MagickSignature;
208 if ((cache_resources == (SplayTreeInfo *) NULL) &&
209 (instantiate_cache == MagickFalse))
211 if (cache_semaphore == (SemaphoreInfo *) NULL)
212 AcquireSemaphoreInfo(&cache_semaphore);
213 LockSemaphoreInfo(cache_semaphore);
214 if ((cache_resources == (SplayTreeInfo *) NULL) &&
215 (instantiate_cache == MagickFalse))
217 cache_resources=NewSplayTree((int (*)(const void *,const void *))
218 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
219 instantiate_cache=MagickTrue;
221 UnlockSemaphoreInfo(cache_semaphore);
223 (void) AddValueToSplayTree(cache_resources,cache_info,cache_info);
224 return((Cache ) cache_info);
228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 % A c q u i r e P i x e l C a c h e N e x u s %
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 % AcquirePixelCacheNexus() allocates the NexusInfo structure.
240 % The format of the AcquirePixelCacheNexus method is:
242 % NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
244 % A description of each parameter follows:
246 % o number_threads: the number of nexus threads.
249 MagickExport NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
257 nexus_info=(NexusInfo **) AcquireQuantumMemory(number_threads,
258 sizeof(*nexus_info));
259 if (nexus_info == (NexusInfo **) NULL)
260 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
261 for (i=0; i < (ssize_t) number_threads; i++)
263 nexus_info[i]=(NexusInfo *) AcquireAlignedMemory(1,sizeof(**nexus_info));
264 if (nexus_info[i] == (NexusInfo *) NULL)
265 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
266 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
267 nexus_info[i]->signature=MagickSignature;
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277 + A c q u i r e P i x e l C a c h e P i x e l s %
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
283 % AcquirePixelCachePixels() returns the pixels associated with the specified
286 % The format of the AcquirePixelCachePixels() method is:
288 % const void *AcquirePixelCachePixels(const Image *image,
289 % MagickSizeType *length,ExceptionInfo *exception)
291 % A description of each parameter follows:
293 % o image: the image.
295 % o length: the pixel cache length.
297 % o exception: return any errors or warnings in this structure.
300 MagickExport const void *AcquirePixelCachePixels(const Image *image,
301 MagickSizeType *length,ExceptionInfo *exception)
306 assert(image != (const Image *) NULL);
307 assert(image->signature == MagickSignature);
308 assert(exception != (ExceptionInfo *) NULL);
309 assert(exception->signature == MagickSignature);
310 assert(image->cache != (Cache) NULL);
311 cache_info=(CacheInfo *) image->cache;
312 assert(cache_info->signature == MagickSignature);
314 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
315 return((const void *) NULL);
316 *length=cache_info->length;
317 return((const void *) cache_info->pixels);
321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325 + C a c h e C o m p o n e n t G e n e s i s %
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331 % CacheComponentGenesis() instantiates the cache component.
333 % The format of the CacheComponentGenesis method is:
335 % MagickBooleanType CacheComponentGenesis(void)
338 MagickExport MagickBooleanType CacheComponentGenesis(void)
340 AcquireSemaphoreInfo(&cache_semaphore);
345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349 + C a c h e C o m p o n e n t T e r m i n u s %
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355 % CacheComponentTerminus() destroys the cache component.
357 % The format of the CacheComponentTerminus() method is:
359 % CacheComponentTerminus(void)
362 MagickExport void CacheComponentTerminus(void)
364 if (cache_semaphore == (SemaphoreInfo *) NULL)
365 AcquireSemaphoreInfo(&cache_semaphore);
366 LockSemaphoreInfo(cache_semaphore);
367 if (cache_resources != (SplayTreeInfo *) NULL)
368 cache_resources=DestroySplayTree(cache_resources);
369 instantiate_cache=MagickFalse;
370 UnlockSemaphoreInfo(cache_semaphore);
371 DestroySemaphoreInfo(&cache_semaphore);
375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379 + C l i p P i x e l C a c h e N e x u s %
383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 % ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
386 % mask. It returns MagickTrue if the pixel region is clipped, otherwise
389 % The format of the ClipPixelCacheNexus() method is:
391 % MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
392 % ExceptionInfo *exception)
394 % A description of each parameter follows:
396 % o image: the image.
398 % o nexus_info: the cache nexus to clip.
400 % o exception: return any errors or warnings in this structure.
403 static MagickBooleanType ClipPixelCacheNexus(Image *image,
404 NexusInfo *nexus_info,ExceptionInfo *exception)
416 register const Quantum
429 if (image->debug != MagickFalse)
430 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
431 if (image->clip_mask == (Image *) NULL)
433 cache_info=(CacheInfo *) image->cache;
434 if (cache_info == (Cache) NULL)
436 image_nexus=AcquirePixelCacheNexus(1);
437 clip_nexus=AcquirePixelCacheNexus(1);
438 if ((image_nexus == (NexusInfo **) NULL) ||
439 (clip_nexus == (NexusInfo **) NULL))
440 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
441 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
442 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
443 nexus_info->region.height,image_nexus[0],exception);
444 q=nexus_info->pixels;
445 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
446 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
447 nexus_info->region.height,clip_nexus[0],exception);
448 number_pixels=(MagickSizeType) nexus_info->region.width*
449 nexus_info->region.height;
450 for (i=0; i < (ssize_t) number_pixels; i++)
452 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
454 if (GetPixelIntensity(image,r) > ((Quantum) QuantumRange/2))
456 SetPixelRed(image,GetPixelRed(image,p),q);
457 SetPixelGreen(image,GetPixelGreen(image,p),q);
458 SetPixelBlue(image,GetPixelBlue(image,p),q);
459 if (cache_info->colorspace == CMYKColorspace)
460 SetPixelBlack(image,GetPixelBlack(image,p),q);
461 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
463 p+=GetPixelChannels(image);
464 q+=GetPixelChannels(image);
465 r+=GetPixelChannels(image->clip_mask);
467 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
468 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
469 if (i < (ssize_t) number_pixels)
475 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
479 + C l o n e P i x e l C a c h e %
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 % ClonePixelCache() clones a pixel cache.
487 % The format of the ClonePixelCache() method is:
489 % Cache ClonePixelCache(const Cache cache)
491 % A description of each parameter follows:
493 % o cache: the pixel cache.
496 MagickExport Cache ClonePixelCache(const Cache cache)
504 assert(cache != (const Cache) NULL);
505 cache_info=(const CacheInfo *) cache;
506 assert(cache_info->signature == MagickSignature);
507 if (cache_info->debug != MagickFalse)
508 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
509 cache_info->filename);
510 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
511 if (clone_info == (Cache) NULL)
512 return((Cache) NULL);
513 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
514 return((Cache ) clone_info);
518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522 + C l o n e P i x e l C a c h e P i x e l s %
526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
527 % ClonePixelCachePixels() clones the source pixel cache to the destination
530 % The format of the ClonePixelCachePixels() method is:
532 % MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
533 % CacheInfo *source_info,ExceptionInfo *exception)
535 % A description of each parameter follows:
537 % o cache_info: the pixel cache.
539 % o source_info: the source pixel cache.
541 % o exception: return any errors or warnings in this structure.
545 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
551 LockSemaphoreInfo(cache_info->disk_semaphore);
552 if (cache_info->file != -1)
554 status=close(cache_info->file);
555 cache_info->file=(-1);
556 RelinquishMagickResource(FileResource,1);
558 UnlockSemaphoreInfo(cache_info->disk_semaphore);
559 return(status == -1 ? MagickFalse : MagickTrue);
562 static void LimitPixelCacheDescriptors(void)
569 Limit # of open file descriptors.
571 if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
573 LockSemaphoreInfo(cache_semaphore);
574 if (cache_resources == (SplayTreeInfo *) NULL)
576 UnlockSemaphoreInfo(cache_semaphore);
579 ResetSplayTreeIterator(cache_resources);
580 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
581 while (p != (CacheInfo *) NULL)
583 if ((p->type == DiskCache) && (p->file != -1))
585 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
587 for (q=p; p != (CacheInfo *) NULL; )
589 if ((p->type == DiskCache) && (p->file != -1) &&
590 (p->timestamp < q->timestamp))
592 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
594 if (q != (CacheInfo *) NULL)
597 Close least recently used cache.
599 (void) close(q->file);
602 UnlockSemaphoreInfo(cache_semaphore);
605 static inline MagickSizeType MagickMax(const MagickSizeType x,
606 const MagickSizeType y)
613 static inline MagickSizeType MagickMin(const MagickSizeType x,
614 const MagickSizeType y)
621 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
628 Open pixel cache on disk.
630 LockSemaphoreInfo(cache_info->disk_semaphore);
631 if (cache_info->file != -1)
633 UnlockSemaphoreInfo(cache_info->disk_semaphore);
634 return(MagickTrue); /* cache already open */
636 LimitPixelCacheDescriptors();
637 if (*cache_info->cache_filename == '\0')
638 file=AcquireUniqueFileResource(cache_info->cache_filename);
644 file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
649 file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
652 file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
658 file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
661 file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
667 UnlockSemaphoreInfo(cache_info->disk_semaphore);
670 (void) AcquireMagickResource(FileResource,1);
671 cache_info->file=file;
672 cache_info->timestamp=time(0);
673 UnlockSemaphoreInfo(cache_info->disk_semaphore);
677 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
678 const MagickOffsetType offset,const MagickSizeType length,
679 unsigned char *restrict buffer)
681 register MagickOffsetType
687 cache_info->timestamp=time(0);
688 #if !defined(MAGICKCORE_HAVE_PREAD)
689 LockSemaphoreInfo(cache_info->disk_semaphore);
690 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
692 UnlockSemaphoreInfo(cache_info->disk_semaphore);
693 return((MagickOffsetType) -1);
697 for (i=0; i < (MagickOffsetType) length; i+=count)
699 #if !defined(MAGICKCORE_HAVE_PREAD)
700 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
701 (MagickSizeType) SSIZE_MAX));
703 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
704 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
715 #if !defined(MAGICKCORE_HAVE_PREAD)
716 UnlockSemaphoreInfo(cache_info->disk_semaphore);
721 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
722 const MagickOffsetType offset,const MagickSizeType length,
723 const unsigned char *restrict buffer)
725 register MagickOffsetType
731 cache_info->timestamp=time(0);
732 #if !defined(MAGICKCORE_HAVE_PWRITE)
733 LockSemaphoreInfo(cache_info->disk_semaphore);
734 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
736 UnlockSemaphoreInfo(cache_info->disk_semaphore);
737 return((MagickOffsetType) -1);
741 for (i=0; i < (MagickOffsetType) length; i+=count)
743 #if !defined(MAGICKCORE_HAVE_PWRITE)
744 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
745 (MagickSizeType) SSIZE_MAX));
747 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
748 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
759 #if !defined(MAGICKCORE_HAVE_PWRITE)
760 UnlockSemaphoreInfo(cache_info->disk_semaphore);
765 static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info,
766 CacheInfo *cache_info,ExceptionInfo *exception)
771 register MagickOffsetType
781 Clone pixel cache (both caches on disk).
783 if (cache_info->debug != MagickFalse)
784 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
785 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
787 if (blob == (unsigned char *) NULL)
789 (void) ThrowMagickException(exception,GetMagickModule(),
790 ResourceLimitError,"MemoryAllocationFailed","`%s'",
791 cache_info->filename);
794 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
796 blob=(unsigned char *) RelinquishMagickMemory(blob);
797 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
798 cache_info->cache_filename);
801 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
803 (void) ClosePixelCacheOnDisk(cache_info);
804 blob=(unsigned char *) RelinquishMagickMemory(blob);
805 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
806 clone_info->cache_filename);
810 for (i=0; i < (MagickOffsetType) cache_info->length; i+=count)
812 count=ReadPixelCacheRegion(cache_info,cache_info->offset+i,
813 MagickMin(cache_info->length-i,(MagickSizeType) MagickMaxBufferExtent),
817 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
818 cache_info->cache_filename);
821 length=(size_t) count;
822 count=WritePixelCacheRegion(clone_info,clone_info->offset+i,length,blob);
823 if ((MagickSizeType) count != length)
825 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
826 clone_info->cache_filename);
830 (void) ClosePixelCacheOnDisk(clone_info);
831 (void) ClosePixelCacheOnDisk(cache_info);
832 blob=(unsigned char *) RelinquishMagickMemory(blob);
833 if (i < (MagickOffsetType) cache_info->length)
838 static MagickBooleanType OptimizedPixelCacheClone(CacheInfo *clone_info,
839 CacheInfo *cache_info,ExceptionInfo *exception)
844 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
847 Clone pixel cache (both caches in memory).
849 if (cache_info->debug != MagickFalse)
850 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
851 (void) memcpy(clone_info->pixels,cache_info->pixels,(size_t)
855 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
858 Clone pixel cache (one cache on disk, one in memory).
860 if (cache_info->debug != MagickFalse)
861 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
862 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
864 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
865 cache_info->cache_filename);
868 count=ReadPixelCacheRegion(cache_info,cache_info->offset,
869 cache_info->length,(unsigned char *) clone_info->pixels);
870 (void) ClosePixelCacheOnDisk(cache_info);
871 if ((MagickSizeType) count != cache_info->length)
873 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
874 cache_info->cache_filename);
879 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
882 Clone pixel cache (one cache on disk, one in memory).
884 if (clone_info->debug != MagickFalse)
885 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
886 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
888 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
889 clone_info->cache_filename);
892 count=WritePixelCacheRegion(clone_info,clone_info->offset,
893 clone_info->length,(unsigned char *) cache_info->pixels);
894 (void) ClosePixelCacheOnDisk(clone_info);
895 if ((MagickSizeType) count != clone_info->length)
897 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
898 clone_info->cache_filename);
904 Clone pixel cache (both caches on disk).
906 return(DiskToDiskPixelCacheClone(clone_info,cache_info,exception));
909 static MagickBooleanType UnoptimizedPixelCacheClone(CacheInfo *clone_info,
910 CacheInfo *cache_info,ExceptionInfo *exception)
933 Clone pixel cache (unoptimized).
935 if (cache_info->debug != MagickFalse)
937 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
938 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
940 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
941 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
943 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
944 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
946 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
948 length=(size_t) MagickMax(MagickMax(cache_info->pixel_channels,
949 clone_info->pixel_channels)*sizeof(Quantum),MagickMax(
950 cache_info->metacontent_extent,clone_info->metacontent_extent));
951 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blob));
952 if (blob == (unsigned char *) NULL)
954 (void) ThrowMagickException(exception,GetMagickModule(),
955 ResourceLimitError,"MemoryAllocationFailed","`%s'",
956 cache_info->filename);
959 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
962 if (cache_info->type == DiskCache)
964 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
966 blob=(unsigned char *) RelinquishMagickMemory(blob);
967 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
968 cache_info->cache_filename);
971 cache_offset=cache_info->offset;
973 if (clone_info->type == DiskCache)
975 if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
977 if (cache_info->type == DiskCache)
978 (void) ClosePixelCacheOnDisk(cache_info);
979 blob=(unsigned char *) RelinquishMagickMemory(blob);
980 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
981 clone_info->cache_filename);
984 clone_offset=clone_info->offset;
987 Clone pixel channels.
990 for (y=0; y < (ssize_t) cache_info->rows; y++)
992 for (x=0; x < (ssize_t) cache_info->columns; x++)
995 Read a set of pixel channels.
997 length=cache_info->pixel_channels*sizeof(Quantum);
998 if (cache_info->type != DiskCache)
999 (void) memcpy(blob,(unsigned char *) cache_info->pixels+cache_offset,
1003 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1004 if ((MagickSizeType) count != length)
1010 cache_offset+=length;
1011 if ((y < (ssize_t) clone_info->rows) &&
1012 (x < (ssize_t) clone_info->columns))
1015 Write a set of pixel channels.
1017 length=clone_info->pixel_channels*sizeof(Quantum);
1018 if (clone_info->type != DiskCache)
1019 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1023 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1025 if ((MagickSizeType) count != length)
1031 clone_offset+=length;
1034 length=clone_info->pixel_channels*sizeof(Quantum);
1035 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1036 for ( ; x < (ssize_t) clone_info->columns; x++)
1039 Set remaining columns with transparent pixel channels.
1041 if (clone_info->type != DiskCache)
1042 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1046 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1047 if ((MagickSizeType) count != length)
1053 clone_offset+=length;
1056 length=clone_info->pixel_channels*sizeof(Quantum);
1057 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1058 for ( ; y < (ssize_t) clone_info->rows; y++)
1061 Set remaining rows with transparent pixels.
1063 for (x=0; x < (ssize_t) clone_info->columns; x++)
1065 if (clone_info->type != DiskCache)
1066 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1070 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1071 if ((MagickSizeType) count != length)
1077 clone_offset+=length;
1080 if ((cache_info->metacontent_extent != 0) &&
1081 (clone_info->metacontent_extent != 0))
1086 for (y=0; y < (ssize_t) cache_info->rows; y++)
1088 for (x=0; x < (ssize_t) cache_info->columns; x++)
1091 Read a set of metacontent.
1093 length=cache_info->metacontent_extent;
1094 if (cache_info->type != DiskCache)
1095 (void) memcpy(blob,(unsigned char *) cache_info->pixels+
1096 cache_offset,length);
1099 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1100 if ((MagickSizeType) count != length)
1106 cache_offset+=length;
1107 if ((y < (ssize_t) clone_info->rows) &&
1108 (x < (ssize_t) clone_info->columns))
1111 Write a set of metacontent.
1113 length=clone_info->metacontent_extent;
1114 if (clone_info->type != DiskCache)
1115 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1119 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1121 if ((MagickSizeType) count != length)
1127 clone_offset+=length;
1130 length=clone_info->metacontent_extent;
1131 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1132 for ( ; x < (ssize_t) clone_info->columns; x++)
1135 Set remaining columns with metacontent.
1137 if (clone_info->type != DiskCache)
1138 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1142 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1144 if ((MagickSizeType) count != length)
1150 clone_offset+=length;
1153 length=clone_info->metacontent_extent;
1154 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1155 for ( ; y < (ssize_t) clone_info->rows; y++)
1158 Set remaining rows with metacontent.
1160 for (x=0; x < (ssize_t) clone_info->columns; x++)
1162 if (clone_info->type != DiskCache)
1163 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1167 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1168 if ((MagickSizeType) count != length)
1174 clone_offset+=length;
1178 if (clone_info->type == DiskCache)
1179 (void) ClosePixelCacheOnDisk(clone_info);
1180 if (cache_info->type == DiskCache)
1181 (void) ClosePixelCacheOnDisk(cache_info);
1182 blob=(unsigned char *) RelinquishMagickMemory(blob);
1186 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1187 CacheInfo *cache_info,ExceptionInfo *exception)
1189 if (cache_info->type == PingCache)
1191 if ((cache_info->columns == clone_info->columns) &&
1192 (cache_info->rows == clone_info->rows) &&
1193 (cache_info->pixel_channels == clone_info->pixel_channels) &&
1194 (cache_info->metacontent_extent == clone_info->metacontent_extent))
1195 return(OptimizedPixelCacheClone(clone_info,cache_info,exception));
1196 return(UnoptimizedPixelCacheClone(clone_info,cache_info,exception));
1200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1204 + C l o n e P i x e l C a c h e M e t h o d s %
1208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1213 % The format of the ClonePixelCacheMethods() method is:
1215 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
1217 % A description of each parameter follows:
1219 % o clone: Specifies a pointer to a Cache structure.
1221 % o cache: the pixel cache.
1224 MagickExport void ClonePixelCacheMethods(Cache clone,const Cache cache)
1230 assert(clone != (Cache) NULL);
1231 source_info=(CacheInfo *) clone;
1232 assert(source_info->signature == MagickSignature);
1233 if (source_info->debug != MagickFalse)
1234 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1235 source_info->filename);
1236 assert(cache != (Cache) NULL);
1237 cache_info=(CacheInfo *) cache;
1238 assert(cache_info->signature == MagickSignature);
1239 source_info->methods=cache_info->methods;
1243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1247 + D e s t r o y I m a g e P i x e l C a c h e %
1251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1253 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1255 % The format of the DestroyImagePixelCache() method is:
1257 % void DestroyImagePixelCache(Image *image)
1259 % A description of each parameter follows:
1261 % o image: the image.
1264 static void DestroyImagePixelCache(Image *image)
1266 assert(image != (Image *) NULL);
1267 assert(image->signature == MagickSignature);
1268 if (image->debug != MagickFalse)
1269 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1270 if (image->cache == (void *) NULL)
1272 image->cache=DestroyPixelCache(image->cache);
1276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1280 + D e s t r o y I m a g e P i x e l s %
1284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1286 % DestroyImagePixels() deallocates memory associated with the pixel cache.
1288 % The format of the DestroyImagePixels() method is:
1290 % void DestroyImagePixels(Image *image)
1292 % A description of each parameter follows:
1294 % o image: the image.
1297 MagickExport void DestroyImagePixels(Image *image)
1302 assert(image != (const Image *) NULL);
1303 assert(image->signature == MagickSignature);
1304 if (image->debug != MagickFalse)
1305 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1306 assert(image->cache != (Cache) NULL);
1307 cache_info=(CacheInfo *) image->cache;
1308 assert(cache_info->signature == MagickSignature);
1309 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1311 cache_info->methods.destroy_pixel_handler(image);
1314 image->cache=DestroyPixelCache(image->cache);
1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1322 + D e s t r o y P i x e l C a c h e %
1326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1328 % DestroyPixelCache() deallocates memory associated with the pixel cache.
1330 % The format of the DestroyPixelCache() method is:
1332 % Cache DestroyPixelCache(Cache cache)
1334 % A description of each parameter follows:
1336 % o cache: the pixel cache.
1340 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1342 switch (cache_info->type)
1346 if (cache_info->mapped == MagickFalse)
1347 cache_info->pixels=(Quantum *) RelinquishMagickMemory(
1348 cache_info->pixels);
1350 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,
1351 (size_t) cache_info->length);
1352 RelinquishMagickResource(MemoryResource,cache_info->length);
1357 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t)
1358 cache_info->length);
1359 RelinquishMagickResource(MapResource,cache_info->length);
1363 if (cache_info->file != -1)
1364 (void) ClosePixelCacheOnDisk(cache_info);
1365 RelinquishMagickResource(DiskResource,cache_info->length);
1371 cache_info->type=UndefinedCache;
1372 cache_info->mapped=MagickFalse;
1373 cache_info->metacontent=(void *) NULL;
1376 MagickExport Cache DestroyPixelCache(Cache cache)
1381 assert(cache != (Cache) NULL);
1382 cache_info=(CacheInfo *) cache;
1383 assert(cache_info->signature == MagickSignature);
1384 if (cache_info->debug != MagickFalse)
1385 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1386 cache_info->filename);
1387 LockSemaphoreInfo(cache_info->semaphore);
1388 cache_info->reference_count--;
1389 if (cache_info->reference_count != 0)
1391 UnlockSemaphoreInfo(cache_info->semaphore);
1392 return((Cache) NULL);
1394 UnlockSemaphoreInfo(cache_info->semaphore);
1395 if (cache_resources != (SplayTreeInfo *) NULL)
1396 (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
1397 if (cache_info->debug != MagickFalse)
1400 message[MaxTextExtent];
1402 (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
1403 cache_info->filename);
1404 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1406 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1407 (cache_info->type != DiskCache)))
1408 RelinquishPixelCachePixels(cache_info);
1411 RelinquishPixelCachePixels(cache_info);
1412 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1414 *cache_info->cache_filename='\0';
1415 if (cache_info->nexus_info != (NexusInfo **) NULL)
1416 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1417 cache_info->number_threads);
1418 if (cache_info->random_info != (RandomInfo *) NULL)
1419 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1420 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1421 DestroySemaphoreInfo(&cache_info->disk_semaphore);
1422 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1423 DestroySemaphoreInfo(&cache_info->semaphore);
1424 cache_info->signature=(~MagickSignature);
1425 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
1431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435 + D e s t r o y P i x e l C a c h e N e x u s %
1439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1443 % The format of the DestroyPixelCacheNexus() method is:
1445 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1446 % const size_t number_threads)
1448 % A description of each parameter follows:
1450 % o nexus_info: the nexus to destroy.
1452 % o number_threads: the number of nexus threads.
1456 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1458 if (nexus_info->mapped == MagickFalse)
1459 (void) RelinquishMagickMemory(nexus_info->cache);
1461 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1462 nexus_info->cache=(Quantum *) NULL;
1463 nexus_info->pixels=(Quantum *) NULL;
1464 nexus_info->metacontent=(void *) NULL;
1465 nexus_info->length=0;
1466 nexus_info->mapped=MagickFalse;
1469 MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1470 const size_t number_threads)
1475 assert(nexus_info != (NexusInfo **) NULL);
1476 for (i=0; i < (ssize_t) number_threads; i++)
1478 if (nexus_info[i]->cache != (Quantum *) NULL)
1479 RelinquishCacheNexusPixels(nexus_info[i]);
1480 nexus_info[i]->signature=(~MagickSignature);
1481 nexus_info[i]=(NexusInfo *) RelinquishAlignedMemory(nexus_info[i]);
1483 nexus_info=(NexusInfo **) RelinquishMagickMemory(nexus_info);
1488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492 % G e t A u t h e n t i c M e t a c o n t e n t %
1496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1498 % GetAuthenticMetacontent() returns the authentic metacontent corresponding
1499 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
1500 % returned if the associated pixels are not available.
1502 % The format of the GetAuthenticMetacontent() method is:
1504 % void *GetAuthenticMetacontent(const Image *image)
1506 % A description of each parameter follows:
1508 % o image: the image.
1511 MagickExport void *GetAuthenticMetacontent(const Image *image)
1517 id = GetOpenMPThreadId();
1522 assert(image != (const Image *) NULL);
1523 assert(image->signature == MagickSignature);
1524 assert(image->cache != (Cache) NULL);
1525 cache_info=(CacheInfo *) image->cache;
1526 assert(cache_info->signature == MagickSignature);
1527 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1528 (GetAuthenticMetacontentFromHandler) NULL)
1530 metacontent=cache_info->methods.
1531 get_authentic_metacontent_from_handler(image);
1532 return(metacontent);
1534 assert(id < (int) cache_info->number_threads);
1535 metacontent=GetPixelCacheNexusMetacontent(cache_info,
1536 cache_info->nexus_info[id]);
1537 return(metacontent);
1541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1545 + 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 %
1549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1551 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding
1552 % with the last call to QueueAuthenticPixelsCache() or
1553 % GetAuthenticPixelsCache().
1555 % The format of the GetAuthenticMetacontentFromCache() method is:
1557 % void *GetAuthenticMetacontentFromCache(const Image *image)
1559 % A description of each parameter follows:
1561 % o image: the image.
1564 static void *GetAuthenticMetacontentFromCache(const Image *image)
1570 id = GetOpenMPThreadId();
1575 assert(image != (const Image *) NULL);
1576 assert(image->signature == MagickSignature);
1577 assert(image->cache != (Cache) NULL);
1578 cache_info=(CacheInfo *) image->cache;
1579 assert(cache_info->signature == MagickSignature);
1580 assert(id < (int) cache_info->number_threads);
1581 metacontent=GetPixelCacheNexusMetacontent(image->cache,
1582 cache_info->nexus_info[id]);
1583 return(metacontent);
1587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1591 + 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 %
1595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1598 % disk pixel cache as defined by the geometry parameters. A pointer to the
1599 % pixels is returned if the pixels are transferred, otherwise a NULL is
1602 % The format of the GetAuthenticPixelCacheNexus() method is:
1604 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
1605 % const ssize_t y,const size_t columns,const size_t rows,
1606 % NexusInfo *nexus_info,ExceptionInfo *exception)
1608 % A description of each parameter follows:
1610 % o image: the image.
1612 % o x,y,columns,rows: These values define the perimeter of a region of
1615 % o nexus_info: the cache nexus to return.
1617 % o exception: return any errors or warnings in this structure.
1621 static inline MagickBooleanType IsPixelAuthentic(const CacheInfo *cache_info,
1622 NexusInfo *nexus_info)
1630 if (cache_info->type == PingCache)
1632 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1633 nexus_info->region.x;
1634 status=nexus_info->pixels == (cache_info->pixels+offset*
1635 cache_info->pixel_channels) ? MagickTrue : MagickFalse;
1639 MagickExport Quantum *GetAuthenticPixelCacheNexus(Image *image,
1640 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
1641 NexusInfo *nexus_info,ExceptionInfo *exception)
1650 Transfer pixels from the cache.
1652 assert(image != (Image *) NULL);
1653 assert(image->signature == MagickSignature);
1654 pixels=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
1655 if (pixels == (Quantum *) NULL)
1656 return((Quantum *) NULL);
1657 cache_info=(CacheInfo *) image->cache;
1658 assert(cache_info->signature == MagickSignature);
1659 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
1661 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1662 return((Quantum *) NULL);
1663 if (cache_info->metacontent_extent != 0)
1664 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1665 return((Quantum *) NULL);
1670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1674 + 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 %
1678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1680 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1681 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1683 % The format of the GetAuthenticPixelsFromCache() method is:
1685 % Quantum *GetAuthenticPixelsFromCache(const Image image)
1687 % A description of each parameter follows:
1689 % o image: the image.
1692 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
1698 id = GetOpenMPThreadId();
1700 assert(image != (const Image *) NULL);
1701 assert(image->signature == MagickSignature);
1702 assert(image->cache != (Cache) NULL);
1703 cache_info=(CacheInfo *) image->cache;
1704 assert(cache_info->signature == MagickSignature);
1705 assert(id < (int) cache_info->number_threads);
1706 return(GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]));
1710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1714 % G e t A u t h e n t i c P i x e l Q u e u e %
1718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1720 % GetAuthenticPixelQueue() returns the authentic pixels associated
1721 % corresponding with the last call to QueueAuthenticPixels() or
1722 % GetAuthenticPixels().
1724 % The format of the GetAuthenticPixelQueue() method is:
1726 % Quantum *GetAuthenticPixelQueue(const Image image)
1728 % A description of each parameter follows:
1730 % o image: the image.
1733 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
1739 id = GetOpenMPThreadId();
1741 assert(image != (const Image *) NULL);
1742 assert(image->signature == MagickSignature);
1743 assert(image->cache != (Cache) NULL);
1744 cache_info=(CacheInfo *) image->cache;
1745 assert(cache_info->signature == MagickSignature);
1746 if (cache_info->methods.get_authentic_pixels_from_handler !=
1747 (GetAuthenticPixelsFromHandler) NULL)
1748 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1749 assert(id < (int) cache_info->number_threads);
1750 return(GetPixelCacheNexusPixels(cache_info,cache_info->nexus_info[id]));
1754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1758 % G e t A u t h e n t i c P i x e l s %
1761 % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1764 % region is successfully accessed, a pointer to a Quantum array
1765 % representing the region is returned, otherwise NULL is returned.
1767 % The returned pointer may point to a temporary working copy of the pixels
1768 % or it may point to the original pixels in memory. Performance is maximized
1769 % if the selected region is part of one row, or one or more full rows, since
1770 % then there is opportunity to access the pixels in-place (without a copy)
1771 % if the image is in memory, or in a memory-mapped file. The returned pointer
1772 % must *never* be deallocated by the user.
1774 % Pixels accessed via the returned pointer represent a simple array of type
1775 % Quantum. If the image has corresponding metacontent,call
1776 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
1777 % meta-content corresponding to the region. Once the Quantum array has
1778 % been updated, the changes must be saved back to the underlying image using
1779 % SyncAuthenticPixels() or they may be lost.
1781 % The format of the GetAuthenticPixels() method is:
1783 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1784 % const ssize_t y,const size_t columns,const size_t rows,
1785 % ExceptionInfo *exception)
1787 % A description of each parameter follows:
1789 % o image: the image.
1791 % o x,y,columns,rows: These values define the perimeter of a region of
1794 % o exception: return any errors or warnings in this structure.
1797 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1798 const ssize_t y,const size_t columns,const size_t rows,
1799 ExceptionInfo *exception)
1805 id = GetOpenMPThreadId();
1810 assert(image != (Image *) NULL);
1811 assert(image->signature == MagickSignature);
1812 assert(image->cache != (Cache) NULL);
1813 cache_info=(CacheInfo *) image->cache;
1814 assert(cache_info->signature == MagickSignature);
1815 if (cache_info->methods.get_authentic_pixels_handler !=
1816 (GetAuthenticPixelsHandler) NULL)
1818 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1822 assert(id < (int) cache_info->number_threads);
1823 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1824 cache_info->nexus_info[id],exception);
1829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1833 + G e t A u t h e n t i c P i x e l s C a c h e %
1837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1839 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1840 % as defined by the geometry parameters. A pointer to the pixels is returned
1841 % if the pixels are transferred, otherwise a NULL is returned.
1843 % The format of the GetAuthenticPixelsCache() method is:
1845 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1846 % const ssize_t y,const size_t columns,const size_t rows,
1847 % ExceptionInfo *exception)
1849 % A description of each parameter follows:
1851 % o image: the image.
1853 % o x,y,columns,rows: These values define the perimeter of a region of
1856 % o exception: return any errors or warnings in this structure.
1859 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1860 const ssize_t y,const size_t columns,const size_t rows,
1861 ExceptionInfo *exception)
1867 id = GetOpenMPThreadId();
1872 assert(image != (const Image *) NULL);
1873 assert(image->signature == MagickSignature);
1874 assert(image->cache != (Cache) NULL);
1875 cache_info=(CacheInfo *) image->cache;
1876 if (cache_info == (Cache) NULL)
1877 return((Quantum *) NULL);
1878 assert(cache_info->signature == MagickSignature);
1879 assert(id < (int) cache_info->number_threads);
1880 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1881 cache_info->nexus_info[id],exception);
1886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1890 + G e t I m a g e E x t e n t %
1894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1896 % GetImageExtent() returns the extent of the pixels associated corresponding
1897 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
1899 % The format of the GetImageExtent() method is:
1901 % MagickSizeType GetImageExtent(const Image *image)
1903 % A description of each parameter follows:
1905 % o image: the image.
1908 MagickExport MagickSizeType GetImageExtent(const Image *image)
1914 id = GetOpenMPThreadId();
1916 assert(image != (Image *) NULL);
1917 assert(image->signature == MagickSignature);
1918 if (image->debug != MagickFalse)
1919 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1920 assert(image->cache != (Cache) NULL);
1921 cache_info=(CacheInfo *) image->cache;
1922 assert(cache_info->signature == MagickSignature);
1923 assert(id < (int) cache_info->number_threads);
1924 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
1928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1932 + G e t I m a g e P i x e l C a c h e %
1936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1938 % GetImagePixelCache() ensures that there is only a single reference to the
1939 % pixel cache to be modified, updating the provided cache pointer to point to
1940 % a clone of the original pixel cache if necessary.
1942 % The format of the GetImagePixelCache method is:
1944 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1945 % ExceptionInfo *exception)
1947 % A description of each parameter follows:
1949 % o image: the image.
1951 % o clone: any value other than MagickFalse clones the cache pixels.
1953 % o exception: return any errors or warnings in this structure.
1956 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
1962 Does the image match the pixel cache morphology?
1964 cache_info=(CacheInfo *) image->cache;
1965 if ((image->storage_class != cache_info->storage_class) ||
1966 (image->colorspace != cache_info->colorspace) ||
1967 (image->columns != cache_info->columns) ||
1968 (image->rows != cache_info->rows) ||
1969 (image->pixel_channels != cache_info->pixel_channels) ||
1970 (image->metacontent_extent != cache_info->metacontent_extent) ||
1971 (cache_info->nexus_info == (NexusInfo **) NULL) ||
1972 (cache_info->number_threads < GetOpenMPMaximumThreads()))
1973 return(MagickFalse);
1977 static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1978 ExceptionInfo *exception)
1987 static MagickSizeType
1996 LockSemaphoreInfo(image->semaphore);
1997 if (cpu_throttle == 0)
2003 Set CPU throttle in milleseconds.
2005 cpu_throttle=MagickResourceInfinity;
2006 limit=GetEnvironmentValue("MAGICK_THROTTLE");
2007 if (limit == (char *) NULL)
2008 limit=GetPolicyValue("throttle");
2009 if (limit != (char *) NULL)
2011 cpu_throttle=(MagickSizeType) StringToInteger(limit);
2012 limit=DestroyString(limit);
2015 if ((cpu_throttle != MagickResourceInfinity) && ((cycles++ % 32) == 0))
2016 MagickDelay(cpu_throttle);
2017 if (time_limit == 0)
2020 Set the exire time in seconds.
2022 time_limit=GetMagickResourceLimit(TimeResource);
2023 cache_genesis=time((time_t *) NULL);
2025 if ((time_limit != MagickResourceInfinity) &&
2026 ((MagickSizeType) (time((time_t *) NULL)-cache_genesis) >= time_limit))
2027 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
2028 assert(image->cache != (Cache) NULL);
2029 cache_info=(CacheInfo *) image->cache;
2030 destroy=MagickFalse;
2031 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2033 LockSemaphoreInfo(cache_info->semaphore);
2034 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2045 clone_image=(*image);
2046 clone_image.semaphore=AllocateSemaphoreInfo();
2047 clone_image.reference_count=1;
2048 clone_image.cache=ClonePixelCache(cache_info);
2049 clone_info=(CacheInfo *) clone_image.cache;
2050 status=OpenPixelCache(&clone_image,IOMode,exception);
2051 if (status != MagickFalse)
2053 if (clone != MagickFalse)
2054 status=ClonePixelCachePixels(clone_info,cache_info,exception);
2055 if (status != MagickFalse)
2058 image->cache=clone_image.cache;
2061 DestroySemaphoreInfo(&clone_image.semaphore);
2063 UnlockSemaphoreInfo(cache_info->semaphore);
2065 if (destroy != MagickFalse)
2066 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
2067 if (status != MagickFalse)
2070 Ensure the image matches the pixel cache morphology.
2072 image->taint=MagickTrue;
2073 image->type=UndefinedType;
2074 if (image->colorspace == GRAYColorspace)
2075 image->colorspace=RGBColorspace;
2076 if (ValidatePixelCacheMorphology(image) == MagickFalse)
2077 status=OpenPixelCache(image,IOMode,exception);
2079 UnlockSemaphoreInfo(image->semaphore);
2080 if (status == MagickFalse)
2081 return((Cache) NULL);
2082 return(image->cache);
2086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2090 % G e t O n e A u t h e n t i c P i x e l %
2094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2096 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2097 % location. The image background color is returned if an error occurs.
2099 % The format of the GetOneAuthenticPixel() method is:
2101 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
2102 % const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2104 % A description of each parameter follows:
2106 % o image: the image.
2108 % o x,y: These values define the location of the pixel to return.
2110 % o pixel: return a pixel at the specified (x,y) location.
2112 % o exception: return any errors or warnings in this structure.
2115 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2116 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2124 assert(image != (Image *) NULL);
2125 assert(image->signature == MagickSignature);
2126 assert(image->cache != (Cache) NULL);
2127 cache_info=(CacheInfo *) image->cache;
2128 assert(cache_info->signature == MagickSignature);
2129 *pixel=image->background_color;
2130 if (cache_info->methods.get_one_authentic_pixel_from_handler !=
2131 (GetOneAuthenticPixelFromHandler) NULL)
2132 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2134 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2135 if (q == (Quantum *) NULL)
2136 return(MagickFalse);
2137 GetPixelPacket(image,q,pixel);
2142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2146 + 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 %
2150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2152 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2153 % location. The image background color is returned if an error occurs.
2155 % The format of the GetOneAuthenticPixelFromCache() method is:
2157 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2158 % const ssize_t x,const ssize_t y,PixelPacket *pixel,
2159 % ExceptionInfo *exception)
2161 % A description of each parameter follows:
2163 % o image: the image.
2165 % o x,y: These values define the location of the pixel to return.
2167 % o pixel: return a pixel at the specified (x,y) location.
2169 % o exception: return any errors or warnings in this structure.
2172 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2173 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2179 id = GetOpenMPThreadId();
2184 assert(image != (const Image *) NULL);
2185 assert(image->signature == MagickSignature);
2186 assert(image->cache != (Cache) NULL);
2187 cache_info=(CacheInfo *) image->cache;
2188 assert(cache_info->signature == MagickSignature);
2189 assert(id < (int) cache_info->number_threads);
2190 *pixel=image->background_color;
2191 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
2193 if (q == (Quantum *) NULL)
2194 return(MagickFalse);
2195 GetPixelPacket(image,q,pixel);
2200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2204 % G e t O n e V i r t u a l M a g i c k P i x e l %
2208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2210 % GetOneVirtualMagickPixel() returns a single pixel at the specified (x,y)
2211 % location. The image background color is returned if an error occurs. If
2212 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2214 % The format of the GetOneVirtualMagickPixel() method is:
2216 % MagickBooleanType GetOneVirtualMagickPixel(const Image image,
2217 % const ssize_t x,const ssize_t y,PixelInfo *pixel,
2218 % ExceptionInfo exception)
2220 % A description of each parameter follows:
2222 % o image: the image.
2224 % o x,y: these values define the location of the pixel to return.
2226 % o pixel: return a pixel at the specified (x,y) location.
2228 % o exception: return any errors or warnings in this structure.
2231 MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
2232 const ssize_t x,const ssize_t y,PixelInfo *pixel,
2233 ExceptionInfo *exception)
2239 id = GetOpenMPThreadId();
2241 register const Quantum
2244 assert(image != (const Image *) NULL);
2245 assert(image->signature == MagickSignature);
2246 assert(image->cache != (Cache) NULL);
2247 cache_info=(CacheInfo *) image->cache;
2248 assert(cache_info->signature == MagickSignature);
2249 assert(id < (int) cache_info->number_threads);
2250 pixels=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2251 1UL,1UL,cache_info->nexus_info[id],exception);
2252 GetPixelInfo(image,pixel);
2253 if (pixels == (const Quantum *) NULL)
2254 return(MagickFalse);
2255 SetPixelInfo(image,pixels,pixel);
2260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264 % G e t O n e V i r t u a l M e t h o d P i x e l %
2268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2270 % GetOneVirtualMethodPixel() returns a single pixel at the specified (x,y)
2271 % location as defined by specified pixel method. The image background color
2272 % is returned if an error occurs. If you plan to modify the pixel, use
2273 % GetOneAuthenticPixel() instead.
2275 % The format of the GetOneVirtualMethodPixel() method is:
2277 % MagickBooleanType GetOneVirtualMethodPixel(const Image image,
2278 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2279 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2281 % A description of each parameter follows:
2283 % o image: the image.
2285 % o virtual_pixel_method: the virtual pixel method.
2287 % o x,y: These values define the location of the pixel to return.
2289 % o pixel: return a pixel at the specified (x,y) location.
2291 % o exception: return any errors or warnings in this structure.
2294 MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
2295 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2296 PixelPacket *pixel,ExceptionInfo *exception)
2302 id = GetOpenMPThreadId();
2307 assert(image != (const Image *) NULL);
2308 assert(image->signature == MagickSignature);
2309 assert(image->cache != (Cache) NULL);
2310 cache_info=(CacheInfo *) image->cache;
2311 assert(cache_info->signature == MagickSignature);
2312 *pixel=image->background_color;
2313 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2314 (GetOneVirtualPixelFromHandler) NULL)
2315 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2316 virtual_pixel_method,x,y,pixel,exception));
2317 assert(id < (int) cache_info->number_threads);
2318 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2319 cache_info->nexus_info[id],exception);
2320 if (p == (const Quantum *) NULL)
2321 return(MagickFalse);
2322 GetPixelPacket(image,p,pixel);
2323 if (image->colorspace == CMYKColorspace)
2324 pixel->black=GetPixelBlack(image,p);
2329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2333 % G e t O n e V i r t u a l P i x e l %
2337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2339 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2340 % (x,y) location. The image background color is returned if an error occurs.
2341 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2343 % The format of the GetOneVirtualPixel() method is:
2345 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
2346 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2348 % A description of each parameter follows:
2350 % o image: the image.
2352 % o x,y: These values define the location of the pixel to return.
2354 % o pixel: return a pixel at the specified (x,y) location.
2356 % o exception: return any errors or warnings in this structure.
2359 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2360 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2366 id = GetOpenMPThreadId();
2371 assert(image != (const Image *) NULL);
2372 assert(image->signature == MagickSignature);
2373 assert(image->cache != (Cache) NULL);
2374 cache_info=(CacheInfo *) image->cache;
2375 assert(cache_info->signature == MagickSignature);
2376 *pixel=image->background_color;
2377 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2378 (GetOneVirtualPixelFromHandler) NULL)
2379 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2380 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2381 assert(id < (int) cache_info->number_threads);
2382 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2383 1UL,1UL,cache_info->nexus_info[id],exception);
2384 if (p == (const Quantum *) NULL)
2385 return(MagickFalse);
2386 GetPixelPacket(image,p,pixel);
2387 if (image->colorspace == CMYKColorspace)
2388 pixel->black=GetPixelBlack(image,p);
2393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2397 + 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 %
2401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2403 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2404 % specified (x,y) location. The image background color is returned if an
2407 % The format of the GetOneVirtualPixelFromCache() method is:
2409 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2410 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2411 % PixelPacket *pixel,ExceptionInfo *exception)
2413 % A description of each parameter follows:
2415 % o image: the image.
2417 % o virtual_pixel_method: the virtual pixel method.
2419 % o x,y: These values define the location of the pixel to return.
2421 % o pixel: return a pixel at the specified (x,y) location.
2423 % o exception: return any errors or warnings in this structure.
2426 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2427 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2428 PixelPacket *pixel,ExceptionInfo *exception)
2434 id = GetOpenMPThreadId();
2439 assert(image != (const Image *) NULL);
2440 assert(image->signature == MagickSignature);
2441 assert(image->cache != (Cache) NULL);
2442 cache_info=(CacheInfo *) image->cache;
2443 assert(cache_info->signature == MagickSignature);
2444 assert(id < (int) cache_info->number_threads);
2445 *pixel=image->background_color;
2446 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2447 cache_info->nexus_info[id],exception);
2448 if (p == (const Quantum *) NULL)
2449 return(MagickFalse);
2450 GetPixelPacket(image,p,pixel);
2451 if (image->colorspace == CMYKColorspace)
2452 pixel->black=GetPixelBlack(image,p);
2457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2461 + G e t P i x e l C a c h e C o l o r s p a c e %
2465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2467 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2469 % The format of the GetPixelCacheColorspace() method is:
2471 % Colorspace GetPixelCacheColorspace(Cache cache)
2473 % A description of each parameter follows:
2475 % o cache: the pixel cache.
2478 MagickExport ColorspaceType GetPixelCacheColorspace(const Cache cache)
2483 assert(cache != (Cache) NULL);
2484 cache_info=(CacheInfo *) cache;
2485 assert(cache_info->signature == MagickSignature);
2486 if (cache_info->debug != MagickFalse)
2487 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2488 cache_info->filename);
2489 return(cache_info->colorspace);
2493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2497 + G e t P i x e l C a c h e M e t h o d s %
2501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2503 % GetPixelCacheMethods() initializes the CacheMethods structure.
2505 % The format of the GetPixelCacheMethods() method is:
2507 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2509 % A description of each parameter follows:
2511 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2514 MagickExport void GetPixelCacheMethods(CacheMethods *cache_methods)
2516 assert(cache_methods != (CacheMethods *) NULL);
2517 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2518 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2519 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2520 cache_methods->get_virtual_metacontent_from_handler=
2521 GetVirtualMetacontentFromCache;
2522 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2523 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2524 cache_methods->get_authentic_metacontent_from_handler=
2525 GetAuthenticMetacontentFromCache;
2526 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2527 cache_methods->get_one_authentic_pixel_from_handler=
2528 GetOneAuthenticPixelFromCache;
2529 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2530 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2531 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2539 + G e t P i x e l C a c h e N e x u s E x t e n t %
2543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2545 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2546 % corresponding with the last call to SetPixelCacheNexusPixels() or
2547 % GetPixelCacheNexusPixels().
2549 % The format of the GetPixelCacheNexusExtent() method is:
2551 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2552 % NexusInfo *nexus_info)
2554 % A description of each parameter follows:
2556 % o nexus_info: the nexus info.
2559 MagickExport MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2560 NexusInfo *nexus_info)
2568 assert(cache != (const Cache) NULL);
2569 cache_info=(CacheInfo *) cache;
2570 assert(cache_info->signature == MagickSignature);
2571 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2573 return((MagickSizeType) cache_info->columns*cache_info->rows);
2578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2582 + 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 %
2586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2588 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2591 % The format of the GetPixelCacheNexusMetacontent() method is:
2593 % void *GetPixelCacheNexusMetacontent(const Cache cache,
2594 % NexusInfo *nexus_info)
2596 % A description of each parameter follows:
2598 % o cache: the pixel cache.
2600 % o nexus_info: the cache nexus to return the meta-content.
2603 MagickExport void *GetPixelCacheNexusMetacontent(const Cache cache,
2604 NexusInfo *nexus_info)
2609 assert(cache != (const Cache) NULL);
2610 cache_info=(CacheInfo *) cache;
2611 assert(cache_info->signature == MagickSignature);
2612 if (cache_info->storage_class == UndefinedClass)
2613 return((void *) NULL);
2614 return(nexus_info->metacontent);
2618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2622 + G e t P i x e l C a c h e N e x u s P i x e l s %
2626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2628 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2631 % The format of the GetPixelCacheNexusPixels() method is:
2633 % Quantum *GetPixelCacheNexusPixels(const Cache cache,
2634 % NexusInfo *nexus_info)
2636 % A description of each parameter follows:
2638 % o cache: the pixel cache.
2640 % o nexus_info: the cache nexus to return the pixels.
2643 MagickExport Quantum *GetPixelCacheNexusPixels(const Cache cache,
2644 NexusInfo *nexus_info)
2649 assert(cache != (const Cache) NULL);
2650 cache_info=(CacheInfo *) cache;
2651 assert(cache_info->signature == MagickSignature);
2652 if (cache_info->storage_class == UndefinedClass)
2653 return((Quantum *) NULL);
2654 return(nexus_info->pixels);
2658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2662 + G e t P i x e l C a c h e P i x e l s %
2666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2668 % GetPixelCachePixels() returns the pixels associated with the specified image.
2670 % The format of the GetPixelCachePixels() method is:
2672 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2673 % ExceptionInfo *exception)
2675 % A description of each parameter follows:
2677 % o image: the image.
2679 % o length: the pixel cache length.
2681 % o exception: return any errors or warnings in this structure.
2684 MagickExport void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2685 ExceptionInfo *exception)
2690 assert(image != (const Image *) NULL);
2691 assert(image->signature == MagickSignature);
2692 assert(image->cache != (Cache) NULL);
2693 assert(length != (MagickSizeType *) NULL);
2694 assert(exception != (ExceptionInfo *) NULL);
2695 assert(exception->signature == MagickSignature);
2696 cache_info=(CacheInfo *) image->cache;
2697 assert(cache_info->signature == MagickSignature);
2699 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2700 return((void *) NULL);
2701 *length=cache_info->length;
2702 return((void *) cache_info->pixels);
2706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2710 + 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 %
2714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2716 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2718 % The format of the GetPixelCacheStorageClass() method is:
2720 % ClassType GetPixelCacheStorageClass(Cache cache)
2722 % A description of each parameter follows:
2724 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2726 % o cache: the pixel cache.
2729 MagickExport ClassType GetPixelCacheStorageClass(const Cache cache)
2734 assert(cache != (Cache) NULL);
2735 cache_info=(CacheInfo *) cache;
2736 assert(cache_info->signature == MagickSignature);
2737 if (cache_info->debug != MagickFalse)
2738 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2739 cache_info->filename);
2740 return(cache_info->storage_class);
2744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2748 + G e t P i x e l C a c h e T i l e S i z e %
2752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2754 % GetPixelCacheTileSize() returns the pixel cache tile size.
2756 % The format of the GetPixelCacheTileSize() method is:
2758 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2761 % A description of each parameter follows:
2763 % o image: the image.
2765 % o width: the optimize cache tile width in pixels.
2767 % o height: the optimize cache tile height in pixels.
2770 MagickExport void GetPixelCacheTileSize(const Image *image,size_t *width,
2776 assert(image != (Image *) NULL);
2777 assert(image->signature == MagickSignature);
2778 if (image->debug != MagickFalse)
2779 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2780 cache_info=(CacheInfo *) image->cache;
2781 assert(cache_info->signature == MagickSignature);
2782 *width=2048UL/(cache_info->pixel_channels*sizeof(Quantum));
2783 if (GetPixelCacheType(image) == DiskCache)
2784 *width=8192UL/(cache_info->pixel_channels*sizeof(Quantum));
2789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2793 + G e t P i x e l C a c h e T y p e %
2797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2799 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2801 % The format of the GetPixelCacheType() method is:
2803 % CacheType GetPixelCacheType(const Image *image)
2805 % A description of each parameter follows:
2807 % o image: the image.
2810 MagickExport CacheType GetPixelCacheType(const Image *image)
2815 assert(image != (Image *) NULL);
2816 assert(image->signature == MagickSignature);
2817 assert(image->cache != (Cache) NULL);
2818 cache_info=(CacheInfo *) image->cache;
2819 assert(cache_info->signature == MagickSignature);
2820 return(cache_info->type);
2824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2828 + 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 %
2832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2834 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2835 % pixel cache. A virtual pixel is any pixel access that is outside the
2836 % boundaries of the image cache.
2838 % The format of the GetPixelCacheVirtualMethod() method is:
2840 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2842 % A description of each parameter follows:
2844 % o image: the image.
2847 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2852 assert(image != (Image *) NULL);
2853 assert(image->signature == MagickSignature);
2854 assert(image->cache != (Cache) NULL);
2855 cache_info=(CacheInfo *) image->cache;
2856 assert(cache_info->signature == MagickSignature);
2857 return(cache_info->virtual_pixel_method);
2861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2865 + 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 %
2869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2871 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2872 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2874 % The format of the GetVirtualMetacontentFromCache() method is:
2876 % void *GetVirtualMetacontentFromCache(const Image *image)
2878 % A description of each parameter follows:
2880 % o image: the image.
2883 static const void *GetVirtualMetacontentFromCache(const Image *image)
2889 id = GetOpenMPThreadId();
2894 assert(image != (const Image *) NULL);
2895 assert(image->signature == MagickSignature);
2896 assert(image->cache != (Cache) NULL);
2897 cache_info=(CacheInfo *) image->cache;
2898 assert(cache_info->signature == MagickSignature);
2899 assert(id < (int) cache_info->number_threads);
2900 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2901 cache_info->nexus_info[id]);
2902 return(metacontent);
2906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2910 + 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 %
2914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2916 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2919 % The format of the GetVirtualMetacontentFromNexus() method is:
2921 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2922 % NexusInfo *nexus_info)
2924 % A description of each parameter follows:
2926 % o cache: the pixel cache.
2928 % o nexus_info: the cache nexus to return the meta-content.
2931 MagickExport const void *GetVirtualMetacontentFromNexus(
2932 const Cache cache,NexusInfo *nexus_info)
2937 assert(cache != (Cache) NULL);
2938 cache_info=(CacheInfo *) cache;
2939 assert(cache_info->signature == MagickSignature);
2940 if (cache_info->storage_class == UndefinedClass)
2941 return((void *) NULL);
2942 return(nexus_info->metacontent);
2946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2950 % G e t V i r t u a l M e t a c o n t e n t %
2954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2956 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
2957 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
2958 % returned if the meta-content are not available.
2960 % The format of the GetVirtualMetacontent() method is:
2962 % const void *GetVirtualMetacontent(const Image *image)
2964 % A description of each parameter follows:
2966 % o image: the image.
2969 MagickExport const void *GetVirtualMetacontent(const Image *image)
2975 id = GetOpenMPThreadId();
2980 assert(image != (const Image *) NULL);
2981 assert(image->signature == MagickSignature);
2982 assert(image->cache != (Cache) NULL);
2983 cache_info=(CacheInfo *) image->cache;
2984 assert(cache_info->signature == MagickSignature);
2985 if (cache_info->methods.get_virtual_metacontent_from_handler !=
2986 (GetVirtualMetacontentFromHandler) NULL)
2988 metacontent=cache_info->methods.
2989 get_virtual_metacontent_from_handler(image);
2990 return(metacontent);
2992 assert(id < (int) cache_info->number_threads);
2993 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2994 cache_info->nexus_info[id]);
2995 return(metacontent);
2999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3003 + 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 %
3007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3009 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
3010 % pixel cache as defined by the geometry parameters. A pointer to the pixels
3011 % is returned if the pixels are transferred, otherwise a NULL is returned.
3013 % The format of the GetVirtualPixelsFromNexus() method is:
3015 % Quantum *GetVirtualPixelsFromNexus(const Image *image,
3016 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
3017 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
3018 % ExceptionInfo *exception)
3020 % A description of each parameter follows:
3022 % o image: the image.
3024 % o virtual_pixel_method: the virtual pixel method.
3026 % o x,y,columns,rows: These values define the perimeter of a region of
3029 % o nexus_info: the cache nexus to acquire.
3031 % o exception: return any errors or warnings in this structure.
3038 0, 48, 12, 60, 3, 51, 15, 63,
3039 32, 16, 44, 28, 35, 19, 47, 31,
3040 8, 56, 4, 52, 11, 59, 7, 55,
3041 40, 24, 36, 20, 43, 27, 39, 23,
3042 2, 50, 14, 62, 1, 49, 13, 61,
3043 34, 18, 46, 30, 33, 17, 45, 29,
3044 10, 58, 6, 54, 9, 57, 5, 53,
3045 42, 26, 38, 22, 41, 25, 37, 21
3048 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
3053 index=x+DitherMatrix[x & 0x07]-32L;
3056 if (index >= (ssize_t) columns)
3057 return((ssize_t) columns-1L);
3061 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
3066 index=y+DitherMatrix[y & 0x07]-32L;
3069 if (index >= (ssize_t) rows)
3070 return((ssize_t) rows-1L);
3074 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
3078 if (x >= (ssize_t) columns)
3079 return((ssize_t) (columns-1));
3083 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
3087 if (y >= (ssize_t) rows)
3088 return((ssize_t) (rows-1));
3092 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
3094 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
3097 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
3099 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
3103 VirtualPixelModulo() computes the remainder of dividing offset by extent. It
3104 returns not only the quotient (tile the offset falls in) but also the positive
3105 remainer within that tile such that 0 <= remainder < extent. This method is
3106 essentially a ldiv() using a floored modulo division rather than the normal
3107 default truncated modulo division.
3109 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
3110 const size_t extent)
3115 modulo.quotient=offset/(ssize_t) extent;
3118 modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
3122 MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
3123 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3124 const size_t columns,const size_t rows,NexusInfo *nexus_info,
3125 ExceptionInfo *exception)
3147 register const Quantum
3160 register unsigned char
3164 *virtual_associated_pixel;
3169 assert(image != (const Image *) NULL);
3170 assert(image->signature == MagickSignature);
3171 assert(image->cache != (Cache) NULL);
3172 cache_info=(CacheInfo *) image->cache;
3173 assert(cache_info->signature == MagickSignature);
3174 if (cache_info->type == UndefinedCache)
3175 return((const Quantum *) NULL);
3178 region.width=columns;
3180 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3181 if (pixels == (Quantum *) NULL)
3182 return((const Quantum *) NULL);
3183 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3184 nexus_info->region.x;
3185 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3186 nexus_info->region.width-1L;
3187 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3188 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3189 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3190 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3196 Pixel request is inside cache extents.
3198 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3200 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3201 if (status == MagickFalse)
3202 return((const Quantum *) NULL);
3203 if (cache_info->metacontent_extent != 0)
3205 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3206 if (status == MagickFalse)
3207 return((const Quantum *) NULL);
3212 Pixel request is outside cache extents.
3215 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3216 virtual_nexus=AcquirePixelCacheNexus(1);
3217 if (virtual_nexus == (NexusInfo **) NULL)
3219 if (virtual_nexus != (NexusInfo **) NULL)
3220 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3221 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3222 "UnableToGetCacheNexus","`%s'",image->filename);
3223 return((const Quantum *) NULL);
3225 virtual_pixel=(Quantum *) NULL;
3226 virtual_associated_pixel=(void *) NULL;
3227 switch (virtual_pixel_method)
3229 case BackgroundVirtualPixelMethod:
3230 case BlackVirtualPixelMethod:
3231 case GrayVirtualPixelMethod:
3232 case TransparentVirtualPixelMethod:
3233 case MaskVirtualPixelMethod:
3234 case WhiteVirtualPixelMethod:
3235 case EdgeVirtualPixelMethod:
3236 case CheckerTileVirtualPixelMethod:
3237 case HorizontalTileVirtualPixelMethod:
3238 case VerticalTileVirtualPixelMethod:
3241 Acquire virtual pixel and associated channels.
3243 virtual_pixel=(Quantum *) AcquireQuantumMemory(
3244 cache_info->pixel_channels,sizeof(*virtual_pixel));
3245 if (virtual_pixel == (Quantum *) NULL)
3247 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3248 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3249 "UnableToGetCacheNexus","`%s'",image->filename);
3250 return((const Quantum *) NULL);
3252 (void) ResetMagickMemory(virtual_pixel,0,cache_info->pixel_channels*
3253 sizeof(*virtual_pixel));
3254 if (cache_info->metacontent_extent != 0)
3256 virtual_associated_pixel=(void *) AcquireMagickMemory(
3257 cache_info->metacontent_extent);
3258 if (virtual_associated_pixel == (void *) NULL)
3260 virtual_pixel=(Quantum *) RelinquishMagickMemory(
3262 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3263 (void) ThrowMagickException(exception,GetMagickModule(),
3264 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
3265 return((const Quantum *) NULL);
3267 (void) ResetMagickMemory(virtual_associated_pixel,0,
3268 cache_info->metacontent_extent);
3270 switch (virtual_pixel_method)
3272 case BlackVirtualPixelMethod:
3274 SetPixelRed(image,0,virtual_pixel);
3275 SetPixelGreen(image,0,virtual_pixel);
3276 SetPixelBlue(image,0,virtual_pixel);
3277 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3280 case GrayVirtualPixelMethod:
3282 SetPixelRed(image,QuantumRange/2,virtual_pixel);
3283 SetPixelGreen(image,QuantumRange/2,virtual_pixel);
3284 SetPixelBlue(image,QuantumRange/2,virtual_pixel);
3285 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3288 case TransparentVirtualPixelMethod:
3290 SetPixelRed(image,0,virtual_pixel);
3291 SetPixelGreen(image,0,virtual_pixel);
3292 SetPixelBlue(image,0,virtual_pixel);
3293 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3296 case MaskVirtualPixelMethod:
3297 case WhiteVirtualPixelMethod:
3299 SetPixelRed(image,(Quantum) QuantumRange,virtual_pixel);
3300 SetPixelGreen(image,(Quantum) QuantumRange,virtual_pixel);
3301 SetPixelBlue(image,(Quantum) QuantumRange,virtual_pixel);
3302 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3307 SetPixelRed(image,image->background_color.red,virtual_pixel);
3308 SetPixelGreen(image,image->background_color.green,virtual_pixel);
3309 SetPixelBlue(image,image->background_color.blue,virtual_pixel);
3310 SetPixelAlpha(image,image->background_color.alpha,virtual_pixel);
3319 for (v=0; v < (ssize_t) rows; v++)
3321 for (u=0; u < (ssize_t) columns; u+=length)
3323 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3324 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3325 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3333 Transfer a single pixel.
3335 length=(MagickSizeType) 1;
3336 switch (virtual_pixel_method)
3340 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3341 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3342 1UL,1UL,*virtual_nexus,exception);
3343 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3346 case RandomVirtualPixelMethod:
3348 if (cache_info->random_info == (RandomInfo *) NULL)
3349 cache_info->random_info=AcquireRandomInfo();
3350 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3351 RandomX(cache_info->random_info,cache_info->columns),
3352 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3353 *virtual_nexus,exception);
3354 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3357 case DitherVirtualPixelMethod:
3359 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3360 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3361 1UL,1UL,*virtual_nexus,exception);
3362 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3365 case TileVirtualPixelMethod:
3367 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3368 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3369 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3370 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3372 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3375 case MirrorVirtualPixelMethod:
3377 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3378 if ((x_modulo.quotient & 0x01) == 1L)
3379 x_modulo.remainder=(ssize_t) cache_info->columns-
3380 x_modulo.remainder-1L;
3381 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3382 if ((y_modulo.quotient & 0x01) == 1L)
3383 y_modulo.remainder=(ssize_t) cache_info->rows-
3384 y_modulo.remainder-1L;
3385 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3386 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3388 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3391 case HorizontalTileEdgeVirtualPixelMethod:
3393 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3394 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3395 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3396 *virtual_nexus,exception);
3397 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3400 case VerticalTileEdgeVirtualPixelMethod:
3402 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3403 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3404 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3405 *virtual_nexus,exception);
3406 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3409 case BackgroundVirtualPixelMethod:
3410 case BlackVirtualPixelMethod:
3411 case GrayVirtualPixelMethod:
3412 case TransparentVirtualPixelMethod:
3413 case MaskVirtualPixelMethod:
3414 case WhiteVirtualPixelMethod:
3417 r=virtual_associated_pixel;
3420 case EdgeVirtualPixelMethod:
3421 case CheckerTileVirtualPixelMethod:
3423 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3424 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3425 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3428 r=virtual_associated_pixel;
3431 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3432 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3434 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3437 case HorizontalTileVirtualPixelMethod:
3439 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3442 r=virtual_associated_pixel;
3445 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3446 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3447 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3448 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3450 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3453 case VerticalTileVirtualPixelMethod:
3455 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3458 r=virtual_associated_pixel;
3461 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3462 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3463 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3464 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3466 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3470 if (p == (const Quantum *) NULL)
3472 (void) memcpy(q,p,(size_t) length*cache_info->pixel_channels*
3474 q+=cache_info->pixel_channels;
3475 if ((s != (void *) NULL) &&
3476 (r != (const void *) NULL))
3478 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3479 s+=cache_info->metacontent_extent;
3484 Transfer a run of pixels.
3486 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3487 length,1UL,*virtual_nexus,exception);
3488 if (p == (const Quantum *) NULL)
3490 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3491 (void) memcpy(q,p,(size_t) length*cache_info->pixel_channels*sizeof(*p));
3492 q+=length*cache_info->pixel_channels;
3493 if ((s != (void *) NULL) && (r != (const void *) NULL))
3495 (void) memcpy(s,r,(size_t) length);
3496 s+=length*cache_info->metacontent_extent;
3503 if (virtual_associated_pixel != (void *) NULL)
3504 virtual_associated_pixel=(void *) RelinquishMagickMemory(
3505 virtual_associated_pixel);
3506 if (virtual_pixel != (Quantum *) NULL)
3507 virtual_pixel=(Quantum *) RelinquishMagickMemory(virtual_pixel);
3508 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3517 + G e t V i r t u a l P i x e l C a c h e %
3521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3523 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3524 % cache as defined by the geometry parameters. A pointer to the pixels
3525 % is returned if the pixels are transferred, otherwise a NULL is returned.
3527 % The format of the GetVirtualPixelCache() method is:
3529 % const Quantum *GetVirtualPixelCache(const Image *image,
3530 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3531 % const ssize_t y,const size_t columns,const size_t rows,
3532 % ExceptionInfo *exception)
3534 % A description of each parameter follows:
3536 % o image: the image.
3538 % o virtual_pixel_method: the virtual pixel method.
3540 % o x,y,columns,rows: These values define the perimeter of a region of
3543 % o exception: return any errors or warnings in this structure.
3546 static const Quantum *GetVirtualPixelCache(const Image *image,
3547 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3548 const size_t columns,const size_t rows,ExceptionInfo *exception)
3554 id = GetOpenMPThreadId();
3559 assert(image != (const Image *) NULL);
3560 assert(image->signature == MagickSignature);
3561 assert(image->cache != (Cache) NULL);
3562 cache_info=(CacheInfo *) image->cache;
3563 assert(cache_info->signature == MagickSignature);
3564 assert(id < (int) cache_info->number_threads);
3565 pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3566 cache_info->nexus_info[id],exception);
3571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3575 % G e t V i r t u a l P i x e l Q u e u e %
3579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3581 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3582 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3584 % The format of the GetVirtualPixelQueue() method is:
3586 % const Quantum *GetVirtualPixelQueue(const Image image)
3588 % A description of each parameter follows:
3590 % o image: the image.
3593 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3599 id = GetOpenMPThreadId();
3601 assert(image != (const Image *) NULL);
3602 assert(image->signature == MagickSignature);
3603 assert(image->cache != (Cache) NULL);
3604 cache_info=(CacheInfo *) image->cache;
3605 assert(cache_info->signature == MagickSignature);
3606 if (cache_info->methods.get_virtual_pixels_handler !=
3607 (GetVirtualPixelsHandler) NULL)
3608 return(cache_info->methods.get_virtual_pixels_handler(image));
3609 assert(id < (int) cache_info->number_threads);
3610 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3618 % G e t V i r t u a l P i x e l s %
3622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3624 % GetVirtualPixels() returns an immutable pixel region. If the
3625 % region is successfully accessed, a pointer to it is returned, otherwise
3626 % NULL is returned. The returned pointer may point to a temporary working
3627 % copy of the pixels or it may point to the original pixels in memory.
3628 % Performance is maximized if the selected region is part of one row, or one
3629 % or more full rows, since there is opportunity to access the pixels in-place
3630 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3631 % returned pointer must *never* be deallocated by the user.
3633 % Pixels accessed via the returned pointer represent a simple array of type
3634 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3635 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3636 % access the meta-content (of type void) corresponding to the the
3639 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3641 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3642 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3643 % GetCacheViewAuthenticPixels() instead.
3645 % The format of the GetVirtualPixels() method is:
3647 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3648 % const ssize_t y,const size_t columns,const size_t rows,
3649 % ExceptionInfo *exception)
3651 % A description of each parameter follows:
3653 % o image: the image.
3655 % o x,y,columns,rows: These values define the perimeter of a region of
3658 % o exception: return any errors or warnings in this structure.
3661 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3662 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3663 ExceptionInfo *exception)
3669 id = GetOpenMPThreadId();
3674 assert(image != (const Image *) NULL);
3675 assert(image->signature == MagickSignature);
3676 assert(image->cache != (Cache) NULL);
3677 cache_info=(CacheInfo *) image->cache;
3678 assert(cache_info->signature == MagickSignature);
3679 if (cache_info->methods.get_virtual_pixel_handler !=
3680 (GetVirtualPixelHandler) NULL)
3681 return(cache_info->methods.get_virtual_pixel_handler(image,
3682 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3683 assert(id < (int) cache_info->number_threads);
3684 pixels=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3685 columns,rows,cache_info->nexus_info[id],exception);
3690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3694 + 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 %
3698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3700 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3701 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3703 % The format of the GetVirtualPixelsCache() method is:
3705 % Quantum *GetVirtualPixelsCache(const Image *image)
3707 % A description of each parameter follows:
3709 % o image: the image.
3712 static const Quantum *GetVirtualPixelsCache(const Image *image)
3718 id = GetOpenMPThreadId();
3720 assert(image != (const Image *) NULL);
3721 assert(image->signature == MagickSignature);
3722 assert(image->cache != (Cache) NULL);
3723 cache_info=(CacheInfo *) image->cache;
3724 assert(cache_info->signature == MagickSignature);
3725 assert(id < (int) cache_info->number_threads);
3726 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3734 + G e t V i r t u a l P i x e l s N e x u s %
3738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3740 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3743 % The format of the GetVirtualPixelsNexus() method is:
3745 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3746 % NexusInfo *nexus_info)
3748 % A description of each parameter follows:
3750 % o cache: the pixel cache.
3752 % o nexus_info: the cache nexus to return the colormap pixels.
3755 MagickExport const Quantum *GetVirtualPixelsNexus(const Cache cache,
3756 NexusInfo *nexus_info)
3761 assert(cache != (Cache) NULL);
3762 cache_info=(CacheInfo *) cache;
3763 assert(cache_info->signature == MagickSignature);
3764 if (cache_info->storage_class == UndefinedClass)
3765 return((Quantum *) NULL);
3766 return((const Quantum *) nexus_info->pixels);
3770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3774 + M a s k P i x e l C a c h e N e x u s %
3778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3780 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3781 % The method returns MagickTrue if the pixel region is masked, otherwise
3784 % The format of the MaskPixelCacheNexus() method is:
3786 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3787 % NexusInfo *nexus_info,ExceptionInfo *exception)
3789 % A description of each parameter follows:
3791 % o image: the image.
3793 % o nexus_info: the cache nexus to clip.
3795 % o exception: return any errors or warnings in this structure.
3799 static inline void MagickPixelCompositeMask(const PixelInfo *p,
3800 const MagickRealType alpha,const PixelInfo *q,
3801 const MagickRealType beta,PixelInfo *composite)
3806 if (alpha == TransparentAlpha)
3811 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3812 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3813 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3814 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3815 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3816 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3817 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
3820 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3821 ExceptionInfo *exception)
3837 register const Quantum
3850 if (image->debug != MagickFalse)
3851 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3852 if (image->mask == (Image *) NULL)
3853 return(MagickFalse);
3854 cache_info=(CacheInfo *) image->cache;
3855 if (cache_info == (Cache) NULL)
3856 return(MagickFalse);
3857 image_nexus=AcquirePixelCacheNexus(1);
3858 clip_nexus=AcquirePixelCacheNexus(1);
3859 if ((image_nexus == (NexusInfo **) NULL) ||
3860 (clip_nexus == (NexusInfo **) NULL))
3861 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3862 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3863 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3864 nexus_info->region.height,image_nexus[0],exception);
3865 q=nexus_info->pixels;
3866 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3867 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3868 nexus_info->region.height,clip_nexus[0],&image->exception);
3869 GetPixelInfo(image,&alpha);
3870 GetPixelInfo(image,&beta);
3871 number_pixels=(MagickSizeType) nexus_info->region.width*
3872 nexus_info->region.height;
3873 for (i=0; i < (ssize_t) number_pixels; i++)
3875 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3877 SetPixelInfo(image,p,&alpha);
3878 SetPixelInfo(image,q,&beta);
3879 MagickPixelCompositeMask(&beta,(MagickRealType) GetPixelIntensity(image,r),
3880 &alpha,alpha.alpha,&beta);
3881 SetPixelRed(image,ClampToQuantum(beta.red),q);
3882 SetPixelGreen(image,ClampToQuantum(beta.green),q);
3883 SetPixelBlue(image,ClampToQuantum(beta.blue),q);
3884 if (cache_info->colorspace == CMYKColorspace)
3885 SetPixelBlack(image,ClampToQuantum(beta.black),q);
3886 SetPixelAlpha(image,ClampToQuantum(beta.alpha),q);
3891 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3892 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3893 if (i < (ssize_t) number_pixels)
3894 return(MagickFalse);
3899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3903 + O p e n P i x e l C a c h e %
3907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3909 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3910 % dimensions, allocating space for the image pixels and optionally the
3911 % metacontent, and memory mapping the cache if it is disk based. The cache
3912 % nexus array is initialized as well.
3914 % The format of the OpenPixelCache() method is:
3916 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3917 % ExceptionInfo *exception)
3919 % A description of each parameter follows:
3921 % o image: the image.
3923 % o mode: ReadMode, WriteMode, or IOMode.
3925 % o exception: return any errors or warnings in this structure.
3929 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3931 cache_info->mapped=MagickFalse;
3932 cache_info->pixels=(Quantum *) AcquireMagickMemory((size_t)
3933 cache_info->length);
3934 if (cache_info->pixels == (Quantum *) NULL)
3936 cache_info->mapped=MagickTrue;
3937 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3938 cache_info->length);
3942 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3952 cache_info=(CacheInfo *) image->cache;
3953 if (image->debug != MagickFalse)
3956 format[MaxTextExtent],
3957 message[MaxTextExtent];
3959 (void) FormatMagickSize(length,MagickFalse,format);
3960 (void) FormatLocaleString(message,MaxTextExtent,
3961 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3962 cache_info->cache_filename,cache_info->file,format);
3963 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3965 if (length != (MagickSizeType) ((MagickOffsetType) length))
3966 return(MagickFalse);
3967 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3969 return(MagickFalse);
3970 if ((MagickSizeType) extent >= length)
3972 offset=(MagickOffsetType) length-1;
3973 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3974 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3977 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3978 ExceptionInfo *exception)
3985 format[MaxTextExtent],
3986 message[MaxTextExtent];
3999 assert(image != (const Image *) NULL);
4000 assert(image->signature == MagickSignature);
4001 assert(image->cache != (Cache) NULL);
4002 if (image->debug != MagickFalse)
4003 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4004 if ((image->columns == 0) || (image->rows == 0))
4005 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
4006 DefinePixelComponentMap(image);
4007 cache_info=(CacheInfo *) image->cache;
4008 assert(cache_info->signature == MagickSignature);
4009 source_info=(*cache_info);
4010 source_info.file=(-1);
4011 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
4012 image->filename,(double) GetImageIndexInList(image));
4013 cache_info->storage_class=image->storage_class;
4014 cache_info->colorspace=image->colorspace;
4015 cache_info->mode=mode;
4016 cache_info->rows=image->rows;
4017 cache_info->columns=image->columns;
4018 cache_info->pixel_channels=GetPixelChannels(image);
4019 cache_info->metacontent_extent=image->metacontent_extent;
4020 if (image->ping != MagickFalse)
4022 cache_info->type=PingCache;
4023 cache_info->pixels=(Quantum *) NULL;
4024 cache_info->metacontent=(void *) NULL;
4025 cache_info->length=0;
4028 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4029 packet_size=cache_info->pixel_channels*sizeof(Quantum);
4030 if (image->metacontent_extent != 0)
4031 packet_size+=cache_info->metacontent_extent;
4032 length=number_pixels*packet_size;
4033 columns=(size_t) (length/cache_info->rows/packet_size);
4034 if (cache_info->columns != columns)
4035 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4037 cache_info->length=length;
4038 if ((cache_info->type != UndefinedCache) &&
4039 (cache_info->columns <= source_info.columns) &&
4040 (cache_info->rows <= source_info.rows) &&
4041 (cache_info->pixel_channels <= source_info.pixel_channels) &&
4042 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4045 Inline pixel cache clone optimization.
4047 if ((cache_info->columns == source_info.columns) &&
4048 (cache_info->rows == source_info.rows) &&
4049 (cache_info->pixel_channels == source_info.pixel_channels) &&
4050 (cache_info->metacontent_extent == source_info.metacontent_extent))
4052 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4054 status=AcquireMagickResource(AreaResource,cache_info->length);
4055 length=number_pixels*(cache_info->pixel_channels*sizeof(Quantum)+
4056 cache_info->metacontent_extent);
4057 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4059 status=AcquireMagickResource(MemoryResource,cache_info->length);
4060 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4061 (cache_info->type == MemoryCache))
4063 AllocatePixelCachePixels(cache_info);
4064 if (cache_info->pixels == (Quantum *) NULL)
4065 cache_info->pixels=source_info.pixels;
4069 Create memory pixel cache.
4072 if (image->debug != MagickFalse)
4074 (void) FormatMagickSize(cache_info->length,MagickTrue,
4076 (void) FormatLocaleString(message,MaxTextExtent,
4077 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4078 cache_info->filename,cache_info->mapped != MagickFalse ?
4079 "anonymous" : "heap",(double) cache_info->columns,(double)
4080 cache_info->rows,(double) cache_info->pixel_channels,
4082 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4085 cache_info->type=MemoryCache;
4086 cache_info->metacontent=(void *) NULL;
4087 if (cache_info->metacontent_extent != 0)
4088 cache_info->metacontent=(void *) (cache_info->pixels+
4089 number_pixels*cache_info->pixel_channels);
4090 if (source_info.storage_class != UndefinedClass)
4092 status=ClonePixelCachePixels(cache_info,&source_info,
4094 RelinquishPixelCachePixels(&source_info);
4099 RelinquishMagickResource(MemoryResource,cache_info->length);
4102 Create pixel cache on disk.
4104 status=AcquireMagickResource(DiskResource,cache_info->length);
4105 if (status == MagickFalse)
4107 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4108 "CacheResourcesExhausted","`%s'",image->filename);
4109 return(MagickFalse);
4111 if (cache_info->type == DiskCache)
4113 (void) ClosePixelCacheOnDisk(cache_info);
4114 *cache_info->cache_filename='\0';
4115 status=DiskToDiskPixelCacheClone(cache_info,&source_info,exception);
4117 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4119 RelinquishMagickResource(DiskResource,cache_info->length);
4120 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4122 return(MagickFalse);
4124 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4125 cache_info->length);
4126 if (status == MagickFalse)
4128 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4130 return(MagickFalse);
4132 length=number_pixels*(cache_info->pixel_channels*sizeof(Quantum)+
4133 cache_info->metacontent_extent);
4134 status=AcquireMagickResource(AreaResource,cache_info->length);
4135 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
4136 cache_info->type=DiskCache;
4139 status=AcquireMagickResource(MapResource,cache_info->length);
4140 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4141 (cache_info->type != MemoryCache))
4142 cache_info->type=DiskCache;
4145 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4146 cache_info->offset,(size_t) cache_info->length);
4147 if (cache_info->pixels == (Quantum *) NULL)
4149 cache_info->type=DiskCache;
4150 cache_info->pixels=source_info.pixels;
4155 Create file-backed memory-mapped pixel cache.
4158 (void) ClosePixelCacheOnDisk(cache_info);
4159 cache_info->type=MapCache;
4160 cache_info->mapped=MagickTrue;
4161 cache_info->metacontent=(void *) NULL;
4162 if (cache_info->metacontent_extent != 0)
4163 cache_info->metacontent=(void *) (cache_info->pixels+
4164 number_pixels*cache_info->pixel_channels);
4165 if (source_info.storage_class != UndefinedClass)
4167 status=ClonePixelCachePixels(cache_info,&source_info,
4169 RelinquishPixelCachePixels(&source_info);
4171 if (image->debug != MagickFalse)
4173 (void) FormatMagickSize(cache_info->length,MagickTrue,
4175 (void) FormatLocaleString(message,MaxTextExtent,
4176 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4177 cache_info->filename,cache_info->cache_filename,
4178 cache_info->file,(double) cache_info->columns,(double)
4179 cache_info->rows,(double) cache_info->pixel_channels,
4181 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4187 RelinquishMagickResource(MapResource,cache_info->length);
4190 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4192 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4193 RelinquishPixelCachePixels(&source_info);
4195 if (image->debug != MagickFalse)
4197 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4198 (void) FormatLocaleString(message,MaxTextExtent,
4199 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4200 cache_info->cache_filename,cache_info->file,(double)
4201 cache_info->columns,(double) cache_info->rows,(double)
4202 cache_info->pixel_channels,format);
4203 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4213 + P e r s i s t P i x e l C a c h e %
4217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4219 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4220 % persistent pixel cache is one that resides on disk and is not destroyed
4221 % when the program exits.
4223 % The format of the PersistPixelCache() method is:
4225 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4226 % const MagickBooleanType attach,MagickOffsetType *offset,
4227 % ExceptionInfo *exception)
4229 % A description of each parameter follows:
4231 % o image: the image.
4233 % o filename: the persistent pixel cache filename.
4235 % o attach: A value other than zero initializes the persistent pixel cache.
4237 % o initialize: A value other than zero initializes the persistent pixel
4240 % o offset: the offset in the persistent cache to store pixels.
4242 % o exception: return any errors or warnings in this structure.
4245 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4246 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4247 ExceptionInfo *exception)
4262 assert(image != (Image *) NULL);
4263 assert(image->signature == MagickSignature);
4264 if (image->debug != MagickFalse)
4265 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4266 assert(image->cache != (void *) NULL);
4267 assert(filename != (const char *) NULL);
4268 assert(offset != (MagickOffsetType *) NULL);
4269 page_size=GetMagickPageSize();
4270 cache_info=(CacheInfo *) image->cache;
4271 assert(cache_info->signature == MagickSignature);
4272 if (attach != MagickFalse)
4275 Attach existing persistent pixel cache.
4277 if (image->debug != MagickFalse)
4278 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4279 "attach persistent cache");
4280 (void) CopyMagickString(cache_info->cache_filename,filename,
4282 cache_info->type=DiskCache;
4283 cache_info->offset=(*offset);
4284 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4285 return(MagickFalse);
4286 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4289 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4290 (cache_info->reference_count == 1))
4292 LockSemaphoreInfo(cache_info->semaphore);
4293 if ((cache_info->mode != ReadMode) &&
4294 (cache_info->type != MemoryCache) &&
4295 (cache_info->reference_count == 1))
4301 Usurp existing persistent pixel cache.
4303 status=rename(cache_info->cache_filename,filename);
4306 (void) CopyMagickString(cache_info->cache_filename,filename,
4308 *offset+=cache_info->length+page_size-(cache_info->length %
4310 UnlockSemaphoreInfo(cache_info->semaphore);
4311 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4312 if (image->debug != MagickFalse)
4313 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4314 "Usurp resident persistent cache");
4318 UnlockSemaphoreInfo(cache_info->semaphore);
4321 Clone persistent pixel cache.
4323 clone_image=(*image);
4324 clone_info=(CacheInfo *) clone_image.cache;
4325 image->cache=ClonePixelCache(cache_info);
4326 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4327 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4328 cache_info->type=DiskCache;
4329 cache_info->offset=(*offset);
4330 cache_info=(CacheInfo *) image->cache;
4331 status=OpenPixelCache(image,IOMode,exception);
4332 if (status != MagickFalse)
4333 status=ClonePixelCachePixels(cache_info,clone_info,&image->exception);
4334 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4335 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4344 + Q u e u e A u t h e n t i c N e x u s %
4348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4350 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4351 % by the region rectangle and returns a pointer to the region. This region is
4352 % subsequently transferred from the pixel cache with
4353 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4354 % pixels are transferred, otherwise a NULL is returned.
4356 % The format of the QueueAuthenticNexus() method is:
4358 % Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4359 % const ssize_t y,const size_t columns,const size_t rows,
4360 % NexusInfo *nexus_info,ExceptionInfo *exception)
4362 % A description of each parameter follows:
4364 % o image: the image.
4366 % o x,y,columns,rows: These values define the perimeter of a region of
4369 % o nexus_info: the cache nexus to set.
4371 % o exception: return any errors or warnings in this structure.
4374 MagickExport Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4375 const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
4376 ExceptionInfo *exception)
4391 Validate pixel cache geometry.
4393 assert(image != (const Image *) NULL);
4394 assert(image->signature == MagickSignature);
4395 assert(image->cache != (Cache) NULL);
4396 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
4397 assert(cache_info->signature == MagickSignature);
4398 if (cache_info == (Cache) NULL)
4399 return((Quantum *) NULL);
4400 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4402 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4403 "NoPixelsDefinedInCache","`%s'",image->filename);
4404 return((Quantum *) NULL);
4406 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4407 (y >= (ssize_t) cache_info->rows))
4409 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4410 "PixelsAreNotAuthentic","`%s'",image->filename);
4411 return((Quantum *) NULL);
4413 offset=(MagickOffsetType) y*cache_info->columns+x;
4415 return((Quantum *) NULL);
4416 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4417 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4418 if ((MagickSizeType) offset >= number_pixels)
4419 return((Quantum *) NULL);
4425 region.width=columns;
4427 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4435 + 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 %
4439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4441 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4442 % defined by the region rectangle and returns a pointer to the region. This
4443 % region is subsequently transferred from the pixel cache with
4444 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4445 % pixels are transferred, otherwise a NULL is returned.
4447 % The format of the QueueAuthenticPixelsCache() method is:
4449 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4450 % const ssize_t y,const size_t columns,const size_t rows,
4451 % ExceptionInfo *exception)
4453 % A description of each parameter follows:
4455 % o image: the image.
4457 % o x,y,columns,rows: These values define the perimeter of a region of
4460 % o exception: return any errors or warnings in this structure.
4463 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4464 const ssize_t y,const size_t columns,const size_t rows,
4465 ExceptionInfo *exception)
4471 id = GetOpenMPThreadId();
4476 assert(image != (const Image *) NULL);
4477 assert(image->signature == MagickSignature);
4478 assert(image->cache != (Cache) NULL);
4479 cache_info=(CacheInfo *) image->cache;
4480 assert(cache_info->signature == MagickSignature);
4481 assert(id < (int) cache_info->number_threads);
4482 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4492 % Q u e u e A u t h e n t i c P i x e l s %
4496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4498 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4499 % successfully initialized a pointer to a Quantum array representing the
4500 % region is returned, otherwise NULL is returned. The returned pointer may
4501 % point to a temporary working buffer for the pixels or it may point to the
4502 % final location of the pixels in memory.
4504 % Write-only access means that any existing pixel values corresponding to
4505 % the region are ignored. This is useful if the initial image is being
4506 % created from scratch, or if the existing pixel values are to be
4507 % completely replaced without need to refer to their pre-existing values.
4508 % The application is free to read and write the pixel buffer returned by
4509 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4510 % initialize the pixel array values. Initializing pixel array values is the
4511 % application's responsibility.
4513 % Performance is maximized if the selected region is part of one row, or
4514 % one or more full rows, since then there is opportunity to access the
4515 % pixels in-place (without a copy) if the image is in memory, or in a
4516 % memory-mapped file. The returned pointer must *never* be deallocated
4519 % Pixels accessed via the returned pointer represent a simple array of type
4520 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4521 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4522 % obtain the meta-content (of type void) corresponding to the region.
4523 % Once the Quantum (and/or Quantum) array has been updated, the
4524 % changes must be saved back to the underlying image using
4525 % SyncAuthenticPixels() or they may be lost.
4527 % The format of the QueueAuthenticPixels() method is:
4529 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4530 % const ssize_t y,const size_t columns,const size_t rows,
4531 % ExceptionInfo *exception)
4533 % A description of each parameter follows:
4535 % o image: the image.
4537 % o x,y,columns,rows: These values define the perimeter of a region of
4540 % o exception: return any errors or warnings in this structure.
4543 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4544 const ssize_t y,const size_t columns,const size_t rows,
4545 ExceptionInfo *exception)
4551 id = GetOpenMPThreadId();
4556 assert(image != (Image *) NULL);
4557 assert(image->signature == MagickSignature);
4558 assert(image->cache != (Cache) NULL);
4559 cache_info=(CacheInfo *) image->cache;
4560 assert(cache_info->signature == MagickSignature);
4561 if (cache_info->methods.queue_authentic_pixels_handler !=
4562 (QueueAuthenticPixelsHandler) NULL)
4564 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4565 columns,rows,exception);
4568 assert(id < (int) cache_info->number_threads);
4569 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4579 + 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 %
4583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4585 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4588 % The format of the ReadPixelCacheMetacontent() method is:
4590 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4591 % NexusInfo *nexus_info,ExceptionInfo *exception)
4593 % A description of each parameter follows:
4595 % o cache_info: the pixel cache.
4597 % o nexus_info: the cache nexus to read the metacontent.
4599 % o exception: return any errors or warnings in this structure.
4602 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4603 NexusInfo *nexus_info,ExceptionInfo *exception)
4616 register unsigned char
4622 if (cache_info->metacontent_extent == 0)
4623 return(MagickFalse);
4624 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4626 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4627 nexus_info->region.x;
4628 length=(MagickSizeType) nexus_info->region.width*
4629 cache_info->metacontent_extent;
4630 rows=nexus_info->region.height;
4632 q=(unsigned char *) nexus_info->metacontent;
4633 switch (cache_info->type)
4638 register unsigned char
4642 Read meta-content from memory.
4644 if ((cache_info->columns == nexus_info->region.width) &&
4645 (extent == (MagickSizeType) ((size_t) extent)))
4650 p=(unsigned char *) cache_info->metacontent+offset*
4651 cache_info->metacontent_extent;
4652 for (y=0; y < (ssize_t) rows; y++)
4654 (void) memcpy(q,p,(size_t) length);
4655 p+=cache_info->metacontent_extent*cache_info->columns;
4656 q+=cache_info->metacontent_extent*nexus_info->region.width;
4663 Read meta content from disk.
4665 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4667 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4668 cache_info->cache_filename);
4669 return(MagickFalse);
4671 if ((cache_info->columns == nexus_info->region.width) &&
4672 (extent <= MagickMaxBufferExtent))
4677 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4678 for (y=0; y < (ssize_t) rows; y++)
4680 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4681 cache_info->pixel_channels*sizeof(Quantum)+offset*
4682 cache_info->metacontent_extent,length,(unsigned char *) q);
4683 if ((MagickSizeType) count != length)
4685 offset+=cache_info->columns;
4686 q+=cache_info->metacontent_extent*nexus_info->region.width;
4688 if (y < (ssize_t) rows)
4690 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4691 cache_info->cache_filename);
4692 return(MagickFalse);
4699 if ((cache_info->debug != MagickFalse) &&
4700 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4701 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4702 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4703 nexus_info->region.width,(double) nexus_info->region.height,(double)
4704 nexus_info->region.x,(double) nexus_info->region.y);
4709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4713 + R e a d P i x e l C a c h e P i x e l s %
4717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4719 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4722 % The format of the ReadPixelCachePixels() method is:
4724 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4725 % NexusInfo *nexus_info,ExceptionInfo *exception)
4727 % A description of each parameter follows:
4729 % o cache_info: the pixel cache.
4731 % o nexus_info: the cache nexus to read the pixels.
4733 % o exception: return any errors or warnings in this structure.
4736 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4737 NexusInfo *nexus_info,ExceptionInfo *exception)
4756 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4758 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4759 nexus_info->region.x;
4760 length=(MagickSizeType) nexus_info->region.width*cache_info->pixel_channels*
4762 rows=nexus_info->region.height;
4764 q=nexus_info->pixels;
4765 switch (cache_info->type)
4774 Read pixels from memory.
4776 if ((cache_info->columns == nexus_info->region.width) &&
4777 (extent == (MagickSizeType) ((size_t) extent)))
4782 p=cache_info->pixels+offset*cache_info->pixel_channels;
4783 for (y=0; y < (ssize_t) rows; y++)
4785 (void) memcpy(q,p,(size_t) length);
4786 p+=cache_info->pixel_channels*cache_info->columns;
4787 q+=cache_info->pixel_channels*nexus_info->region.width;
4794 Read pixels from disk.
4796 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4798 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4799 cache_info->cache_filename);
4800 return(MagickFalse);
4802 if ((cache_info->columns == nexus_info->region.width) &&
4803 (extent <= MagickMaxBufferExtent))
4808 for (y=0; y < (ssize_t) rows; y++)
4810 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4811 cache_info->pixel_channels*sizeof(*q),length,(unsigned char *) q);
4812 if ((MagickSizeType) count != length)
4814 offset+=cache_info->columns;
4815 q+=cache_info->pixel_channels*nexus_info->region.width;
4817 if (y < (ssize_t) rows)
4819 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4820 cache_info->cache_filename);
4821 return(MagickFalse);
4828 if ((cache_info->debug != MagickFalse) &&
4829 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4830 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4831 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4832 nexus_info->region.width,(double) nexus_info->region.height,(double)
4833 nexus_info->region.x,(double) nexus_info->region.y);
4838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4842 + R e f e r e n c e P i x e l C a c h e %
4846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4848 % ReferencePixelCache() increments the reference count associated with the
4849 % pixel cache returning a pointer to the cache.
4851 % The format of the ReferencePixelCache method is:
4853 % Cache ReferencePixelCache(Cache cache_info)
4855 % A description of each parameter follows:
4857 % o cache_info: the pixel cache.
4860 MagickExport Cache ReferencePixelCache(Cache cache)
4865 assert(cache != (Cache *) NULL);
4866 cache_info=(CacheInfo *) cache;
4867 assert(cache_info->signature == MagickSignature);
4868 LockSemaphoreInfo(cache_info->semaphore);
4869 cache_info->reference_count++;
4870 UnlockSemaphoreInfo(cache_info->semaphore);
4875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4879 + S e t P i x e l C a c h e M e t h o d s %
4883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4885 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4887 % The format of the SetPixelCacheMethods() method is:
4889 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4891 % A description of each parameter follows:
4893 % o cache: the pixel cache.
4895 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4898 MagickExport void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4903 GetOneAuthenticPixelFromHandler
4904 get_one_authentic_pixel_from_handler;
4906 GetOneVirtualPixelFromHandler
4907 get_one_virtual_pixel_from_handler;
4910 Set cache pixel methods.
4912 assert(cache != (Cache) NULL);
4913 assert(cache_methods != (CacheMethods *) NULL);
4914 cache_info=(CacheInfo *) cache;
4915 assert(cache_info->signature == MagickSignature);
4916 if (cache_info->debug != MagickFalse)
4917 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4918 cache_info->filename);
4919 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4920 cache_info->methods.get_virtual_pixel_handler=
4921 cache_methods->get_virtual_pixel_handler;
4922 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4923 cache_info->methods.destroy_pixel_handler=
4924 cache_methods->destroy_pixel_handler;
4925 if (cache_methods->get_virtual_metacontent_from_handler !=
4926 (GetVirtualMetacontentFromHandler) NULL)
4927 cache_info->methods.get_virtual_metacontent_from_handler=
4928 cache_methods->get_virtual_metacontent_from_handler;
4929 if (cache_methods->get_authentic_pixels_handler !=
4930 (GetAuthenticPixelsHandler) NULL)
4931 cache_info->methods.get_authentic_pixels_handler=
4932 cache_methods->get_authentic_pixels_handler;
4933 if (cache_methods->queue_authentic_pixels_handler !=
4934 (QueueAuthenticPixelsHandler) NULL)
4935 cache_info->methods.queue_authentic_pixels_handler=
4936 cache_methods->queue_authentic_pixels_handler;
4937 if (cache_methods->sync_authentic_pixels_handler !=
4938 (SyncAuthenticPixelsHandler) NULL)
4939 cache_info->methods.sync_authentic_pixels_handler=
4940 cache_methods->sync_authentic_pixels_handler;
4941 if (cache_methods->get_authentic_pixels_from_handler !=
4942 (GetAuthenticPixelsFromHandler) NULL)
4943 cache_info->methods.get_authentic_pixels_from_handler=
4944 cache_methods->get_authentic_pixels_from_handler;
4945 if (cache_methods->get_authentic_metacontent_from_handler !=
4946 (GetAuthenticMetacontentFromHandler) NULL)
4947 cache_info->methods.get_authentic_metacontent_from_handler=
4948 cache_methods->get_authentic_metacontent_from_handler;
4949 get_one_virtual_pixel_from_handler=
4950 cache_info->methods.get_one_virtual_pixel_from_handler;
4951 if (get_one_virtual_pixel_from_handler !=
4952 (GetOneVirtualPixelFromHandler) NULL)
4953 cache_info->methods.get_one_virtual_pixel_from_handler=
4954 cache_methods->get_one_virtual_pixel_from_handler;
4955 get_one_authentic_pixel_from_handler=
4956 cache_methods->get_one_authentic_pixel_from_handler;
4957 if (get_one_authentic_pixel_from_handler !=
4958 (GetOneAuthenticPixelFromHandler) NULL)
4959 cache_info->methods.get_one_authentic_pixel_from_handler=
4960 cache_methods->get_one_authentic_pixel_from_handler;
4964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4968 + S e t P i x e l C a c h e N e x u s P i x e l s %
4972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4974 % SetPixelCacheNexusPixels() defines the region of the cache for the
4975 % specified cache nexus.
4977 % The format of the SetPixelCacheNexusPixels() method is:
4979 % Quantum SetPixelCacheNexusPixels(const Image *image,
4980 % const RectangleInfo *region,NexusInfo *nexus_info,
4981 % ExceptionInfo *exception)
4983 % A description of each parameter follows:
4985 % o image: the image.
4987 % o region: A pointer to the RectangleInfo structure that defines the
4988 % region of this particular cache nexus.
4990 % o nexus_info: the cache nexus to set.
4992 % o exception: return any errors or warnings in this structure.
4996 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
4997 NexusInfo *nexus_info,ExceptionInfo *exception)
4999 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
5000 return(MagickFalse);
5001 nexus_info->mapped=MagickFalse;
5002 nexus_info->cache=(Quantum *) AcquireMagickMemory((size_t)
5003 nexus_info->length);
5004 if (nexus_info->cache == (Quantum *) NULL)
5006 nexus_info->mapped=MagickTrue;
5007 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
5008 nexus_info->length);
5010 if (nexus_info->cache == (Quantum *) NULL)
5012 (void) ThrowMagickException(exception,GetMagickModule(),
5013 ResourceLimitError,"MemoryAllocationFailed","`%s'",
5014 cache_info->filename);
5015 return(MagickFalse);
5020 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5021 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5033 cache_info=(CacheInfo *) image->cache;
5034 assert(cache_info->signature == MagickSignature);
5035 if (cache_info->type == UndefinedCache)
5036 return((Quantum *) NULL);
5037 nexus_info->region=(*region);
5038 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5039 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5045 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5046 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5047 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5048 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5049 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5050 ((nexus_info->region.width == cache_info->columns) ||
5051 ((nexus_info->region.width % cache_info->columns) == 0)))))
5057 Pixels are accessed directly from memory.
5059 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5060 nexus_info->region.x;
5061 nexus_info->pixels=cache_info->pixels+cache_info->pixel_channels*
5063 nexus_info->metacontent=(void *) NULL;
5064 if (cache_info->metacontent_extent != 0)
5065 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5066 offset*cache_info->metacontent_extent;
5067 return(nexus_info->pixels);
5071 Pixels are stored in a cache region until they are synced to the cache.
5073 number_pixels=(MagickSizeType) nexus_info->region.width*
5074 nexus_info->region.height;
5075 length=number_pixels*cache_info->pixel_channels*sizeof(Quantum);
5076 if (cache_info->metacontent_extent != 0)
5077 length+=number_pixels*cache_info->metacontent_extent;
5078 if (nexus_info->cache == (Quantum *) NULL)
5080 nexus_info->length=length;
5081 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5082 if (status == MagickFalse)
5084 nexus_info->length=0;
5085 return((Quantum *) NULL);
5089 if (nexus_info->length != length)
5091 RelinquishCacheNexusPixels(nexus_info);
5092 nexus_info->length=length;
5093 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5094 if (status == MagickFalse)
5096 nexus_info->length=0;
5097 return((Quantum *) NULL);
5100 nexus_info->pixels=nexus_info->cache;
5101 nexus_info->metacontent=(void *) NULL;
5102 if (cache_info->metacontent_extent != 0)
5103 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5104 cache_info->pixel_channels);
5105 return(nexus_info->pixels);
5109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5113 % 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 %
5117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5119 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5120 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5121 % access that is outside the boundaries of the image cache.
5123 % The format of the SetPixelCacheVirtualMethod() method is:
5125 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5126 % const VirtualPixelMethod virtual_pixel_method)
5128 % A description of each parameter follows:
5130 % o image: the image.
5132 % o virtual_pixel_method: choose the type of virtual pixel.
5135 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5136 const VirtualPixelMethod virtual_pixel_method)
5144 assert(image != (Image *) NULL);
5145 assert(image->signature == MagickSignature);
5146 if (image->debug != MagickFalse)
5147 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5148 assert(image->cache != (Cache) NULL);
5149 cache_info=(CacheInfo *) image->cache;
5150 assert(cache_info->signature == MagickSignature);
5151 method=cache_info->virtual_pixel_method;
5152 cache_info->virtual_pixel_method=virtual_pixel_method;
5157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5161 + 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 %
5165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5167 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5168 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5169 % is synced, otherwise MagickFalse.
5171 % The format of the SyncAuthenticPixelCacheNexus() method is:
5173 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5174 % NexusInfo *nexus_info,ExceptionInfo *exception)
5176 % A description of each parameter follows:
5178 % o image: the image.
5180 % o nexus_info: the cache nexus to sync.
5182 % o exception: return any errors or warnings in this structure.
5185 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5186 NexusInfo *nexus_info,ExceptionInfo *exception)
5195 Transfer pixels to the cache.
5197 assert(image != (Image *) NULL);
5198 assert(image->signature == MagickSignature);
5199 if (image->cache == (Cache) NULL)
5200 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5201 cache_info=(CacheInfo *) image->cache;
5202 assert(cache_info->signature == MagickSignature);
5203 if (cache_info->type == UndefinedCache)
5204 return(MagickFalse);
5205 if ((image->clip_mask != (Image *) NULL) &&
5206 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5207 return(MagickFalse);
5208 if ((image->mask != (Image *) NULL) &&
5209 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5210 return(MagickFalse);
5211 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5213 assert(cache_info->signature == MagickSignature);
5214 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5215 if ((cache_info->metacontent_extent != 0) &&
5216 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5217 return(MagickFalse);
5222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5226 + S y n c A u t h e n t i c P i x e l C a c h e %
5230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5232 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5233 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5234 % otherwise MagickFalse.
5236 % The format of the SyncAuthenticPixelsCache() method is:
5238 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5239 % ExceptionInfo *exception)
5241 % A description of each parameter follows:
5243 % o image: the image.
5245 % o exception: return any errors or warnings in this structure.
5248 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5249 ExceptionInfo *exception)
5255 id = GetOpenMPThreadId();
5260 assert(image != (Image *) NULL);
5261 assert(image->signature == MagickSignature);
5262 assert(image->cache != (Cache) NULL);
5263 cache_info=(CacheInfo *) image->cache;
5264 assert(cache_info->signature == MagickSignature);
5265 assert(id < (int) cache_info->number_threads);
5266 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5276 % S y n c A u t h e n t i c P i x e l s %
5280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5282 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5283 % The method returns MagickTrue if the pixel region is flushed, otherwise
5286 % The format of the SyncAuthenticPixels() method is:
5288 % MagickBooleanType SyncAuthenticPixels(Image *image,
5289 % ExceptionInfo *exception)
5291 % A description of each parameter follows:
5293 % o image: the image.
5295 % o exception: return any errors or warnings in this structure.
5298 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5299 ExceptionInfo *exception)
5305 id = GetOpenMPThreadId();
5310 assert(image != (Image *) NULL);
5311 assert(image->signature == MagickSignature);
5312 assert(image->cache != (Cache) NULL);
5313 cache_info=(CacheInfo *) image->cache;
5314 assert(cache_info->signature == MagickSignature);
5315 if (cache_info->methods.sync_authentic_pixels_handler !=
5316 (SyncAuthenticPixelsHandler) NULL)
5318 status=cache_info->methods.sync_authentic_pixels_handler(image,
5322 assert(id < (int) cache_info->number_threads);
5323 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5333 + 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 %
5337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5339 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5340 % of the pixel cache.
5342 % The format of the WritePixelCacheMetacontent() method is:
5344 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5345 % NexusInfo *nexus_info,ExceptionInfo *exception)
5347 % A description of each parameter follows:
5349 % o cache_info: the pixel cache.
5351 % o nexus_info: the cache nexus to write the meta-content.
5353 % o exception: return any errors or warnings in this structure.
5356 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5357 NexusInfo *nexus_info,ExceptionInfo *exception)
5367 register const unsigned char
5376 if (cache_info->metacontent_extent == 0)
5377 return(MagickFalse);
5378 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5380 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5381 nexus_info->region.x;
5382 length=(MagickSizeType) nexus_info->region.width*
5383 cache_info->metacontent_extent;
5384 rows=nexus_info->region.height;
5385 extent=(MagickSizeType) length*rows;
5386 p=(unsigned char *) nexus_info->metacontent;
5387 switch (cache_info->type)
5392 register unsigned char
5396 Write associated pixels to memory.
5398 if ((cache_info->columns == nexus_info->region.width) &&
5399 (extent == (MagickSizeType) ((size_t) extent)))
5404 q=(unsigned char *) cache_info->metacontent+offset*
5405 cache_info->metacontent_extent;
5406 for (y=0; y < (ssize_t) rows; y++)
5408 (void) memcpy(q,p,(size_t) length);
5409 p+=nexus_info->region.width*cache_info->metacontent_extent;
5410 q+=cache_info->columns*cache_info->metacontent_extent;
5417 Write associated pixels to disk.
5419 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5421 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5422 cache_info->cache_filename);
5423 return(MagickFalse);
5425 if ((cache_info->columns == nexus_info->region.width) &&
5426 (extent <= MagickMaxBufferExtent))
5431 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5432 for (y=0; y < (ssize_t) rows; y++)
5434 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5435 cache_info->pixel_channels*sizeof(Quantum)+offset*
5436 cache_info->metacontent_extent,length,(const unsigned char *) p);
5437 if ((MagickSizeType) count != length)
5439 p+=nexus_info->region.width*cache_info->metacontent_extent;
5440 offset+=cache_info->columns;
5442 if (y < (ssize_t) rows)
5444 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5445 cache_info->cache_filename);
5446 return(MagickFalse);
5453 if ((cache_info->debug != MagickFalse) &&
5454 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5455 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5456 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5457 nexus_info->region.width,(double) nexus_info->region.height,(double)
5458 nexus_info->region.x,(double) nexus_info->region.y);
5463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5467 + W r i t e C a c h e P i x e l s %
5471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5473 % WritePixelCachePixels() writes image pixels to the specified region of the
5476 % The format of the WritePixelCachePixels() method is:
5478 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5479 % NexusInfo *nexus_info,ExceptionInfo *exception)
5481 % A description of each parameter follows:
5483 % o cache_info: the pixel cache.
5485 % o nexus_info: the cache nexus to write the pixels.
5487 % o exception: return any errors or warnings in this structure.
5490 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5491 NexusInfo *nexus_info,ExceptionInfo *exception)
5501 register const Quantum
5510 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5512 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5513 nexus_info->region.x;
5514 length=(MagickSizeType) nexus_info->region.width*cache_info->pixel_channels*
5516 rows=nexus_info->region.height;
5518 p=nexus_info->pixels;
5519 switch (cache_info->type)
5528 Write pixels to memory.
5530 if ((cache_info->columns == nexus_info->region.width) &&
5531 (extent == (MagickSizeType) ((size_t) extent)))
5536 q=cache_info->pixels+offset*cache_info->pixel_channels;
5537 for (y=0; y < (ssize_t) rows; y++)
5539 (void) memcpy(q,p,(size_t) length);
5540 p+=nexus_info->region.width*cache_info->pixel_channels;
5541 q+=cache_info->columns*cache_info->pixel_channels;
5548 Write pixels to disk.
5550 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5552 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5553 cache_info->cache_filename);
5554 return(MagickFalse);
5556 if ((cache_info->columns == nexus_info->region.width) &&
5557 (extent <= MagickMaxBufferExtent))
5562 for (y=0; y < (ssize_t) rows; y++)
5564 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5565 cache_info->pixel_channels*sizeof(*p),length,(const unsigned char *)
5567 if ((MagickSizeType) count != length)
5569 p+=nexus_info->region.width*cache_info->pixel_channels;
5570 offset+=cache_info->columns;
5572 if (y < (ssize_t) rows)
5574 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5575 cache_info->cache_filename);
5576 return(MagickFalse);
5583 if ((cache_info->debug != MagickFalse) &&
5584 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5585 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5586 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5587 nexus_info->region.width,(double) nexus_info->region.height,(double)
5588 nexus_info->region.x,(double) nexus_info->region.y);